Java:如何检查2D阵列中的对角连接四赢

时间:2016-08-21 08:02:39

标签: java arrays multidimensional-array

我有一个Connect Four“board”,它是一个6 * 7 2D char数组,填充空格,X或O.当垂直,水平或垂直连续有四个X或四个Os时,满足获胜条件斜。我已经设法成功检查了纵向和横向的胜利条件,其中获胜的字符由以下某些方法返回:

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;
}

我只是坚持如何检查对角线胜利,而不抛出ArrayIndexOutOfBoundsException。我知道我需要迭代2D数组两次,一次用于前对角线,一次用于后方对角线,这是4个方格长或更多,如下图所示:

Diagonals to be checked diagram

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

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

    // some iteration here

    return dWinner;
}

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:6)

最简单的算法可能是:

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

代码:

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
}

答案 1 :(得分:2)

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

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

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

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

primeSieve :: Int -> [Int] -- Returns a list of primes up to upperbound
primeSieve upperbound = filter [2..upperbound]
  where
    filter ls indx =
        let divisor = (ls!!indx)
            filtered = [x | x <- ls, x `mod` divisor /= 0]
        in if divisor*divisor >= last filtered
          then filtered
          else filter filtered (indx+1)

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

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

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

很抱歉这个问题来自电话,如果你愿意,我可以在以后更新并添加更多例子。