Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Minimax Alpha-Beta修剪不起作用,但Minimax单独起作用_C#_Algorithm_Chess_Minimax_Alpha Beta Pruning - Fatal编程技术网

C# Minimax Alpha-Beta修剪不起作用,但Minimax单独起作用

C# Minimax Alpha-Beta修剪不起作用,但Minimax单独起作用,c#,algorithm,chess,minimax,alpha-beta-pruning,C#,Algorithm,Chess,Minimax,Alpha Beta Pruning,我的问题是当对Minimax应用Alpha/Beta修剪时。它的动作非常粗野和糟糕。当我使用不带Alpha/Beta的Minimax时,效果很好。这两个函数如下所示: 使用Alpha/Beta修剪的Minimax: public int minimaxAB(Piece[,] board, int depth, int a, int b, bool maximizingPlayer, bool WhiteToPlay) { if (depth == 0) { ret

我的问题是当对Minimax应用Alpha/Beta修剪时。它的动作非常粗野和糟糕。当我使用不带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;
    }
}
我的评价职能:

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;
}
public int EvaluatePosition(件号[,]boardPos,bool for white)
{
int eval_W=0;
int eval_B=0;
int eval=0;
对于(int i=0;i<8;i++)
{
对于(int j=0;j<8;j++)
{
if(boardPos[i,j]!=件空)
{
if(iPieceWhite(boardPos[i,j]))
{
eval_W+=GetPieceWorth(boardPos[i,j])+到中心的距离(i,j);
eval+=GetPieceWorth(boardPos[i,j]);
}
否则,如果(IsPieceBlack(boardPos[i,j]))
{
eval_B+=GetPieceWorth(boardPos[i,j])+到中心的距离(i,j);
eval-=GetPieceWorth(boardPos[i,j]);
}
}
}
}
如果(白色)
返回eval_W-eval_B;
其他的
返回eval_B-eval_W;
}
我用:
minimaxAB(CurrentBoard,depthB,int.MinValue,int.MaxValue,true,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, 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;
    }
}

不,这是一个新问题。另一个是关于minimax的。这是关于alpha-beta修剪的。为什么您仍然使用depth==depthB?它不在任何伪代码中,正如您在另一个问题中提到的,这是错误的。此外,它现在是否只进行合法的移动,并且只使用minimax函数下象棋?“depth==depthB”用于检查当前深度,即起始深度是否为4。然后仅在为true时添加移动。这是因为minimax实际上不产生移动,它只产生一个评估数字,指示位置有多好。该代码不会以任何负面方式干扰极小极大值?也是的,它只使用minimax函数下象棋。一旦我添加了alphabeta,它的下棋就非常糟糕。看看伪代码,你不仅仅是在某个深度添加了一个移动。您有一整行从深度0到深度MaxDepth的移动,这些移动应该在每次迭代中更新。这段代码不会产生一个好的结果,minimax应该也很奇怪。我在伪代码中没有看到任何关于如何实际产生移动的内容。问题是,如果我调用minimax,它只返回一个值。这样我只会在第一步得到一个移动和值的列表。不,这是完全错误的。。。你把这条路弄得更复杂了,怎么了?我希望能够为白色和黑色调用该方法。您将不需要这个复杂的东西。此外,不需要深度=深度。只需使用伪代码:。调用该函数时,您会看到分数是否更好,如果更好,则更新最佳移动。我不明白。我打电话需要什么样的代码?我是否为每个可能的移动调用minimax一次?您可以为当前位置的每个移动调用minimax到您所需的深度:“对于可能的移动:…”。然后,如果minimax返回的分数比您以前的最佳分数好,您将更新该循环中的最佳分数和最佳移动。这是一种方法。然而,如果你想得到我在原始问题中评论的PV线,你需要阅读该链接。
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);