我正在编写一个简单的游戏引擎,可以玩像Chess和Checkers这样的游戏,我不确定我是否正确实现了alpha beta函数的根方法。这是常规功能:
double AlphaBeta(GameState gameState, int depth, double a, double b)
{
if (depth == 0 || gameState.IsOver)
return Evaluate(gameState);
var moves = gameState.GetMoves();
var bestValue = double.MinValue;
foreach (Move move in moves)
{
double value = -AlphaBeta(gameState.MakeMove(move), depth - 1, -b, -a);
bestValue = Math.Max(value, bestValue);
a = Math.Max(value, a);
if (a >= b)
break;
}
return bestValue;
}
此处Evaluate方法始终从具有转弯的玩家的角度返回值,MakeMove返回原始游戏状态的副本并进行移动。但我不知道如何处理root函数。这就是我现在所拥有的:
Move AlphaBetaRoot(GameState gameState, int depth)
{
var moves = gameState.GetMoves();
moves = moves.OrderBy(o => AlphaBeta(gameState.MakeMove(o), depth - 1, double.MinValue, double.MaxValue)).ToList();
return moves[0];
}
到目前为止,这似乎工作得很好(我用3x3 Tic Tac Toe测试了它),但它没有对根节点进行任何修剪。所以我想也许应该更像这样:
Move AlphaBetaRoot2(GameState gameState, int depth)
{
double a = double.MinValue;
double b = double.MaxValue;
var moves = gameState.GetMoves();
Move bestMove = null;
foreach (Move move in moves)
{
var value = -AlphaBeta(gameState.MakeMove(move), depth - 1, -b, -a);
if (value >= a)
{
a = Math.Max(value, a);
bestMove = move;
}
if (a >= b)
break;
}
return bestMove;
}
但我不能让这个工作,我不知道该怎么做。无论我改变什么,我最终会得到一些难以理解或失去动作的东西。
虽然网上有很多关于Alpha-Beta Pruning的文献和问题,但我还没有找到任何关于如何实现root方法的知识。所以,我很感激任何帮助。