【问题标题】:Returning moves with MiniMax使用 MiniMax 返回动作
【发布时间】:2015-01-05 23:00:31
【问题描述】:

我的代码正常运行,程序运行完美!原来问题还涉及计算机在需要时没有返回 0。感谢所有帮助过的人。如果有人像我一样需要任何帮助,请查看下面的代码。

import java.util.Scanner;

    public class TicTacToeSolver{
        public static void main(String[] args){
            Scanner input=new Scanner(System.in);

            char[] board={0,0,0,0,0,0,0,0,0};
            int player=1,move;

            System.out.println("Tic-Tac-Toe:");
            while (true){
                PrintBoard(board);   
                if (player==1){
                    System.out.print("Enter move: ");
                    move=input.nextInt();
                    if (ValidMove(board,move)==true){
                        board[move-1]='X';
                        player=-1;
                    }   
                }
                else{
                    board[MiniMax(board,player,0,9)[1]]='O';
                    player=1;
                }
                if(CheckWin(board)!=0){
                    PrintBoard(board);
                    System.out.println("You lost!");
                    System.exit(0);
                }
                else if (CheckDraw(board)==true){
                    PrintBoard(board);
                    System.out.println("Draw!");
                    System.exit(0);
                }
            }
        }
        public static boolean ValidMove(char[]board,int move){
            if(move>=1 && move<=9){
                if (board[move-1]==0){
                    return true;
                }
            }
            return false;
        }
        public static int CheckWin(char[] board){
            if (board[0]=='X' && board[1]=='X' && board[2]=='X'||//Horizontal.
                    board[3]=='X' && board[4]=='X' && board[5]=='X' ||
                    board[6]=='X' && board[7]=='X' && board[8]=='X' ||
                    board[0]=='X' && board[4]=='X' && board[8]=='X' ||//Diagonal.
                    board[2]=='X' && board[4]=='X' && board[6]=='X' ||
                    board[0]=='X' && board[3]=='X' && board[6]=='X' ||//Vertical.
                    board[1]=='X' && board[4]=='X' && board[7]=='X' ||
                    board[2]=='X' && board[5]=='X' && board[8]=='X'){
                return -1;
            }
            else if (board[0]=='O' && board[1]=='O' && board[2]=='O'||//Horizontal.
                    board[3]=='O' && board[4]=='O' && board[5]=='O' ||
                    board[6]=='O' && board[7]=='O' && board[8]=='O' ||
                    board[0]=='O' && board[4]=='O' && board[8]=='O' ||//Diagonal.
                    board[2]=='O' && board[4]=='O' && board[6]=='O' ||
                    board[0]=='O' && board[3]=='O' && board[6]=='O' ||//Vertical.
                    board[1]=='O' && board[4]=='O' && board[7]=='O' ||
                    board[2]=='O' && board[5]=='O' && board[8]=='O'){
                return 1;
            }
            return 0;
        }
        public static boolean CheckDraw(char[] board){
            int total=0;
            for (int i=0;i<9;i++){
                if (board[i]!=0){
                    total+=1;
                }
            }
            if (total==9){
                return true;
            }
            return false;
        }
        public static void PrintBoard(char[] board){   
            System.out.println("------------------------------");
            System.out.println(board[0]+"|"+board[1]+"|"+board[2]);
            System.out.println("-+-+-");
            System.out.println(board[3]+"|"+board[4]+"|"+board[5]);
            System.out.println("-+-+-");
            System.out.println(board[6]+"|"+board[7]+"|"+board[8]); 
            System.out.println("\n");
        }
        public static int[] MiniMax(char[] board,int player,int depth, int maxDepth){
            int bestScore,bestMove=-1,score;

            if (CheckWin(board)!=0||depth==maxDepth){
                return new int[] {CheckWin(board),bestMove};
            }
            if (CheckDraw(board)==true){
                return new int[] {0,bestMove};
            }   
            if (player==-1){
                bestScore=-9999;
            }
            else{
                bestScore=9999;
            }
            for (int i=0;i<9;i++){
                if (board[i]==0){
                    if (player==-1){
                        board[i]='O';
                        score=MiniMax(board,player*-1,depth+1,maxDepth)[0];
                        board[i]=0;

                        if (score>bestScore){
                            bestScore=score;
                            bestMove=i;
                        }
                    }
                    else{
                        board[i]='X';
                        score=MiniMax(board,player*-1,depth+1,maxDepth)[0];
                        board[i]=0;

                        if(score<bestScore){
                            bestScore=score;
                            bestMove=i;
                        }
                    }
                }
            }
            return new int[] {bestScore,bestMove};
        }
    }

【问题讨论】:

    标签: java recursion tic-tac-toe minimax


    【解决方案1】:

    我想我已经在其他地方回答过这个问题,所以你们中一定有几个人在做这个任务!在第一个级别以下,您应该只检查以下级别是否返回任何获胜动作。您不需要使用它们的任何值。示例代码:

    public List<Location> bestMoves() {
        List<Location> winningMoves = possibleMoves().stream()
                .filter(move -> apply(move).isWinFor(nextPlayer))
                .collect(Collectors.toList());
        if (!winningMoves.isEmpty())
            return winningMoves;
        else
            return possibleMoves().stream()
                    .filter(move -> apply(move).bestMoves().isEmpty())
                    .collect(Collectors.toList());
    }
    

    【讨论】:

      【解决方案2】:

      您可以通过包含两者的对象同时返回移动和分数。

      public class TicTacToeSolver{
          private static class Move {
              int move;
              int score;
              Move( int m, int s ) {
                 move = m;
                 score = s;
              }
          }
          ...
       }
      

      你可以像这样返回这个对象:

       return new Move( bestScore, bestMove );
      

      在 minimax() 本身内,你可以得到这样的分数:

      Move candidateMove = MiniMax(board,player*-1,depth+1,maxDepth);
      int score = candidateMove.score;
      

      在顶层,你可以像这样得到最好的移动:

       Move bestMove = MiniMax(board,player,0,9);
       int move = bestMove.move;
      

      【讨论】:

      • 感谢您抽出宝贵时间帮助我。我相信我正确地实施了您的建议,并且我确实看到了决策方面的一些重大改进,但它仍然存在重大缺陷。如果您可以再看一下更新后的代码,那就太棒了。
      • @ReconMa - 我知道这是你的第一个问题。欢迎来到stackoverflow。请务必浏览stackoverflow.com/tour的简介。您可以提出具体问题并投票选出有帮助的答案。请说明“主要缺陷”,并考虑这些是否是一个单独的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-14
      • 1970-01-01
      • 1970-01-01
      • 2020-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多