1

我有一个允许 2 名玩家玩井字游戏的程序。在每个玩家移动之后,它应该在该点显示棋盘并返回一个名为 Status 的枚举,显示玩家是否应该继续,如果玩家赢了,或者如果它是平局。但是,该算法要么返回 StackOverflowError,要么继续输入。这是我使用的算法。

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

    }

这是 printStatus 方法。

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

} 

这是错误:

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)

等等

4

2 回答 2

2

您的问题是您的代码重复调用自身创建一个永无止境的循环。例如,如果方法 A() 有调用方法 B() 的代码,但在 B() 中,有调用 A() 的代码,则代码将无限运行,因为 A() 调用 B(),然后调用A() 再次循环重复。StackOverflow 错误通常表明了这一点。

在您的情况下,这是因为您的函数gameStatus()(我假设它是您发布的代码的第一部分)调用printStatus(),然后在该行中再次调用 gameStatus()Status status = gameStatus();

尝试在 printStatus 中将状态作为参数传递,例如printStatus(2,Status.WIN);,而不是尝试在 printStatus 中获取 gameStatus 的返回。

于 2013-09-02T04:38:54.367 回答
0

您发布的内容中似乎没有任何会导致 StackOverflowError 的代码(除非您在 中做了一些非常奇怪的事情printStatus)。导致该错误的错误必须在您的代码中的其他位置。因此,不幸的是,除非您发布更多代码,否则我无能为力。

然而,这里有两件事我注意到你可以使用一些改进。首先,(你实现这个的方式)你不需要嵌套for循环。for (int j = 0; j < 1; j++) {以和开头的循环for (int i = 0; i < 1; i++) {不是必需的,它们会导致错误,因为它们会生成只检查两个框而不是连续三个框的检查。您可以通过简单地消除这些循环来简化它们。(我还修改了您的if声明,请参阅下文了解更多详细信息)。

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

您还可以通过仅在确定某人获胜后检查是否X或占用空间来简化您的 if 语句。0所以,例如,而不是做

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
}

您可以通过将代码更改为:

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

这样,该语句if (board[0][0] == board[1][1] && board[0][0] == board[2][2])只执行一次,而第二条语句 ,if (board[0][0] == 'X')仅在有人赢得对角线时才执行。在您的实现中,if (board[0][0] == 'X')将运行第一次检查,然后是内部 if 语句,或者它将执行第二次玩家检查if (board[0][0] == 'O'),然后是内部检查。这样,您的代码将必须在 2 到 3 个不同的语句之间运行,而在我的代码中,它在 1 到 2 之间(其中两个仅在玩家获胜时发生)。

于 2013-09-01T04:20:45.120 回答