Minimax算法意外地表现

时间:2014-12-24 13:18:59

标签: java tic-tac-toe minimax

我正在尝试为Tic Tac Toe实现Minimax算法,并且似乎无法让它正确运行。我曾多次尝试重写它,但它没有给出正确的输出。

这是实现游戏的 MinimaxGame.java 的代码 -

public class MinimaxGame {
    public MinimaxResult play(MinimaxBoard board)   {
        ArrayList<Position> possibleMoves = board.getAllPossibleMoves();
        MinimaxBoard bestChild = null;
        int bestScore= Integer.MIN_VALUE;

        for (Position position : possibleMoves) {
            MinimaxBoard child = new MinimaxBoard((MinimaxBoard)board.clone(), position, 'O');
            int moveScore = max(child);

            if (moveScore > bestScore)  {
                bestChild = child;
                bestScore = moveScore;
            }
        }

        MinimaxResult result = new MinimaxResult(bestChild, bestScore);
        return result;
    }

    private int max(MinimaxBoard child) {
        ArrayList<Position> possibleMoves = child.getAllPossibleMoves();
        if (possibleMoves.isEmpty())    {
            int score = evaluateScore(child);
            return score;
        }

        int bestScore = Integer.MIN_VALUE;
        for (Position position : possibleMoves) {
            MinimaxBoard currentChild = new MinimaxBoard((MinimaxBoard)child.clone(), position, 'X');
            int moveScore = min(currentChild);

            if (moveScore > bestScore ) {
                bestScore = moveScore;
            }
        }

        return bestScore;
    }

    private int min(MinimaxBoard child) {
        ArrayList<Position> possibleMoves = child.getAllPossibleMoves();
        if (possibleMoves.isEmpty())    {
            int score = evaluateScore(child);
            return score;
        }

        int bestScore = Integer.MAX_VALUE;
        for (Position position : possibleMoves) {
            MinimaxBoard currentChild = new MinimaxBoard((MinimaxBoard)child.clone(), position, 'O');
            int moveScore = max(currentChild);

            if (moveScore < bestScore ) {
                bestScore = moveScore;
            }
        }

        return bestScore;
    }

    private boolean hasWon(MinimaxBoard board, char player) {
        boolean status = false;
        char [][] boardArray = board.boardArray;

        // Check rows
        for (int i = 0; i < 3; i++) {
            status |= (boardArray[i][0] == player) && (boardArray[i][1] == player) && (boardArray[i][2] == player);
            if (status) {
                return true;
            }
        }

        // Check columns
        for (int i = 0; i < 3; i++) {
            status |= (boardArray[0][i] == player) && (boardArray[1][i] == player) && (boardArray[2][i] == player);
            if (status) {
                return true;
            }
        }

        // Check left diagonal
        status |= (boardArray[0][0] == player) && (boardArray[1][1] == player) && (boardArray[2][2] == player);
        if (status) {
            return true;
        }

        // Check right diagonal
        status |= (boardArray[0][2] == player) && (boardArray[1][1] == player) && (boardArray[2][0] == player);
        if (status) {
            return true;
        }

        return false;
    }


    // The function simply returns a score of +1 if computer wins, -1 if the user wins,
    // and 0 in case of a draw.
    private int evaluateScore(MinimaxBoard board)   {
        if (hasWon(board, 'X')) {
            return -1;
        }
        else if (hasWon(board, 'O'))    {
            return 1;
        }

        return 0;
    }

    // Main method included for debugging purposes
    public static void main(String args[])  {
        Board sampleBoard = new Board();
        sampleBoard.setState("----X----");
        MinimaxBoard minimaxBoard = new MinimaxBoard(sampleBoard);

        MinimaxGame game = new MinimaxGame();
        MinimaxResult result = game.play(minimaxBoard);

        Board updatedBoard = result.getUpdatedBoard().getBoard();
        System.out.println(updatedBoard.getState());
    }
}

很明显,我试图用这个初始字符串执行它 -

"----X----"

我得到的输出就是这个 -

"OOOOXOOOO"

不是以最佳的动作做出回应,而是以这种超级奇怪的方式表现出来并且放置一个&#39; O&#39;在每个空位。 我已经尝试过调试代码,但我仍然不知道代码出了什么问题。我无法弄清楚问题出在哪里。

有人可以帮帮我吗?提前谢谢。

修改 -

以下是 MinimaxBoard.java 的代码,其中我也实现了clone()方法。但是,输出仍然是一样的。谁能告诉我为什么?

public class MinimaxBoard implements Cloneable {
public char[][] boardArray;

public MinimaxBoard(Board board)    {
    boardArray = convertBoardTo2D(board.getState());
}

public MinimaxBoard(MinimaxBoard board, Position position, char player) {
    this.boardArray = board.boardArray;
    boardArray[position.row][position.coloumn] = player;
}

public Board getBoard() {
    Board board = new Board();

    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < boardArray.length; i++) {
        builder.append(String.valueOf(boardArray[i]));
    }

    board.setState(builder.toString());
    return board;
}

public char[][] convertBoardTo2D(String boardString)    {
    char[][] boardArray = new char[3][3];
    char[] chars = boardString.toCharArray();
    if (chars.length == 9) {
      for (int i = 0; i < chars.length; i++) {
        boardArray[i/3][i%3] = chars[i];
      }
    }

    return boardArray;
}

public ArrayList<Position> getAllPossibleMoves() {
    ArrayList<Position> allMoves = new ArrayList<Position>();

    for(int i = 0; i < 3; i++)  {
        for(int j = 0; j < 3; j++)  {
            if(boardArray[i][j] == '-') {
                allMoves.add(new Position(i, j));
            }
        }
    }

    return allMoves;
}

@Override
public Object clone()   {
    try {
        return (MinimaxBoard)super.clone();
    }
    catch(CloneNotSupportedException e) {
        return null;
    }
}

}

1 个答案:

答案 0 :(得分:0)

我认为你必须克隆你的电路板。在你的情况下,你设置&#39; 0&#39; 0在所有可能的位置

MinimaxBoard child = new MinimaxBoard(board, position, 'O');

你必须改为

MinimaxBoard child = new MinimaxBoard(board.clone(), position, 'O');

并在Board类中实现clone()方法

克隆实施示例:

@Override
public Object clone()   {
    try {
        MinimaxBoard cloned = (MinimaxBoard)super.clone();
        cloned.boardArray = (char[][])boardArray.clone();
        for(int row=0; row< cloned.boardArray.length;row++)
            cloned.boardArray[row] = (char[])boardArray[row].clone();
        return cloned;
    }
   catch(CloneNotSupportedException e) {
        return null;
    }
}

}