Search code examples
c#algorithmminimaxalpha-beta-pruning

Minimax works fine but Alpha-beta pruning doesn't


I'm trying to get Alpha-beta pruning to work but it's giving me completely wrong moves compared to my Minimax function. Here is my Minimax function which is working perfectly right now.

float Minimax(char[,] _board, int depth, bool isMax) {
    if (depth == 0 || isFull(_board)) {
        EvaluateBoard(_board);
    }

    if (isMax) {
        float bestScore = -Mathf.Infinity;
        float score = -Mathf.Infinity;

        for (int i = 0; i < 7; i++) {
            char[,] board = (char[, ]) _board.Clone();
            if (Play(board, i, false)) {
                score = Minimax(board, depth - 1, false);
                bestScore = Mathf.Max(score, bestScore);
            }
        }
        return bestScore;
    } else {
        float bestScore = Mathf.Infinity;
        float score = Mathf.Infinity;

        for (int i = 0; i < 7; i++) {
            char[,] board = (char[, ]) _board.Clone();
            if (Play(board, i, true)) {
                score = Minimax(board, depth - 1, true);
                bestScore = Mathf.Min(score, bestScore);
            }
        }
        return bestScore;
    }
}

and here is my Alphabeta pruning function

float ABPruning(char[,] _board, int depth, float alpha, float beta, bool isMax) {
    if (depth == 0 || isFull(_board)) {
        return EvaluateBoard(_board);
    }
    if (isMax) {
        float bestScore = -Mathf.Infinity;
        
        for (int i = 0; i < 7; i++) {
            char[, ] board = (char[,]) _board.Clone();
            if (Play(board, i, false)) {
                bestScore = ABPruning(board, depth - 1, alpha, beta, false);
                alpha = Mathf.Max(alpha, bestScore);
                if (beta<=alpha) {
                    return bestScore;
                }

            }
        }
        return bestScore;
    } else {
        float bestScore = Mathf.Infinity;

        for (int i = 0; i < 7; i++) {
            char[, ] board = (char[,]) _board.Clone();
            if (Play(board, i, true)) {
                bestScore = ABPruning(board, depth - 1, alpha, beta, true);
                beta = Mathf.Min(beta, bestScore);
                if (beta<=alpha) {
                    break;
                }

            }
        }
        return bestScore;
    }
}

Both are using same evaluations, not sure what's wrong here. Thank you for your help.


Solution

  • It's unclear whether you are trying to implement the Fail-hard or Fail-soft methods, but I think that it's the later. If so, then while i cannot test this for you, I think that this is what you want:

    float ABPruning(char[,] _board, int depth, float alpha, float beta, bool isMax) {
        if (depth == 0 || isFull(_board)) {
            return EvaluateBoard(_board);
        }
        if (isMax) {
            float bestScore = -Mathf.Infinity;
            
            for (int i = 0; i < 7; i++) {
                char[, ] board = (char[,]) _board.Clone();
                if (Play(board, i, false)) {
                    bestScore = Mathf.Max(bestScore, ABPruning(board, depth - 1, alpha, beta, false));
                    alpha = Mathf.Max(alpha, bestScore);
                    if (bestScore>=beta) {
                        break;
                    }
                }
            }
            return bestScore;
        } else {
            float bestScore = Mathf.Infinity;
    
            for (int i = 0; i < 7; i++) {
                char[, ] board = (char[,]) _board.Clone();
                if (Play(board, i, true)) {
                    bestScore = Mathf.Min(bestScore, ABPruning(board, depth - 1, alpha, beta, true));
                    beta = Mathf.Min(beta, bestScore);
                    if (bestScore<=alpha) {
                        break;
                    }
                }
            }
            return bestScore;
        }
    }