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

时光毁灭记忆、已成空白 提交于 2020-01-30 02:46:15

问题


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:

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:

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!


回答1:


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
}



回答2:


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.

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).

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.



来源:https://stackoverflow.com/questions/39062111/java-how-to-check-diagonal-connect-four-win-in-2d-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!