四子棋游戏检查胜利的JS代码

3
我正在进行我的第一个完整的编程项目,已经有两周的编程经验了,但遇到了一个似乎无法解决的难题。我正在制作一个连四游戏,并已经开始使用JavaScript构建逻辑,然后再推送到DOM中。我已经通过构造函数创建了单元格对象,并将其推入2D数组形式的游戏对象中。我成功创建了一个每次进行下棋并使用2天数组更改该列最低点处单元格值的函数。然而,我不确定如何让我的胜利检查函数运行。
到目前为止,我的逻辑是对于2D数组中的每个点,您可以通过行、列和对角线进行检查。我理解如何检查胜利的逻辑,但是我不知道如何遍历行和列的数组。在下面的示例中,this.cellsArray是Board Constructor中单元格对象的数组。该数组有7个列数组,每个数组有6行,因为我翻转了典型的行列逻辑以适应Connect Four的基于列的性质。然而,我无法像this.cellsArray[col][row]这样访问数组,因为col和row未定义,我也不知道如何定义索引值?任何帮助将不胜感激! Connect 4 示例:
//array location is equal to an instance of this.cellsArray[col][row]
Board.prototype.checkRowRight = function (arrayLocation) {

    if ((arrayLocation[i+1][i].value === arrayLocation.value) && (arrayLocation[i+2][i]=== arrayLocation.value)  && (arrayLocation[i+3][i].value === arraylocation.value)){
        this.winner = this.currentPlayer;
        this.winnerFound = true;
        console.log('Winner has been found!')
    }
};

可能是四子连珠逻辑的重复问题 - 尽管那个特定的问题是针对C语言的,但代码是标准的过程式风格,并且很容易适应JS。 - paxdiablo
这个有帮助,但我想我的问题与逻辑关系较少,更多的是语法方面的问题,已经进行了编辑更新。 - C. Kearns
C.Kearns,看下面我的回答,基本上是将逻辑转换为Javascript。 - paxdiablo
2个回答

6

回到我在这里找到的逻辑,并重构获胜线检测代码,这可以轻松转换为以下Javascript代码:

function chkLine(a,b,c,d) {
    // Check first cell non-zero and all cells match
    return ((a != 0) && (a ==b) && (a == c) && (a == d));
}

function chkWinner(bd) {
    // Check down
    for (r = 0; r < 3; r++)
        for (c = 0; c < 7; c++)
            if (chkLine(bd[r][c], bd[r+1][c], bd[r+2][c], bd[r+3][c]))
                return bd[r][c];

    // Check right
    for (r = 0; r < 6; r++)
        for (c = 0; c < 4; c++)
            if (chkLine(bd[r][c], bd[r][c+1], bd[r][c+2], bd[r][c+3]))
                return bd[r][c];

    // Check down-right
    for (r = 0; r < 3; r++)
        for (c = 0; c < 4; c++)
            if (chkLine(bd[r][c], bd[r+1][c+1], bd[r+2][c+2], bd[r+3][c+3]))
                return bd[r][c];

    // Check down-left
    for (r = 3; r < 6; r++)
        for (c = 0; c < 4; c++)
            if (chkLine(bd[r][c], bd[r-1][c+1], bd[r-2][c+2], bd[r-3][c+3]))
                return bd[r][c];

    return 0;
}

并进行一次测试调用:

x =[ [0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 1, 1, 0, 0],
     [0, 0, 0, 1, 1, 0, 0],
     [0, 0, 1, 2, 2, 2, 0],
     [0, 1, 2, 2, 1, 2, 0] ];
alert(chkWinner(x));

当调用 chkWinner 函数并传入棋盘时,该函数将返回第一个(假设每次移动只改变一个单元格,并且在每次移动后检查)获胜的玩家。

其基本思想是仅限于检查有意义的单元格。例如,在检查向右移动的单元格时(参见第二个循环),您只需要从最左边的四列 0-3 中以每行 0-6 开始进行检查。

这是因为在其他位置开始可能导致到达棋盘右侧之前就找不到可能的获胜情况。换句话说,列集合 {0,1,2,3}{1,2,3,4}{2,3,4,5}{3,4,5,6} 是有效的,而 {4,5,6,7} 不是(有效的列是 0-6)。


谢谢!这非常有帮助!我仍在努力弄清楚控制台中参数的工作原理,但我对如何循环遍历数组有了更好的理解! - C. Kearns

0

这是一个旧的帖子,但我会把我的解决方案加入到讨论中,因为这是“如何在JavaScript中计算Connect4胜利”的热门搜索结果之一。

我通过使用矩阵加法来解决这个问题。

假设您的游戏板存储在内存中,格式为2D数组,如下所示:

   [ [0, 0, 0, 0, 0, 0, 0],
     [0, 0, Y, 0, 0, 0, 0],
     [0, 0, Y, 0, 0, 0, 0],
     [0, 0, R, 0, 0, 0, 0],
     [0, 0, Y, 0, 0, 0, 0],
     [0, 0, R, R, R, 0, 0] ];

在每次“投币”时,您应该调用一个函数,传递硬币的x/y位置。
这是您计算用户是否赢得游戏的地方。
let directionsMatrix = {
  vertical: { south: [1, 0], north: [-1, 0] },
  horizontal: { east: [0, 1], west: [0, -1] },
  backward: { southEast: [1, 1], northWest: [-1, -1] },
  forward: { southWest: [1, -1], northEast: [-1, 1] },
};

注意:矩阵符号中的“South”表示[1,0],意思是“向下移动1个单元格,向右移动0个单元格”

现在我们可以循环遍历每个轴/方向,检查是否有4个连续的格子。

  const playerHasWon = (colnum, rowNum, playerColor, newGrid) => {
    //For each [North/South, East/West, NorthEast/Northwest, SouthEast/Southwest]
    for (let axis in directionsMatrix) {
      // We difine this variable here so that "East" and "West" share the same count,
      // This allows a coin to be dropped in a middle cell
      let numMatches = 1;

      // For each [North, South]
      for (let direction in directionsMatrix[axis]) {
        // Get X/Y co-ordinates of our dropped coin
        let cellReference = [rowNum, colnum];

        // Add co-ordinates of 1 cell in test direction (eg "North")
        let testCell = newGrid[cellReference[0]][cellReference[1]];

        // Count how many matching color cells are in that direction
        while (testCell == playerColor) {
          try {
            // Add co-ordinates of 1 cell in test direction (eg "North")
            cellReference[0] += directionsMatrix[axis][direction][0];
            cellReference[1] += directionsMatrix[axis][direction][1];
            testCell = newGrid[cellReference[0]][cellReference[1]];

            // Test if cell is matching color
            if (testCell == playerColor) {
              numMatches += 1;

              // If our count reaches 4, the player has won the game
              if (numMatches >= 4) {
                return true;
              }
            }
          } catch (error) {
            // Exceptions are to be expected here.
            // We wrap this in a try/catch to ignore the array overflow exceptions
            // console.error(error);
            break;
          }
        }
        // console.log(`direction: ${direction}, numMatches: ${numMatches}`);

        // If our count reaches 4, the player has won the game
        if (numMatches >= 4) {
          return true;
        }
      }
    }

    // If we reach this statement: they have NOT won the game
    return false;
  };

如果您想查看完整的代码,这里是GitHub存储库的链接。

这里是实时演示的链接。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接