zoukankan      html  css  js  c++  java
  • React井字棋改进需求实现

    前言:

    在线demo

    这篇文章并不是React教程。

    主流前端框架:Vue, React, Angular,工作这两年用过一次Ag,其它都在使用Vue,只有React接触的实在是少。今天下班之余打开 React官网 想轻过一遍教程,看过教程的都知道上面提供了一个井字棋游戏实现的教程,官网那里也写的超级详细,我就不再说了,我想实现的是教程末尾的改进:



    我想完成的就是把官网教程末,改进游戏的想法在前面的基础上进行实现。

    搭建本地开发环境

    1. 我本地是有安装了较新版本的 Node.js。
    2. 使用cmd运行npx create-react-app my-app命令,官方脚手架创建一个叫my-app的React项目
    3. 安装完成 使用yarn start跑起这个项目
      然后跟着教程走一遍,我这里略过......,
      到这,你就已经完成官方提供的教程例子。我开始往下:
    需求1:在游戏历史记录列表显示每一步棋的坐标,格式为 (列号, 行号)。

    简单分析:
    完成前面内容的都知道九个格子是可以用0-8作为下标index的,那这个需求就简单了,只要把下标简单换成横纵坐标,比如const arr = [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3]]这样一个数组取arr[index]就可以拿到横纵坐标,我用rederContent()实现了一个落子详情



    代码:

    rederContent() {
        const positionArr = this.state.positionArr
        if (positionArr.length === 0) {
          // 还未落子
          return ''
        }
        else {
          const arr = [[1, 1], [1, 2], [1, 3],
          [2, 1], [2, 2], [2, 3],
          [3, 1], [3, 2], [3, 3]]
    
          const content = positionArr.map((item, index) => {
            if (index >= this.state.stepNumber) {
              // 这是返回到某一历史步骤会出现positionArr长度大于stepNumber
              return
            }
            let position = arr[item]
            const text = `第${index + 1}步:   ${index % 2 === 0 ? 'X' : 'O'}`
            const text1 = `落子第${position[0]}行,第${position[1]}列`
            return (
              <div key={index}>
                <span className='content-span'>{text}</span>
                <span>{text1}</span>
              </div>
            );
          });
          return content
        }
      }
    
    需求2:在历史记录列表中加粗显示当前选择的项目。

    这个也很快,当前有存一个stepNumber,那和对应的步骤找到关系,相等时去增加区分的样式
    className={move === this.state.stepNumber ? 'moveClick' : ''

    需求3:使用两个循环来渲染出棋盘的格子,而不是在代码里写死(hardcode)

    分析一下:原来写死,那我想实现一个方法renderContent(x,y)接收两个参数,x代表行,y代表列数

    // 渲染行数
      renderContent(x, y) {
        let content = []
        for (let i = 0; i < x; i++) {
          content.push(
            <div className="board-row" key={i}>{this.renderRow(i, y)}</div>
          )
        }
        return content
      }
      // 渲染行内容
      renderRow(x, y) {
        let content = []
        for (let i = 0; i < y; i++) {
          let num = x * 3 + i
          content.push(
            this.renderSquare(num)
          )
        }
        return content
      }
    

    这样你想渲染几行几列的表格都是由你来决定了

    需求4:添加一个可以升序或降序显示历史记录的按钮

    这个就是要让实现一个上一步,下一步的功能咯

     jumpToNext(v) {
        let num = this.state.stepNumber
        if (v) {
        // v 有值 执行下一步的操作
          if (num === this.state.history.length - 1) {
            alert('当前是最后一步')
          } else {
            this.setState({
              stepNumber: num + 1,
              xIsNext: ((num + 1) % 2) === 0
            })
          }
        } else {
        //  执行上一步的操作
          if (num === 0) {
            alert('当前是第一步')
          } else {
            this.setState({
              stepNumber: num - 1,
              xIsNext: ((num - 1) % 2) === 0
            })
          }
        }
      }
    

    如代码所示,根据当前步骤,所在位置,首末的时候做个判断。

    需求5:每当有人获胜时,高亮显示连成一线的 3 颗棋子

    分析:取到胜利时的三子坐标,之前有个方法是用来判断是否三子连线,我做了修改,加个参数flag,true的时候让其返回对应的三子坐标,再把对应坐标的棋子加个样式

      calculateWinner(squares, flag = false) {
        const lines = [
          [0, 1, 2],
          [3, 4, 5],
          [6, 7, 8],
          [0, 3, 6],
          [1, 4, 7],
          [2, 5, 8],
          [0, 4, 8],
          [2, 4, 6],
        ];
        for (let i = 0; i < lines.length; i++) {
          const [a, b, c] = lines[i];
          if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
            if (flag) {
              return [a, b, c]
            } else { return squares[a]; }
    
          }
        }
        return null;
      }
    

    效果:

    需求6:当无人获胜时,显示一个平局的消息

    当无子可下的时候,加个平局提醒,当没出现胜利者,而步数为9则是平局

     if (winner) {
          status = "Winner: " + winner;
        } else if (this.state.stepNumber === 9) {
          status = '游戏结束!双方平局!'
        } else {
          status = "Next player: " + (this.state.xIsNext ? "X" : "O");
        }
    

    小结:

    我只是按自己想法去实现对应需求,实现这些需求的方法可以是多样变化的,代码永远没有唯一,这里我附上 完整代码的地址,感兴趣的可以打开查看。当然咯,这篇文章并不是React教程。

  • 相关阅读:
    C#自己写的迭代器(拓展字典)
    C#中的浅复制和深复制
    C#中的委托和事件
    转载--《怎样制作一款优秀的塔防游戏》
    3D数学基础
    MonoBehaviour可重写的函数
    悲观锁及乐观锁
    java nio
    hadoop2.x通过Zookeeper来实现namenode的HA方案集群搭建-实践版
    oozie bundle学习笔记
  • 原文地址:https://www.cnblogs.com/wangxiaoer5200/p/13961002.html
Copyright © 2011-2022 走看看