Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Tic-Tac-Toe不工作的Minimax算法_Java_Recursion_Tic Tac Toe_Minimax - Fatal编程技术网

Java Tic-Tac-Toe不工作的Minimax算法

Java Tic-Tac-Toe不工作的Minimax算法,java,recursion,tic-tac-toe,minimax,Java,Recursion,Tic Tac Toe,Minimax,我试图用一个简化的极大极小算法来制作一个无与伦比的井字游戏。代码如下所示: private static int findBestMove(String[][] board, boolean comp) { // comp returns true if the computer is the one looking for the best move // findBestMove is always called by the program as findBestMove(

我试图用一个简化的极大极小算法来制作一个无与伦比的井字游戏。代码如下所示:

private static int findBestMove(String[][] board, boolean comp) {
    // comp returns true if the computer is the one looking for the best move
    // findBestMove is always called by the program as findBestMove(board, true)
    // since the computer is the only one that uses it

    // If the board in its current state is a win for the
    // player, return -1 to indicate a loss
    if (playerWon(board)) return -1;

    // If the board in its current state is a win for the
    // computer, return 1 to indicate a win
    if (compWon(board)) return 1;

    // If the board in its current state is a tie
    // return 0 to indicate a tie
    if (tie(board)) return 0;

    // Set the default possible outcome as the opposite of what
    // the respective player wants
    int bestPossibleOutcome = comp ? -1 : 1;

    // Loop through the board looking for empty spaces
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++)

            // Once an empty space is found, create a copy of the board
            // with that space occupied by the respective player 
            if (board[i][j].equals(" ")) {
                String[][] newBoard = new String[3][3];
                for (int a = 0; a < 3; a++) {
                    System.arraycopy(board[a], 0, newBoard[a], 0, 3);
                }
                newBoard[i][j] = comp ? "O" : "X";

                // Recursively call findBestMove() on this copy
                // and see what the outcome is
                int outCome = findBestMove(newBoard, !comp);

                // If this is the computer's turn, and the outcome
                // is higher than the value currently stored as the
                // best, replace it
                if (comp && outCome > bestPossibleOutcome) {
                    bestPossibleOutcome = outCome;


                    // r and c are instance variables that store the row
                    // and column of what the computer's next move should be
                    r = i;
                    c = j;


                // If this is the player's turn, and the outcome
                // is lower than the value currently stored as the
                // best, replace it
                } else if (!comp && outCome < bestPossibleOutcome) {
                    bestPossibleOutcome = outCome;
                }
            }
        }
    }
    // Return the ultimate value deemed to be the best
    return bestPossibleOutcome;
}
private static void findBestMove(String[][] board) {
    double bestMove = Double.NEGATIVE_INFINITY;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
             if (board[i][j].equals(" ")) {
                 board[i][j] = "O";
                 double score = minimax(board, false);
                 board[i][j] = " ";
                 if (score > bestMove) {
                      bestMove = score;
                      r = i;
                      c = j;
                 }
             }
         }
     }
}

private static double minimax(String[][] board, boolean comp) {
    if (playerWon(board)) {
        return -1;
    }
    if (compWon(board)) {
        return 1;
    }
    if (tie(board)) return 0;

    double bestScore;
    if (comp) {
         bestScore = Double.NEGATIVE_INFINITY;
         for (int i = 0; i < 3; i++) {
             for (int j = 0; j < 3; j++) {
                 if (board[i][j].equals(" ")) {
                    board[i][j] = "O";
                    double score = minimax(board, false);
                    board[i][j] = " ";
                    bestScore = Math.max(score, bestScore);
                 }
             }
         }
    } else {
         bestScore = Double.POSITIVE_INFINITY;
         for (int i = 0; i < 3; i++) {
              for (int j = 0; j < 3; j++) {
                  if (board[i][j].equals(" ")) {
                      board[i][j] = "X";
                      double score = minimax(board, true);
                      board[i][j] = " ";
                      bestScore = Math.min(score, bestScore);
                  }
              }
          }
     }
     return bestScore;
}

我不是要求任何人为我重写整件事,但如果你能指出任何明显的错误或给我指出正确的方向,我将不胜感激。我也愿意听取您的任何建议或意见。

我还没有对它进行广泛测试,但我相信我已经解决了这个问题。新代码如下所示:

