Java:如何在二维数组中检查对角连接四胜

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39062111/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 04:03:11  来源:igfitidea点击:

Java: How to check diagonal Connect Four win in 2D array

javaarraysmultidimensional-array

提问by P. Tan

I have a Connect Four "board" which is a 6*7 2D char array populated with either spaces, X or O. The win condition is met when there are either four Xs or four Os in a row vertically, horizontally or diagonally. I've managed to get the win conditions checked successfully for vertical and horizontal, where the winning char is returned by some methods as below:

我有一个连接四个“板”,它是一个填充有空格、X 或 O 的 6*7 2D 字符数组。当垂直、水平或对角线上有四个 X 或四个 O 时,满足获胜条件。我设法成功地检查了垂直和水平的获胜条件,其中获胜字符由以下某些方法返回:

private char CheckVerticalWinner(char[][] currentBoard) {
    // check vertical (move down one row, same column)
    char vWinner = ' ';
    for (int col=0; col<7; col++) {
        int vCount = 0;
        for (int row=0; row<5; row++) {
            if (currentBoard[row][col]!=' ' &&
                currentBoard[row][col] == currentBoard[row+1][col]) {
                vCount++;
                System.out.println("VERT "+vCount); //test
            } else {
                vCount = 1;
            }

            if (vCount>=4) {
                vWinner = currentBoard[row][col];
            }
        }
    }
    return vWinner;
}


private char CheckHorizontalWinner(char[][] currentBoard) {
    // check horizontal (move across one column, same row)
    char hWinner = ' ';
    for (int row=0; row<6; row++) {
        int hCount = 0;
        for (int col=0; col<6; col++) {
            if (currentBoard[row][col]!=' ' &&
                currentBoard[row][col] == currentBoard[row][col+1]) {
                hCount++;
                System.out.println("HORIZ "+hCount); //test
            } else {
                hCount = 1;
            }

            if (hCount>= 4) {
                hWinner = currentBoard[row][col];
            }
        }
    }
    return hWinner;
}

I'm just stuck on how to check for diagonal wins, without throwing an ArrayIndexOutOfBoundsException. I know I need to iterate through the 2D array twice, once for forward diagonals and once for backward diagonals that are 4 squares long or more, like in the below diagram:

我只是坚持如何检查对角线获胜,而不抛出 ArrayIndexOutOfBoundsException。我知道我需要遍历 2D 数组两次,一次用于前对角线,一次用于4 个正方形或更多的后向对角线如下图所示:

Diagonals to be checked diagram

待检查的对角线图

Basically, how would I fill in this method to return a winning char?

基本上,我将如何填写此方法以返回获胜字符?

private char CheckDiagonalWinner(char[][] currentBoard) {

    // some iteration here

    return dWinner;
}

Any help would be much appreciated!

任何帮助将非常感激!

回答by meriton

The simplest algorithm probably is:

最简单的算法可能是:

for every direction
    for every coordinate
        check whether the next 3 elements in this direction exist and are the same

in code:

在代码中:

final int maxx = 7;
final int maxy = 6;

char winner(char[][] board) {
    int[][] directions = {{1,0}, {1,-1}, {1,1}, {0,1}};
    for (int[] d : directions) {
        int dx = d[0];
        int dy = d[1];
        for (int x = 0; x < maxx; x++) {
            for (int y = 0; y < maxy; y++) {
                int lastx = x + 3*dx;
                int lasty = y + 3*dy;
                if (0 <= lastx && lastx < maxx && 0 <= lasty && lasty < maxy) {
                    char w = board[x][y];
                    if (w != ' ' && w == board[x+dx][y+dy] 
                                 && w == board[x+2*dx][y+2*dy] 
                                 && w == board[lastx][lasty]) {
                        return w;
                    }
                }
            }
        }
    }
    return ' '; // no winner
}

回答by leonz

First of all, you don't need to check the whole board at any given time, which I think is being done in your code. To optimise your code and make it simpler both for you and the computer, you can do the following:

首先,您不需要在任何给定时间检查整个电路板,我认为这是在您的代码中完成的。要优化您的代码并使您和计算机都更简单,您可以执行以下操作:

BEFORE checking any direction on the board, first populate the board with user input. What that means is that every time you get new input, first thing you do is use that input and update your matrix. That way we always have updated matrix and we can do what we will do next:

在检查板上的任何方向之前,首先用用户输入填充板。这意味着每次获得新输入时,您要做的第一件事就是使用该输入并更新矩阵。这样我们总是有更新的矩阵,我们可以做我们接下来要做的事情:

Get x and y of the input from user. That means is that if user selects row 2, you populate matrix on let's say row 2 and column 4. What do we do with these coordinates? We use THEM and send them to the methods that check the matrix for 4 in a row. This enables us not to check whole matrix, but only the populated matrix.

获取用户输入的 x 和 y。这意味着,如果用户选择第 2 行,您将在第 2 行和第 4 列上填充矩阵。我们如何处理这些坐标?我们使用 THEM 并将它们发送到连续检查矩阵 4 的方法。这使我们能够不检查整个矩阵,而只检查填充的矩阵。

In the vertical check, you can now check only from those coordinates down, for example:

在垂直检查中,您现在只能从这些坐标向下检查,例如:

boolean winner = false;

count = 1;

if (x > 3) 

for (i = 0; i < 3; i++) {

    if (A[x][y-i] == 'X')

        count ++;

    if (count == 4) {

        winner = true;

        return;

    }

For horizontal check, do the same, but horizontally. You need two loops, for checking left and right.

对于水平检查,请执行相同的操作,但要水平检查。您需要两个循环,用于检查左右。

For diagonal check, now you only need to check diagonal containing set coordinates. For example, if user inputted row 4 and column 5, for the left diagonal, we need to check (5,4) , (6,3) and (7,2).

对于对角线检查,现在您只需要检查包含设置坐标的对角线。例如,如果用户输入第 4 行和第 5 列,对于左对角线,我们需要检查 (5,4) 、 (6,3) 和 (7,2)。

Using coordinates to check for winner is much simpler, it allows us to only check the populated part of matrix.

使用坐标检查获胜者要简单得多,它允许我们只检查矩阵的填充部分。

Sorry for messy answer, written this from phone, I can update and add some more examples later if you want.

抱歉,回答很乱,是通过电话写的,如果您愿意,我可以稍后更新并添加更多示例。