【发布时间】: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