【问题标题】:Minimax Alpha Beta Pruning not working, but Minimax alone doesMinimax Alpha Beta Pruning 不起作用,但 Minimax 单独起作用
【发布时间】:2021-05-13 04:51:58
【问题描述】:

我的问题是在将 Alpha/Beta Pruning 应用于 Minimax 时。它做了非常奇怪和糟糕的动作。当我使用没有 Alpha/Beta 的 Minimax 时,它可以正常工作。这两个函数如下所示:

带有 Alpha/Beta 修剪的 Minimax:

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, depth - 1, a, b, 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[,] board, int depth, bool maximizingPlayer, 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, depth - 1, false, !WhiteToPlay);
            value = Math.Max(value, minmaxResult);
            if (depth == depthB)
            {
                moveScores.Add(move, minmaxResult);
            }
        }
        return value;
    }
    else
    {
        int value = int.MaxValue;
        foreach (var move in moves)
        {
            int minmaxResult = minimax(move, depth - 1, true, !WhiteToPlay);
            value = Math.Min(value, minmaxResult);
            if (depth == depthB)
            {
                moveScores.Add(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]) + DistanceToCenter(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, true, whiteToMove);

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

【问题讨论】:

  • 不,这是一个新问题。另一个是关于极小极大的。这个是关于 alpha beta 修剪的。
  • 为什么还在使用depth == depthB?它在任何伪代码中都没有,正如您在其他问题中提到的那样,这是错误的。此外,它现在是否仅使用极小极大函数进行合法移动并下棋?
  • 'depth == depthB' 是检查当前深度是否为4的起始depthB。如果为true,则仅添加移动。这是因为极小极大实际上并不产生移动,它只是产生一个评价数字,表明该位置有多好。该代码不会以任何负面的方式干扰极小值?同样是的,它仅使用极小极大函数下得不错。一旦我添加了字母表,它下的棋就很糟糕。
  • 看伪代码,你不只是在某个深度添加一个动作。你有一整行从深度 0 到深度 MaxDepth 的移动,每次迭代都应该更新。这段代码不会产生很好的结果,极小极大也应该很奇怪。
  • 我在伪代码中看不到任何关于如何实际产生动作的内容。问题是,如果我调用 minimax,它只会返回一个值。这样我只得到了第一步的动作和值列表。

标签: c# algorithm chess minimax alpha-beta-pruning


【解决方案1】:

我想通了,我需要一个白色和黑色的 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, depth - 1, alpha_White, beta_White, alpha_Black, beta_Black, 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, int.MinValue, int.MaxValue, true, whiteToMove);

【讨论】:

  • 不,这是完全错误的......你让这种方式变得更加复杂。
  • 怎么了?我希望能够同时调用白色和黑色的方法。
  • 你将没有这个复杂的东西。也不需要depth = depthB。只需使用伪代码:en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning。调用该函数时,您会查看分数是否更好,如果是,则更新最佳移动。,
  • 我不明白。我需要什么样的代码才能调用?对于每一个可能的移动,我都调用一次 minimax 吗?
  • 您可以为当前位置的每个移动调用 minimax 到您想要的深度:'for move in possible_moves: .....'。然后,如果 minimax 返回的分数比您之前的最佳分数更好,您将更新您的最佳分数并在该循环中进行最佳移动。这是一种方法。但是,如果您想获得我在原始问题中评论的 PV 行,则需要阅读该链接。
猜你喜欢
  • 1970-01-01
  • 2021-08-29
  • 1970-01-01
  • 2021-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多