React教程7:游戏胜利判定

首先

我希望通过多次的文章内容,以及作为我的复习和备忘录,使用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)

关于目的

整体目标

我们将使用3×3的方格来实现React教程中公开的井字游戏。

 

这次的目标是什么?

我们将实现一个用于判断游戏胜利的程序。这次我们主要考虑如何用程序来表达井字游戏的规则。因为算法有点复杂,所以我们将使用图表和伪代码(日语+程序)进行说明。所以,如果你只想做React教程,请只复制源代码并继续下一篇文章。

游戏的胜利判断 de

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

 

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

 

算法推导

胜利模式

在编码之前,让我们考虑一下井字游戏的获胜模式数量。

九个方格的状态由Board组件中定义的squares数组进行管理。通过将这些元素传递给Square组件的value属性来显示方格的状态。squares数组的元素与方格对应关系如下。

マスのインデックス.png

在“圈叉游戏”中,获胜的条件是在同一方向上连续排列3个相同的标记。因此,我们需要考虑与棋盘平行的水平方向、与棋盘垂直的竖直方向以及斜对角方向。下面列举了每个方向可能的获胜模式。

勝利パターン.png

就像上面的图所示,共有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组件中,以便能够显示胜利判定。离游戏完成只剩一点点时间!

 

广告
将在 10 秒后关闭
bannerAds