private static int findBestMove(String[][] board, boolean comp) {
    // comp returns true if the computer is the one looking for the best move
    // findBestMove is always called by the program as findBestMove(board, true)
    // since the computer is the only one that uses it

    // If the board in its current state is a win for the
    // player, return -1 to indicate a loss
    if (playerWon(board)) return -1;

    // If the board in its current state is a win for the
    // computer, return 1 to indicate a win
    if (compWon(board)) return 1;

    // If the board in its current state is a tie
    // return 0 to indicate a tie
    if (tie(board)) return 0;

    // Set the default possible outcome as the opposite of what
    // the respective player wants
    int bestPossibleOutcome = comp ? -1 : 1;

    // Loop through the board looking for empty spaces
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++)

            // Once an empty space is found, create a copy of the board
            // with that space occupied by the respective player 
            if (board[i][j].equals(" ")) {
                String[][] newBoard = new String[3][3];
                for (int a = 0; a < 3; a++) {
                    System.arraycopy(board[a], 0, newBoard[a], 0, 3);
                }
                newBoard[i][j] = comp ? "O" : "X";

                // Recursively call findBestMove() on this copy
                // and see what the outcome is
                int outCome = findBestMove(newBoard, !comp);

                // If this is the computer's turn, and the outcome
                // is higher than the value currently stored as the
                // best, replace it
                if (comp && outCome > bestPossibleOutcome) {
                    bestPossibleOutcome = outCome;


                    // r and c are instance variables that store the row
                    // and column of what the computer's next move should be
                    r = i;
                    c = j;


                // If this is the player's turn, and the outcome
                // is lower than the value currently stored as the
                // best, replace it
                } else if (!comp && outCome < bestPossibleOutcome) {
                    bestPossibleOutcome = outCome;
                }
            }
        }
    }
    // Return the ultimate value deemed to be the best
    return bestPossibleOutcome;
}
private static void findBestMove(String[][] board) {
    double bestMove = Double.NEGATIVE_INFINITY;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
             if (board[i][j].equals(" ")) {
                 board[i][j] = "O";
                 double score = minimax(board, false);
                 board[i][j] = " ";
                 if (score > bestMove) {
                      bestMove = score;
                      r = i;
                      c = j;
                 }
             }
         }
     }
}

private static double minimax(String[][] board, boolean comp) {
    if (playerWon(board)) {
        return -1;
    }
    if (compWon(board)) {
        return 1;
    }
    if (tie(board)) return 0;

    double bestScore;
    if (comp) {
         bestScore = Double.NEGATIVE_INFINITY;
         for (int i = 0; i < 3; i++) {
             for (int j = 0; j < 3; j++) {
                 if (board[i][j].equals(" ")) {
                    board[i][j] = "O";
                    double score = minimax(board, false);
                    board[i][j] = " ";
                    bestScore = Math.max(score, bestScore);
                 }
             }
         }
    } else {
         bestScore = Double.POSITIVE_INFINITY;
         for (int i = 0; i < 3; i++) {
              for (int j = 0; j < 3; j++) {
                  if (board[i][j].equals(" ")) {
                      board[i][j] = "X";
                      double score = minimax(board, true);
                      board[i][j] = " ";
                      bestScore = Math.min(score, bestScore);
                  }
              }
          }
     }
     return bestScore;
}
private static void findBestMove(String[]board){
double bestMove=double.NEGATIVE_无穷大;
对于(int i=0;i<3;i++){
对于(int j=0;j<3;j++){
if(board[i][j].等于(“”){
董事会[i][j]=“O”;
双倍分数=最小最大值(板,假);
董事会[i][j]=”;
如果(得分>最佳移动){
最佳移动=得分;
r=i;
c=j;
}
}
}
}
}
专用静态双极小极大值(字符串[][]板,布尔复合){
国际单项体育联合会(球员名单){
返回-1;
}
国际单项体育联合会(康普旺(董事会)){
返回1;
}
if(tie(board))返回0;
双倍最佳成绩;
如果(公司){
bestScore=双负无穷大;
对于(int i=0;i<3;i++){
对于(int j=0;j<3;j++){
if(board[i][j].等于(“”){
董事会[i][j]=“O”;
双倍分数=最小最大值(板,假);
董事会[i][j]=”;
bestScore=Math.max(分数,bestScore);
}
}
}
}否则{
bestScore=双正无穷大;
对于(int i=0;i<3;i++){
对于(int j=0;j<3;j++){
if(board[i][j].等于(“”){
板[i][j]=“X”;
双倍分数=最小最大值(板,真);
董事会[i][j]=”;
bestScore=Math.min(分数,bestScore);
}
}
}
}
返回最佳分数;
}

我将minimax算法从nextmove坐标设置器中抽象出来,我认为这可能会有所不同。除此之外,它非常相似。

我还没有对它进行广泛的测试,但我相信我解决了这个问题。新代码如下所示:

private static int findBestMove(String[][] board, boolean comp) {
    // comp returns true if the computer is the one looking for the best move
    // findBestMove is always called by the program as findBestMove(board, true)
    // since the computer is the only one that uses it

    // If the board in its current state is a win for the
    // player, return -1 to indicate a loss
    if (playerWon(board)) return -1;

    // If the board in its current state is a win for the
    // computer, return 1 to indicate a win
    if (compWon(board)) return 1;

    // If the board in its current state is a tie
    // return 0 to indicate a tie
    if (tie(board)) return 0;

    // Set the default possible outcome as the opposite of what
    // the respective player wants
    int bestPossibleOutcome = comp ? -1 : 1;

    // Loop through the board looking for empty spaces
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++)

            // Once an empty space is found, create a copy of the board
            // with that space occupied by the respective player 
            if (board[i][j].equals(" ")) {
                String[][] newBoard = new String[3][3];
                for (int a = 0; a < 3; a++) {
                    System.arraycopy(board[a], 0, newBoard[a], 0, 3);
                }
                newBoard[i][j] = comp ? "O" : "X";

                // Recursively call findBestMove() on this copy
                // and see what the outcome is
                int outCome = findBestMove(newBoard, !comp);

                // If this is the computer's turn, and the outcome
                // is higher than the value currently stored as the
                // best, replace it
                if (comp && outCome > bestPossibleOutcome) {
                    bestPossibleOutcome = outCome;


                    // r and c are instance variables that store the row
                    // and column of what the computer's next move should be
                    r = i;
                    c = j;


                // If this is the player's turn, and the outcome
                // is lower than the value currently stored as the
                // best, replace it
                } else if (!comp && outCome < bestPossibleOutcome) {
                    bestPossibleOutcome = outCome;
                }
            }
        }
    }
    // Return the ultimate value deemed to be the best
    return bestPossibleOutcome;
}
private static void findBestMove(String[][] board) {
    double bestMove = Double.NEGATIVE_INFINITY;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
             if (board[i][j].equals(" ")) {
                 board[i][j] = "O";
                 double score = minimax(board, false);
                 board[i][j] = " ";
                 if (score > bestMove) {
                      bestMove = score;
                      r = i;
                      c = j;
                 }
             }
         }
     }
}

