Skip to content
本页目录

React-井字游戏

项目地址:https://github.com/845415120/React-squareReact实例井字游戏

构建棋盘

jsx
import React from 'react'
//组件
function 棋子() {
  return <button>1</button>;
}
export default function 棋盘() {
    <棋子/>
  // ...
}

通过 props 传递数据

jsx
function 棋子({ value }) {
  return <button>{ value }</button>;
}
export default function 棋盘() {
    <棋子  value="1"/>
  // ...
}

点击交互

jsx
//棋子组件
function 棋子({ value }) {
    function 鼠标点击事件() {
    console.log('clicked!');
  }
  return (<button  onClick={鼠标点击}>{ value }</button>);
}
export default function 棋盘() {
    <棋子  value="1"/>
  // ...
}

我们希望 棋子组件能够“记住”它被单击过,并用“X”填充它。

为了“记住”一些东西,组件使用 state

React 提供了一个名为 useState 的特殊函数,可以从组件中调用它来让它“记住”一些东西

jsx
import { useState } from 'react';

function 棋子() {
  const [value, setValue] = useState(null);

  function handleClick() {
   setValue('X');
  }
     return (<button  onClick={handleClick}>{ value }</button>);
}

value 存储值

setValue 是可用于更改值的函数

获取九个方框的state

Board 需要以某种方式知道 9 个 Square 组件中每个组件的 state。

最好的方法是将游戏的 state 存储在 Board 父组件中,而不是每个 Square

编辑 Board 组件,使其声明一个名为 squares 的 state 变量,该变量默认为对应于 9 个方块的 9 个空值数组:

jsx
// ...
export default function Board() {
  const [squares, setSquares] = useState(Array(9).fill(null));
  return (
     <棋子 value={squares[0]} />
  );
}

从 Board 组件接收 value props

jsx
function 棋子({value}) {
  return <button className="square">{value}</button>;
}

交替放置“X”和“O”

现在,每个 棋子都会收到一个 value props,对于空方块,该 props 将是 'X''O'null

接下来,你需要更改单击 Square 时发生的情况

棋子点击事件 onSquareClick

jsx
function 棋子({value,onSquareClick }) {
  return (<button  onClick={onSquareClick }>{ value }</button>);
}

鼠标点击 函数添加到 棋子组件的 props 中:

棋盘中声明一个函数

jsx
<棋子 value={squares[0]} onSquareClick={handleClick} />

handleClick函数更新

jsx
  function handleClick(i) {
    const nextSquares = squares.slice();
    nextSquares[i] = "X";
    setSquares(nextSquares);
  }

handleClick 函数使用 JavaScript 数组的 slice() 方法创建 squares 数组(nextSquares)的副本。然后,handleClick 更新 nextSquares 数组,将 X 添加到第一个([0] 索引)方块。

使用箭头函数在组件中使用

  <Square value={squares[0]} onSquareClick={() => handleClick(0)} />

交替落子

jsx
export default function Board() {
  const [xIsNext, setXIsNext] = useState(true);
  const [squares, setSquares] = useState(Array(9).fill(null));

  function handleClick(i) {
    const nextSquares = squares.slice();
    if (xIsNext) {
      nextSquares[i] = "X";
    } else {
      nextSquares[i] = "O";
    }
    setSquares(nextSquares);
    setXIsNext(!xIsNext);
  }

  return (
    //...
  );
}

宣布获胜者

添加一个名为 calculateWinner 的辅助函数,它接受 9 个方块的数组,检查获胜者并根据需要返回 'X''O'null

jsx
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;
}

增加条件判断

jsx
function handleClick(i) {
  if (squares[i] || calculateWinner(squares)) {
    return;
  }

为了让玩家知道游戏何时结束,你可以显示“获胜者:X”或“获胜者:O”等文字

jsx
  const winner = calculateWinner(squares);
  let status;
  if (winner) {
    status = "Winner: " + winner;
  } else {
    status = "Next player: " + (xIsNext ? "X" : "O");
  }

在棋盘中增加

jsx
    <div className="status">{status}</div>

完整代码

jsx
import React, { useState } from 'react'

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

export default function Board () {
  //每次玩家落子时,xIsNext(一个布尔值)将被翻转以确定下一个玩家
  const [xIsNext, setXIsNext] = useState(true)
  const [square, setSquare] = useState(Array(9).fill(null))
  function handleClick (i) {
    if (square[i] || calculateWinner(square)) {
      return
    }
    const nextSquares = square.slice()
    if (xIsNext) {
      nextSquares[i] = 'X'
    } else {
      nextSquares[i] = 'O'
    }
    setSquare(nextSquares)
    setXIsNext(!xIsNext)
  }
  //获胜
  const winner = calculateWinner(square)
  let status
  if (winner) {
    status = "胜利者是: " + winner
  } else {
    status = "下一回合: " + (xIsNext ? "X" : "O")
  }
  return (
    <div>

      <div className="status">{status}</div>
      <div className="board-row">
        <Square value={square[0]} onSquareClick={() => handleClick(0)} />
        <Square value={square[1]} onSquareClick={() => handleClick(1)} />
        <Square value={square[2]} onSquareClick={() => handleClick(2)} />
      </div>
      <div className="board-row">
        <Square value={square[3]} onSquareClick={() => handleClick(3)} />
        <Square value={square[4]} onSquareClick={() => handleClick(4)} />
        <Square value={square[5]} onSquareClick={() => handleClick(5)} />
      </div>
      <div className="board-row">
        <Square value={square[6]} onSquareClick={() => handleClick(6)} />
        <Square value={square[7]} onSquareClick={() => handleClick(7)} />
        <Square value={square[8]} onSquareClick={() => handleClick(8)} />
      </div>
    </div>
  )

}
//宣布获胜者
function calculateWinner (square) {
  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 (square[a] && square[a] === square[b] && square[a] === square[c]) {
      return square[a]
    }
  }
  return null
}