문제

I have a program that allows 2 players to play TicTacToe. After each player makes a move, it should display the board at that point and return an enumaration called Status that show whether the players should continue, if a player won, or if it's a draw. However, the algorithm either return a StackOverflowError, or continues input. Here is the algorithm I used.

       //Checks for winner by rows
       for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 1; j++) {
            if (board[i][j] == 'X') {
                if (board[i][j] == board[i][0 + 1] && board[i][j] == board[i][0 + 2]) {
                    printStatus(1);
                    return Status.WIN;
                } else {
                    return Status.CONTINUE;
                }
            } else if (board[i][j] == 'O') {
                if (board[i][j] == board[i][0 + 1] && board[i][j] == board[i][0 + 2]) {
                    printStatus(2);
                    return Status.WIN;
                } else {
                    return Status.CONTINUE;
                }
            }
        }
    }
    //Checks for winner by columns
    for (int i = 0; i < 1; i++) {
        for (int j = 0; j < 3; j++) {
            if (board[i][j] == 'X') {
                if (board[i][j] == board[0 + 1][j] && board[i][j] == board[0 + 2][j]) {
                    printStatus(1);
                    return Status.WIN;
                } else {
                    return Status.CONTINUE;
                }
            } else if (board[i][j] == 'O') {
                if (board[i][j] == board[0 + 1][j] && board[i][j] == board[0 + 2][j]) {
                    printStatus(1);
                    return Status.WIN;
                } else {
                    return Status.CONTINUE;
                }
            }
        }

    }
    //This group of if statements boards for winner diagnolly
    if (board[0][0] == 'X') {
        if (board[0][0] == board[1][1] && board[0][0] == board[2][2]) {
            printStatus(1);
            return Status.WIN;
        } else {
            return Status.CONTINUE;
        }
    }else if (board[0][0] == '0') {
        if (board[0][0] == board[1][1] && board[0][0] == board[2][2]) {
            printStatus(1);
            return Status.WIN;
        } else {
            return Status.CONTINUE;
        }
    }
    if (board[0][2] == 'O') {
        if (board[0][2] == board[1][1] && board[0][2] == board[2][0]) {
            printStatus(1);
            return Status.WIN;
        } else {
            return Status.CONTINUE;
        }
    }else if (board[0][2] == 'X') {
        if (board[0][2] == board[1][1] && board[0][2] == board[2][0]) {
            printStatus(1);
            return Status.WIN;
        } else {
            return Status.CONTINUE;
        }

    }

Here is the printStatus method.

private void printStatus(int player) {
    Status status = gameStatus();
    if (status == Status.DRAW) {
        System.out.println("The game has ended in a draw.");
        System.exit(0);
    } else if (status == Status.WIN) {
        System.out.println("Player " + player + " has won the game.");
        System.exit(0);
    } else if (status == Status.CONTINUE) {
        System.out.println("The game continues.");
        play();
    }

} 

Here is the error:

Exception in thread "main" java.lang.StackOverflowError
at tictactoe.TicTacToe.gameStatus(TicTacToe.java:86)
at tictactoe.TicTacToe.printStatus(TicTacToe.java:69)
at tictactoe.TicTacToe.gameStatus(TicTacToe.java:92)
    at tictactoe.TicTacToe.printStatus(TicTacToe.java:69)
at tictactoe.TicTacToe.gameStatus(TicTacToe.java:92)
at tictactoe.TicTacToe.printStatus(TicTacToe.java:69)

And so forth

도움이 되었습니까?

해결책

Your problem is that you have code that repetitively calls itself creating a never-ending cycle. For example, if method A() has code that calls method B(), but within B(), there is code that calls A(), then the code will run infinitely as A() invokes B(), which then invokes A() again with the cycle repeating. StackOverflow errors are often indicative of this.

In your case, it's because your function gameStatus() (which, I assume is the first part of code you posted), calls printStatus(), which then calls gameStatus() again in the line Status status = gameStatus();

Try passing the status as an argument in printStatus, like printStatus(2,Status.WIN);, instead of trying to get the return of gameStatus within printStatus.

다른 팁

There does not appear to be any code in what you posted that would cause a StackOverflowError (unless you're doing something really weird in printStatus). The error causing that must be somewhere else in your code. So, unfortunately, unless you post more code, I can't help.

However, here are two things I noticed you could use some improvement on. First, (the way you're implementing this) you do not need nested for loops. The loops beginning with for (int j = 0; j < 1; j++) {, and with for (int i = 0; i < 1; i++) {, are not necessary, and they cause errors, as they produce checks where only two boxes are checked, instead of three in a row. You can simplify them by simply eliminating those loops. (I also modified your if statement, see below for more detail).

    //Checks for winner by rows
for (int i = 0; i < 3; i++) {
    if (board[i][j] == board[i][0 + 1] && board[i][j] == board[i][0 + 2]) { //Check if one player has matched a row
        if (board[i][j] == 'X') { //Then check which player won
            printStatus(1);
        }
        else{
            printStatus(2);
        }
        return Status.WIN;
    } else {
        return Status.CONTINUE;
    }
}

You can also simplify your if statement by only checking for whether X or 0 occupy a space, after you have figured out someone won. So, for example, instead of doing

if (board[0][0] == 'X') {
        if (board[0][0] == board[1][1] && board[0][0] == board[2][2]) {
            printStatus(1);
        }
        //More code here
}
else if (board[0][0] == 'O') {
        if (board[0][0] == board[1][1] && board[0][0] == board[2][2]) {
            printStatus(1);
        }
        //More code here
}

You can simply the code by changing it to:

if (board[0][0] == board[1][1] && board[0][0] == board[2][2]) { //Check if first diagonal is complete
        if (board[0][0] == 'X') { //Check who won
            printStatus(1);
        }
        else{
            printStatus(1);
        }
        return Status.WIN;
    } else {
        return Status.CONTINUE;
    }

In this way, the statement if (board[0][0] == board[1][1] && board[0][0] == board[2][2]) is only executed once, and the second statement, if (board[0][0] == 'X'), is only executed if someone has won the diagonal. In your implementation, the first check of if (board[0][0] == 'X') will be run, then either the interior if statement, or it will execute the second player check, if (board[0][0] == 'O'), then the interior one. In this way, your code will have to run between 2 and 3 different statements, whereas in mine, it's between 1 and 2 (with two only occurring when a player has won).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top