React官网入门项目井字棋游戏

        React官网里有很详细的教程 ,也有在线沙盒,但是写的东一榔头西一棒槌的,不适合新手入门,所以我还是建议大家可以先去看看阮一峰大神的React博客或者某硅谷的网课,这个网课讲的很详细,甚至详细到有些啰嗦,我大概是用20天把网课看完,然后再看的官方文档,把这个小游戏做一下,我这里是采用在本地完成这个项目。

游戏预览:

准备工作:

npx create-react-app my-app
  • 删除掉新项目中 src/ 文件夹下的所有文件。

注意:

不要删除整个 src 文件夹,删除里面的源文件。我们会在接下来的步骤中使用示例代码替换默认源文件。

       

  1. 在 src/ 文件夹中创建一个名为 index.css 的文件,并拷贝
    body {
      font: 14px "Century Gothic", Futura, sans-serif;
      margin: 20px;
    }
    
    ol,
    ul {
      padding-left: 30px;
    }
    
    .board-row:after {
      clear: both;
      content: "";
      display: table;
    }
    
    .status {
      margin-bottom: 10px;
    }
    
    .square {
      background: #fff;
      border: 1px solid #999;
      float: left;
      font-size: 24px;
      font-weight: bold;
      line-height: 34px;
      height: 34px;
      margin-right: -1px;
      margin-top: -1px;
      padding: 0;
      text-align: center;
      width: 34px;
    }
    
    .square:focus {
      outline: none;
    }
    
    .kbd-navigation .square:focus {
      background: #ddd;
    }
    
    .game {
      display: flex;
      flex-direction: row;
    }
    
    .game-info {
      margin-left: 20px;
    }
    
  2. 在 src/ 文件夹下创建一个名为 index.js 的文件,并拷贝
    import React from "react";
    import ReactDOM from "react-dom";
    import "./index.css";
    
    //每个小方块组件 点击显示棋子
    function Square(props) {
      return (
        <button className="square" onClick={props.onClick}>
          {props.value}
        </button>
      );
    }
    //大方块组件
    class Board extends React.Component {
      renderSquare(i) {
        return (
          <Square
            value={this.props.squares[i]}
            onClick={() => this.props.onClick(i)}
          />
        );
      }
    
      render() {
        return (
          <div>
            <div className="board-row">
              {this.renderSquare(0)}
              {this.renderSquare(1)}
              {this.renderSquare(2)}
            </div>
            <div className="board-row">
              {this.renderSquare(3)}
              {this.renderSquare(4)}
              {this.renderSquare(5)}
            </div>
            <div className="board-row">
              {this.renderSquare(6)}
              {this.renderSquare(7)}
              {this.renderSquare(8)}
            </div>
          </div>
        );
      }
    }
    
    //整个游戏组件
    class Game extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          //初始化历史记录 棋盘上都是空的
          history: [
            {
              squares: Array(9).fill(null),
            },
          ],
          stepNumber: 0, //游戏最开始步数为0
          xIsNext: true, //判断下一个落子是O还是X
        };
      }
    
      handleClick(i) {
        const history = this.state.history.slice(0, this.state.stepNumber + 1);
        //使当前落子始终是最新落子
        const current = history[history.length - 1];
        const squares = current.squares.slice();
        //当有玩家胜出时,或者某个 Square 已经被填充时该函数不做任何处理直接返回
        if (calculateWinner(squares) || squares[i]) {
          return;
        }
        squares[i] = this.state.xIsNext ? "X" : "O";
        this.setState({
          //将新的落子情况加到历史记录数组中
          history: history.concat([
            {
              squares: squares,
            },
          ]),
          stepNumber: history.length,
          xIsNext: !this.state.xIsNext,
        });
      }
      //跳转
      jumpTo(step) {
        this.setState({
          stepNumber: step,
          xIsNext: step % 2 === 0,
        });
      }
    
      render() {
        const history = this.state.history;
        const current = history[this.state.stepNumber];
        const winner = calculateWinner(current.squares);
        //map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值
        const moves = history.map((step, move) => {
          //这里的move是索引值
          const desc = move ? "Go to move #" + move : "Go to game start";
          return (
            <li key={move}>
              <button onClick={() => this.jumpTo(move)}>{desc}</button>
            </li>
          );
        });
    
        let status;
        if (winner) {
          status = "Winner: " + winner;
        } else {
          status = "Next player: " + (this.state.xIsNext ? "X" : "O");
        }
    
        return (
          <div className="game">
            <div className="game-board">
              <Board
                squares={current.squares}
                onClick={(i) => this.handleClick(i)}
              />
            </div>
            <div className="game-info">
              <div>{status}</div>
              <ol>{moves}</ol>
            </div>
          </div>
        );
      }
    }
    
    // ========================================
    
    ReactDOM.render(<Game />, document.getElementById("root"));
    
    //判断Winner
    function calculateWinner(squares) {
      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]) {
          return squares[a];
        }
      }
      return null;
    }
    
  3. 拷贝以下三行代码到 src/ 文件夹下的 index.js 文件的顶部:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

        现在,在项目文件夹下执行 npm start 命令,然后在浏览器访问 http://localhost:3000。这样你就可以在浏览器中看见一个空的井字棋的棋盘了。

猜你喜欢

转载自blog.csdn.net/nxcniuxiangchen/article/details/120269965