0%

813_React官方文档_井字棋游戏(待完善)

Square组件

import React from 'react';
//import { useState } from 'react';

export default function Square({ value, onSquareClick }) {
  return (
    <button className="square" onClick={onSquareClick}>
      {value}
    </button>
  );

Board组件

import React from 'react';
import Square from '../Square';
//import Game from '../Game';
import { useState } from 'react';

//这个辅助函数用于判断谁是获胜者
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;
}

//状态提升:将子组件的状态提升到父组件
//要从多个子组件收集数据,或让两个子组件相互通信,请改为在其父组件中声明共享 state。父组件可以通过 props 将该 state 传回给子组件。这使子组件彼此同步并与其父组件保持同步。
export default function Board() {
  const [squares, setSquares] = useState(Array(9).fill(null));
  const [xIsNext, setxIsNext] = useState(true);

  function handleClick(i) {
    //如果方块不为空或者已经决出获胜者,游戏就终止
    if (squares[i] || calculateWinner(squares)) {
      return;
    }

    //改变点击的Square状态,并更新数组
    //思考:为什么不直接改变原数组的值,而是要重新生成一个数组再赋值?
    //1、使得复杂的功能(时间旅行)容易实现。2、降低Diff算法的成本
    const nextSquares = squares.slice();
    if (xIsNext) {
      nextSquares[i] = 'X';
    } else {
      nextSquares[i] = 'O';
    }
    setSquares(nextSquares);
    setxIsNext(!xIsNext);
    //xIsNext = !xIsNext;
  }

  //如果游戏没有结束,就显示下一步该谁走。如果游戏结束就显示获胜者
  const winner = calculateWinner(squares);
  let status;
  if (winner) {
    status = '获胜者是' + winner;
  } else {
    status = '下一步该轮到' + (xIsNext ? 'X' : 'O');
  }
  return (
    <>
      <div className="board-row">
        <Square value={squares[0]} onSquareClick={() => handleClick(0)} />
        <Square value={squares[1]} onSquareClick={() => handleClick(1)} />
        <Square value={squares[2]} onSquareClick={() => handleClick(2)} />
      </div>
      <div className="board-row">
        <Square value={squares[3]} onSquareClick={() => handleClick(3)} />
        <Square value={squares[4]} onSquareClick={() => handleClick(4)} />
        <Square value={squares[5]} onSquareClick={() => handleClick(5)} />
      </div>
      <div className="board-row">
        <Square value={squares[6]} onSquareClick={() => handleClick(6)} />
        <Square value={squares[7]} onSquareClick={() => handleClick(7)} />
        <Square value={squares[8]} onSquareClick={() => handleClick(8)} />
      </div>
      <h1>{status}</h1>
    </>
  );
}