简体   繁体   中英

miniMax algorithm in Java

I'm currently not satisfied with the AI I'm programming. The AI is supposed to get the best score for each move in a 3x3 board (TicTacToe).

The possible scores are -1 (Lose), 0 (Tie) and 1 (Win).

First the method makeTurn() is called, which then calls the method containing the miniMax algorithm.

public void makeTurn(Button[][] currentBoard) {                                                 // Calculating best move using miniMax algorithm
        AIcheck = new Check(currentBoard);
        int bestScore = Integer.MIN_VALUE;
        int[] bestMove = new int[2];
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (currentBoard[i][j].getText().equals("")) {
                    currentBoard[i][j].setText("O");
                    int score = calcScore(currentBoard, 0, false);
                    System.out.println(score);
                    currentBoard[i][j].setText("");
                    if (score > bestScore) {
                        bestScore = score;
                        bestMove = new int[]{i, j};

                    }
                }
            }
        }
        Board.getInstance().getField(bestMove[0], bestMove[1]).performClick();
    }

private int calcScore(Button[][] currentBoard, int depth, boolean isMax) {                      // MiniMax Algorithm, calculating score for each branch via recursive execution
        int score;
        if (AIcheck.checkWin()) {
            return (Util.getInstance().getTurnCounter() % 2) == 0 ? 1 : -1;
        } else if (AIcheck.checkTie()) {
            return 0;
        }
        int bestScore = isMax ? Integer.MIN_VALUE : Integer.MAX_VALUE;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (currentBoard[i][j].getText().equals("")) {
                    if (isMax) {
                        currentBoard[i][j].setText("O");
                    } else {
                        currentBoard[i][j].setText("X");
                    }
                    score = calcScore(currentBoard, depth + 1, !isMax);
                    currentBoard[i][j].setText("");
                    bestScore = isMax ? Math.max(bestScore, score) : Math.min(bestScore, score);
                }
            }
        }
        return bestScore;
    }

I'm using isMax to determine if it's the maximizer's turn or not, also using turnCounter % 2 to determine which player's turn it is, since they take turns.

Yet still the AI is not preventing my win, it more of seems like it just goes from one field to next, instead of choosing the optimal field. How would I be able to implement the miniMax algorithm properly? Thanks a lot!

Example:

[]|[]|[]

[]|[]|[]

[X]|[]|[]


[O]|[]|[]

[]|[]|[]

[X]|[]|[]


[O]|[]|[]

[]|[]|[]

[X]|[]|[X]


[O]|[O]|[]

[]|[]|[]

[X]|[]|[X]


[O]|[O]|[X]

[]|[]|[]

[X]|[]|[X]


[O]|[O]|[X]

[O]|[]|[]

[X]|[]|[X]


[O]|[O]|[X]

[O]|[X]|[] I win, also it shows how the AI seems to just take the next spot (from left to right)

[X]|[]|[X]

I think the problem is how you determine who won in calcScore . You use Util.getInstance().getTurnCounter() , but you don't seem to be updating the counter in the recursive calls. You can instead just use depth % 2 or isMax for that:

if (AIcheck.checkWin()) {
    return isMax ? -1 : 1;
}

I think the problem is this line in calcScore()

if (currentBoard[i][j].getText().equals("")) {

You're only calculating the score if the board is empty, but you always set it to "0" before calling the function, so the code block for that if will never be executed.

makeTurn() is similar, but I guess you're clearing the boards between turns? If not you need to update this as well.

Edit: in the main function:

                    currentBoard[i][j].setText("O");
                    int score = calcScore(currentBoard, 0, false);

in calcScore:

// this will always evaluate to false
if (currentBoard[i][j].getText().equals("")) {

There is a problem with your bestScore assignment. For each empty box you do this:

int bestScore = isMax ? Integer.MIN_VALUE : Integer.MAX_VALUE;

If you calculate it like this, you will always end up with the same scores, which might be the reason it only selects the next empty box. In a minimax algorithm, you need a way to assigning different score values for each move so you can find the best move through comparation. In a chess game or something similar, these scores are usually given through some heuristics. Since your game is much simpler, this should be easier. A simple solution might be to assign a different score to each board state and you can simply select the moves that lead to this desired state. You can easily do this since the number of these states is very limited in your game.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM