React教程7:游戏胜利判定
首先
我希望通过多次的文章内容,以及作为我的复习和备忘录,使用React来开发井字游戏(三连棋)。
-
- React
-
- CodeSandbox(公式)
- CodeSandbox(非公式)
系列的列表
-
- React入門1:环境搭建 [在线版]
-
- React入门1.5:环境搭建 [本地版-番外篇]
-
- React入门2:盘面的创建
-
- React入门3:交互实现
-
- React入门4:重构 [提升篇]
-
- React入門5:重构 [交互篇]
-
- React入門6:行动顺序的实现
-
- React入門7:游戏胜利判断(本节)
-
- React入門8:文字实现
-
- React入門9:时间旅行(1)
-
- React入門10:时间旅行(2)
- React入門11:时间旅行(3)
关于目的
整体目标
我们将使用3×3的方格来实现React教程中公开的井字游戏。
这次的目标是什么?
我们将实现一个用于判断游戏胜利的程序。这次我们主要考虑如何用程序来表达井字游戏的规则。因为算法有点复杂,所以我们将使用图表和伪代码(日语+程序)进行说明。所以,如果你只想做React教程,请只复制源代码并继续下一篇文章。
游戏的胜利判断 de
您可以在下一页中查看上次的源文件。
- 前回の内容はコチラから!
算法推导
胜利模式
在编码之前,让我们考虑一下井字游戏的获胜模式数量。
九个方格的状态由Board组件中定义的squares数组进行管理。通过将这些元素传递给Square组件的value属性来显示方格的状态。squares数组的元素与方格对应关系如下。
在“圈叉游戏”中,获胜的条件是在同一方向上连续排列3个相同的标记。因此,我们需要考虑与棋盘平行的水平方向、与棋盘垂直的竖直方向以及斜对角方向。下面列举了每个方向可能的获胜模式。
就像上面的图所示,共有8种胜利判定。每个胜利模式可以通过表示3个方格的位置来进行编程表达。
const 勝利パターン = [マスの位置a, マスの位置b, マスの位置c];
程序规范
我们将实现一个名为calculateWinner()的程序,它将作为一个在每次轮到对方下棋时计算获胜者的函数。这个函数的目的是执行以下操作。
-
- 盤面の状況として、全マスの状態を引数として受け取る
-
- ゲームに決着がついたか否かを判定する
決着がついた場合は、勝者の印(「X」もしくは「O」)を返す
決着がついていない場合は、null を返す
然后,我们考虑符合上述规范的伪代码。在文章开头简单提到,伪代码是将自然语言(我们人类日常使用的语言)和程序结合在一起的一种形式。
function calculateWinner( 全マスの状態 ) {
const 全勝利パターン = [
[ 勝利パターン0 ],
[ 勝利パターン1 ],
[ 勝利パターン2 ],
...,
[ 勝利パターン7 ],
];
for( 全勝利パターンを調べる ) {
if( 勝者条件が満たされた ) {
勝者の印を返す;
}
}
全勝利パターンが満たされなかったので null を返す;
}
胜利判定的方法
当确认了组成胜利判定所需的方格排列后,我们将思考能够判断棋盘是否满足胜利条件的算法。
要判断某个胜利模式是否成立,需要满足以下所有条件。为了与数组索引对应,我们将第一个元素称为”0步”。
-
- 勝利パターンの 0マス目の状態が空白ではない (「X」か「O」の印がある)
-
- 勝利パターンの 1マス目は、0マス目と同じ印である
- 勝利パターンの 2マス目も、0マス目と同じ印である
我将尝试用伪代码来表示这个。
const 勝利パターン = [0マス目の位置, 1マス目の位置, 2マス目の位置];
if (0マス目に印がある && 0マス目と1マス目は同じ印である && 0マス目と2マス目は同じ印である) {
その印が勝者である;
}
创建函数
疑似代码完成了。
我們已經提供了三個假代碼直到這一點,但我們將結合它們來明確地定義 calculateWinner() 函數。雖然這變得複雜了,但這只是為了理解概念,不必完全讀懂也沒問題。
function calculateWinner( 全マスの状態 ) {
const 全勝利パターン = [
勝利パターン0,
勝利パターン1,
勝利パターン2,
...,
勝利パターン7,
];
for( let i = 0; i < 全勝利パターンの数; i++ ) {
const 0マス目の位置 = i番目の勝利パターンにおける0マス目の位置;
const 1マス目の位置 = i番目の勝利パターンにおける1マス目の位置;
const 2マス目の位置 = i番目の勝利パターンにおける2マス目の位置;
if (0マス目に印がある && 0マス目と1マス目は同じ印である && 0マス目と2マス目は同じ印である)
その印が勝者である;
}
}
全勝利パターンが満たされなかったので null を返す;
}
使用程序表示
我们将在 App.js 中定义 calculateWinner() 函数。如果您将其与上述伪代码进行对照,应该能更容易地理解处理过程。
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 = lines[i][0];
const b = lines[i][1];
const c = lines[i][2];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
代码格式化
我正在创建一个名为calculateWinner()的函数。在for循环中的开头有以下代码。
const a = lines[i][0];
const b = lines[i][1];
const c = lines[i][2];
目前这样也没有问题,但是我们可以对代码进行整理,用一行表达。
const [a, b, c] = lines[i];
我已经成功创建了一个可以用来判断胜利的函数。
最后
这次,我们创建了一个名为calculateWinner()的函数作为判断游戏胜负的程序。因为我们只是定义了这个函数,所以它的功能和上一次的相同。下一页将展示当前阶段的源代码文件。
下一步,我们将把此函数嵌入到Board组件中,以便能够显示胜利判定。离游戏完成只剩一点点时间!