Minimax Alpha Beta 剪枝不工作,但 Minimax 单独工作

问题描述

我的问题是在将 Alpha/Beta 剪枝应用于 Minimax 时。它会做出非常奇怪和糟糕的动作。当我在没有 Alpha/Beta 的情况下使用 Minimax 时,它工作正常。这两个函数看起来像这样:

带 Alpha/Beta 剪枝的极小极大:

public int minimaxAB(Piece[,] board,int depth,int a,int b,bool maximizingPlayer,bool WhitetoPlay)
{
    if (depth == 0)
    {
        return EvaluatePosition(board,WhitetoPlay);
    }

    var moves = GenerateMoves(board,WhitetoPlay);
    if (maximizingPlayer)
    {
        int value = int.MinValue;
        foreach (var move in moves)
        {
            int minmaxResult = minimaxAB(move,depth - 1,a,b,false,!WhitetoPlay);
            value = Math.Max(value,minmaxResult);

            a = Math.Max(a,value);

            if (a >= b)
                return a;

            if (depth == depthB)
            {
                movescores.Add(move,minmaxResult);
            }
        }
        return value;
    }
    else
    {
        int value = int.MaxValue;
        foreach (var move in moves)
        {
            int minmaxResult = minimaxAB(move,true,!WhitetoPlay);
            value = Math.Min(value,minmaxResult);

            b = Math.Min(b,value);

            if (b <= a)
                return b;

            if (depth == depthB)
            {
                movescores.Add(move,minmaxResult);
            }
        }
        return value;
    }
}

无 A/B 的极小极大:

public int minimax(Piece[,bool WhitetoPlay)
{
    if (depth == 0)
    {
        int result = EvaluatePosition(board,WhitetoPlay);
        return result;
    }

    var moves = GenerateMoves(board,WhitetoPlay);
    if (maximizingPlayer)
    {
        int value = int.MinValue;
        foreach (var move in moves)
        {
            int minmaxResult = minimax(move,minmaxResult);
            if (depth == depthB)
            {
                movescores.Add(move,minmaxResult);
            }
        }
        return value;
    }
    else
    {
        int value = int.MaxValue;
        foreach (var move in moves)
        {
            int minmaxResult = minimax(move,minmaxResult);
            }
        }
        return value;
    }
}

我的评价函数

public int EvaluatePosition(Piece[,] boardPos,bool ForWhite)
{
    int eval_W = 0;
    int eval_B = 0;
    int eval = 0;
    for (int i = 0; i < 8; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            if (boardPos[i,j] != Piece.Empty)
            {
                if (IsPieceWhite(boardPos[i,j]))
                {
                    eval_W += GetPieceWorth(boardPos[i,j]) + distancetoCenter(i,j);
                    eval += GetPieceWorth(boardPos[i,j]);
                }
                else if (IsPieceBlack(boardPos[i,j]))
                {
                    eval_B += GetPieceWorth(boardPos[i,j);
                    eval -= GetPieceWorth(boardPos[i,j]);
                }
            }
        }
    }

    if (ForWhite)
        return eval_W - eval_B;
    else
        return eval_B - eval_W;
}

我打电话给:minimaxAB(CurrentBoard,depthB,int.MinValue,int.MaxValue,whitetoMove);

我知道带 AB 的 Minimax 应该产生完全相同的结果,但在我的情况下它没有。我希望有人能够发现我做错了什么。

解决方法

我想通了,我需要白色和黑色的 alpha 和 beta。这样做的原因是我为白棋和黑棋调用了 minimaxAB 函数。

工作方式:

public int minimaxAB(Piece[,] board,int depth,int alpha_White,int beta_White,int alpha_Black,int beta_Black,bool maximizingPlayer,bool WhiteToPlay)
{
    if (depth == 0 || !HasKings(board))
    {
        return EvaluatePosition(board,WhiteToPlay);
    }

    var moves = GenerateMoves(board,WhiteToPlay);
    if (maximizingPlayer)
    {
        int value = int.MinValue;
        foreach (var move in moves)
        {
            int minmaxResult = minimaxAB(move,depth - 1,alpha_White,beta_White,alpha_Black,beta_Black,false,!WhiteToPlay);
            value = Math.Max(value,minmaxResult);

            if (WhiteToPlay)
            {
                alpha_White = Math.Max(alpha_White,value);
                if (alpha_White >= beta_White)
                    return alpha_White;
            }
            else
            {
                alpha_Black = Math.Max(alpha_Black,value);
                if (alpha_Black >= beta_Black)
                    return alpha_Black;
            }

            if (depth == depthB)
            {
                moveScores.Add(move,minmaxResult);
            }
        }
        return value;
    }
    else
    {
        int value = int.MaxValue;
        foreach (var move in moves)
        {
            int minmaxResult = minimaxAB(move,true,!WhiteToPlay);
            value = Math.Min(value,minmaxResult);

            if (WhiteToPlay)
            {
                beta_White = Math.Min(beta_White,value);
                if (beta_White <= alpha_White)
                    return beta_White;
            }
            else
            {
                beta_Black = Math.Min(beta_Black,value);
                if (beta_Black <= alpha_Black)
                    return beta_Black;
            }
            if (depth == depthB)
            {
                moveScores.Add(move,minmaxResult);
            }
        }
        return value;
    }
}

调用方式:

minimaxAB(CurrentBoard,depthB,int.MinValue,int.MaxValue,whiteToMove);