0

I have a minimax algorithm with alpha beta pruning for tic-tac-toe. I have trouble adding a depth limit to how minimax evatuates the board. When I add a depth limit it only partially works. For example, if I move first in the middle, it will choose a losing position on its second move.

(Computer is O. Player is X.)
_ _ _   o _ _   o _ x   o o x
_ x _   _ x _   _ x _   _ x _
_ _ _   _ _ _   _ _ _   _ _ _

But if i begin in the first position, it works fine. It seems to be ignoring my 2-in-a-rows. If I remove the depth limit all together it works correctly all of the time. How can I add a depth limit to the algorithm that lets it work correctly all of the time? Why does it not work with a depth limit?

This is the evaluation part the without a depth limit that fully works at the top of the minimax method:

int score = evaluate(board);
//if maximizer won
if (score == 10) {
    return score;
}
//if minimizer won
if (score == -10) {
    return score;
}
if (hasCellsLeft(board) == false) {
    return 0;
}

This is the evaluation with a depth limit at the top of the method:

if (depth == 6||isGameOver(board)) {
        return evaluate(board);
}

This is the evaluation method:

public int evaluate(Cell[] board) {
    //rows across
    if (isGameOver(board) && endStates.checkWinByRow(board, playerToken) || isGameOver(board) && endStates.checkWinByColumn(board, playerToken) || isGameOver(board) && endStates.checkWinByDiagonal(board, playerToken)) {
        return 10;
    }
    if (isGameOver(board) && endStates.checkWinByRow(board, opponentToken) || isGameOver(board) && endStates.checkWinByColumn(board, opponentToken) || isGameOver(board) && endStates.checkWinByDiagonal(board, opponentToken)) {
        return -10;
    }
    else {
        return  0;
    }
}

This is the isGameOver method:

public boolean isGameOver(Cell[] board) {
    if (endStates.checkWinByRow(board, playerToken) || endStates.checkWinByColumn(board, playerToken) || endStates.checkWinByDiagonal(board, playerToken)) {
        return true;
    }
    if (endStates.checkWinByRow(board, opponentToken) || endStates.checkWinByColumn(board, opponentToken) || endStates.checkWinByDiagonal(board, opponentToken)) {
        return true;
    }
    return false;
}

Here is the minimax algorithm:

public int alphaBeta(Cell[] board, int depth, int nodeIndex, boolean isMax, int alpha, int beta) {
    if (depth == 6||isGameOver(board)) {
        return evaluate(board);
    }
    if (isMax) {
            int best = MIN;
            // Recur for left and right children
            for (int i=0; i<board.length; i++) {
                if (board[i].getToken() == Token.EMPTY) {
                    board[i].setToken(playerToken);
                    int val = alphaBeta(board, depth + 1, nodeIndex * 2 + i, false, alpha, beta);
                    //int best = beta;
                    best = Math.max(best, val);
                    alpha = Math.max(alpha, best);

                    board[i].resetMarker();

                    // Alpha Beta Pruning
                    if (beta <= alpha) {
                        break;
                    }
                }
            }
            return best;
        }
        else {
            int best = MAX;
            // Recur for left and right children
            for (int i=0; i<board.length; i++) {
                if (board[i].getToken() == Token.EMPTY) {
                    board[i].setToken(opponentToken);
                    int val = alphaBeta(board, depth + 1, nodeIndex * 2 + i, true, alpha, beta);
                    //int best = beta;
                    best = Math.min(best, val);
                    beta = Math.min(beta, best);
                    board[i].resetMarker();
                }

                // Alpha Beta Pruning
                if (beta <= alpha) {
                    break;
                }
            }
            return best;
        }


}
Zuse
  • 93
  • 1
  • 11

0 Answers0