React初学者指南:时间旅行(1)

首先

我希望通过多次的文章来使用 React 开发一个井字游戏(三连棋),既作为自己的复习,也作为备忘录的意思。

    • React

 

    • CodeSandbox(公式)

 

    CodeSandbox(非公式)

系列项目列表

    1. React入门1:环境搭建[在线版]

 

    1. React入门1.5:环境搭建[本地版-番外篇]

 

    1. React入门2:盘面的创建

 

    1. React入门3:交互实现

 

    1. React入门4:重构[提升版]

 

    1. React入门5:重构[交互版]

 

    1. React入门6:实现回合

 

    1. React入门7:游戏胜利判定

 

    1. React入门8:实现文本

 

    1. React入门9:时光旅行(1)(本期)

 

    1. React入门10:时光旅行(2)

 

    React入门11:时光旅行(3)

关于目的

整体目标

我们将在React公式教程中实现一个3×3格子的井字棋游戏。

 

这次的目标

在之前的文章中,我们完成了游戏系统。从这篇文章开始,我们将实现可以回到过去的回合的时间旅行功能。本次准备工作是设计一个新组件,用于记住过去棋盘的状态。

时间旅行 (1)

您可以在下一页上查看上次的源文件。

 

    前回の内容はコチラから!

 

保留之前的回合方法

目前,井字遊戲由Board組件和Square組件組成。

Board コンポーネント

盤面を表示する

state 型の squares 配列で盤面の状況を管理する

Square コンポーネントがクリックされたときのイベントとして handleClick() 関数を定義している

Square コンポーネント

盤面上にある1つのマスを表示する

因此,我们将创建一个名为Game的组件,用于保存每个移动后棋盘的状态。在这个组件中,我们会将Board组件的状态和数组提升。

编码

我們將在App.js中的Board組件進行如下更改:

    • メインコンポーネントとしての定義をやめる

state 型の変数と配列の宣言を省く
次のプロパティを設定する

xIsNext : 現在の手番

squares : 現在の盤面の状況

onPlay : 盤面の状況を記憶する処理と手番を交代する処理を行う関数

handleClick() 関数の変更

state 型の変数と配列の更新処理を省く

onPlay プロパティで受け取った関数を実行する

更新された盤面の状況を渡す

function Board({ xIsNext, squares, onPlay }) {
  const winner = calculateWinner(squares);
  let status;

  if (winner) {
    status = "勝者: " + winner;
  } else {
    status = "プレイヤー: " + (xIsNext ? "X" : "O");
  }

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

    const nextSquares = squares.slice();

    if (xIsNext) {
      nextSquares[i] = "X";
    } else {
      nextSquares[i] = "O";
    }
    onPlay(nextSquares);
  }

  return (
    <>
      <div>{status}</div>
      <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>
    </>
  );
}

接下来,我们将定义 Game 组件如下。

    • これをメインコンポーネントとする

Board コンポーネントのリフトアップする

state 型の history 配列を定義する

盤面の状況を示す
初期値: [Array(9).fill(null)]

set関数名: setHistory

state 型の xIsNext 変数を定義する

現在の着手を示す
初期値: true

set関数名: setXIsNext

currentSquares 変数を定義する

現在の盤面の状況を示す
初期値: 最新の盤面の状況

handlePlay() 関数の定義

盤面の状況を記憶する
手番を交代する

Board コンポーネントをレンダーする

各プロパティに適切な値または関数を渡す

export default function Game() {
  const [history, setHistory] = useState([Array(9).fill(null)]);
  const [xIsNext, setXIsNext] = useState(true);
  const currentSquares = history[history.length - 1];

  function handlePlay(nextSquares) {
    setHistory([...history, nextSquares]);
    setXIsNext(!xIsNext);
  }

  return (
    <Board xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} />
  );
}

接下来会展示执行结果。由于进行了升级,组件的构成发生了变化,但操作内容与上次相同。

動作結果.gif

通过这样,游戏组件中的state类型的history数组可以记录游戏界面的情况。history数组的元素表示某个回合的游戏界面情况。具体来说,history[i]表示第i次回合的游戏界面情况,history[i][0]表示游戏界面左上角格子的状态。

最后

在这次实现时间旅行功能的过程中,我们进行了对Game组件进行定义和提升。请参考下一页的当前阶段源代码。

 

下一步,我们将在Game组件中添加文本,以便能够回到过去的回合。

 

广告
将在 10 秒后关闭
bannerAds