确定TicTacToe游戏状态的算法?

时间:2013-09-01 03:08:57

标签: algorithm stack-overflow tic-tac-toe

我有一个允许2名玩家玩TicTacToe的程序。在每个玩家进行移动之后,它应该在该点显示棋盘并返回一个名为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)

等等

2 个答案:

答案 0 :(得分:2)

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

在你的情况下,这是因为你的函数gameStatus()(我假设它是你发布的代码的第一部分),调用printStatus(),然后在{{1}行再次调用gameStatus() 1}}

尝试将状态作为参数传递给printStatus,如Status status = gameStatus();,而不是尝试在printStatus中返回gameStatus。

答案 1 :(得分: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;
    }
}

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

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之间(其中两个仅在玩家获胜时发生)。