private static double minimax(String[][] board, boolean comp) {
    if (playerWon(board)) {
        return -1;
    }
    if (compWon(board)) {
        return 1;
    }
    if (tie(board)) return 0;

    double bestScore;
    if (comp) {
         bestScore = Double.NEGATIVE_INFINITY;
         for (int i = 0; i < 3; i++) {
             for (int j = 0; j < 3; j++) {
                 if (board[i][j].equals(" ")) {
                    board[i][j] = "O";
                    double score = minimax(board, false);
                    board[i][j] = " ";
                    bestScore = Math.max(score, bestScore);
                 }
             }
         }
    } else {
         bestScore = Double.POSITIVE_INFINITY;
         for (int i = 0; i < 3; i++) {
              for (int j = 0; j < 3; j++) {
                  if (board[i][j].equals(" ")) {
                      board[i][j] = "X";
                      double score = minimax(board, true);
                      board[i][j] = " ";
                      bestScore = Math.min(score, bestScore);
                  }
              }
          }
     }
     return bestScore;
}
private static void findBestMove(String[]board){
double bestMove=double.NEGATIVE_无穷大;
对于(int i=0;i<3;i++){
对于(int j=0;j<3;j++){
if(board[i][j].等于(“”){
董事会[i][j]=“O”;
双倍分数=最小最大值(板,假);
董事会[i][j]=”;
如果(得分>最佳移动){
最佳移动=得分;
r=i;
c=j;
}
}
}
}
}
专用静态双极小极大值(字符串[][]板,布尔复合){
国际单项体育联合会(球员名单){
返回-1;
}
国际单项体育联合会(康普旺(董事会)){
返回1;
}
if(tie(board))返回0;
双倍最佳成绩;
如果(公司){
bestScore=双负无穷大;
对于(int i=0;i<3;i++){
对于(int j=0;j<3;j++){
if(board[i][j].等于(“”){
董事会[i][j]=“O”;
双倍分数=最小最大值(板,假);
董事会[i][j]=”;
bestScore=Math.max(分数,bestScore);
}
}
}
}否则{
bestScore=双正无穷大;
对于(int i=0;i<3;i++){
对于(int j=0;j<3;j++){
if(board[i][j].等于(“”){
板[i][j]=“X”;
双倍分数=最小最大值(板,真);
董事会[i][j]=”;
bestScore=Math.min(分数,bestScore);
}
}
}
}
返回最佳分数;
}

我将minimax算法从nextmove坐标设置器中抽象出来,我认为这可能会有所不同。否则,情况就非常相似。

嘿!编写一些单元测试或使用调试器可能是个好主意。这样做是发现代码中的问题的好方法。是一篇关于编写简单测试的教程。@akuzminykh由于所有的方法调用,我对使用类似递归方法的调试器有点犹豫。我正在使用IntelliJ,有没有办法使用IntelliJ调试器来调试这样的递归方法,而不必花费数小时来拼凑数百万个可能的调用?调试是痛苦的,这不是秘密。但有时,如果您想解决问题,而不必花费数小时查看代码并侥幸找到它,您就必须这样做。我建议用较小的输入运行程序,并检查它所做的一切,以发现错误的行为。遗憾的是,你的程序没有真正的输入;你必须调试。但是考虑我的第二个建议,写一些单元测试。这是发现错误的非常有效的方法。此外,在软件工程中,擅长测试是一项非常有价值的技能。训练这种技能从来没有错。有什么更新吗?你发现问题了吗?老实说,我还没有真正参与这个项目。我对编程真的很陌生,我在高中唯一的经历就是学习CS课程,我认为minimax算法可能比我的工资等级高一点。嘿!编写一些单元测试或使用调试器可能是个好主意。这样做是发现代码中的问题的好方法。是一篇关于编写简单测试的教程。@akuzminykh由于所有的方法调用,我对使用类似递归方法的调试器有点犹豫。我正在使用IntelliJ,有没有办法使用IntelliJ调试器来调试rec