我已经为Checkers实施了alpha-beta修剪,并认为我有它工作,但发现计算机不会连续多次跳转(必须时)。例如:
AI确实:
O _ _ _ _ _ _ _ _ _
_ X _ X _ -> _ _ _ X _ (misses a jump because it only does a single move)
_ _ _ _ _ _ _ O _ _
AI 应该:
O _ _ _ _ _ _ _ _ O
_ X _ X _ -> _ _ _ _ _ (sees that it's current turn is not finished, continues)
_ _ _ _ _ _ _ _ _ _
我试图通过检查MovePiece的返回值来修复它,它返回玩家是否完成了他的转弯,由移动是否是跳跃以及是否还有进一步的跳跃来确定。根据返回值,它将再次运行MaxValue / MinValue(取决于它在第一次看到进一步移动时所处的那个)或继续在树中并切换玩家。
相关代码(在C#中)如下(retVal属于包含Value,Depth和Move的类型):
foreach(var m in moves)
{
var resultingBoard = board.Clone();
var moveResult = resultingBoard.MovePiece(m.TypeOfMove,
resultingBoard.GetPieceAtPosition(m.OriginalPieceLocation.X,
m.OriginalPieceLocation.Y),
m.FinalPieceLocation.X, m.FinalPieceLocation.Y);
var newDepth = currentDepth;
if(moveResult == TurnResult.NotDone)
{
retVal = MaxValue(resultingBoard, ref alphaValue, ref betaValue, color, ref newDepth, ref maxDepth);
}
else if(moveResult == TurnResult.Finished)
{
newDepth++;
retVal = MinValue(resultingBoard, ref alphaValue, ref betaValue, color == PieceColor.Black ? PieceColor.Red : PieceColor.Black, ref newDepth, ref maxDepth);
}
}
...
然而,这导致一些......有趣的结果(第一步除了min prunes之外什么也没做),尽管我认为这是正确的改变。
让MaxValue / MinValue再次调用自己的新动作是正确的吗?
答案 0 :(得分:2)
您的minimax算法需要“生成”新动作smells (当您需要吃第二块时)。
我会尝试重新设计 - 您可以扩展move
(可迭代moves
中的元素)来制作包含移动的元组(或列表),并避开minimax算法阶段中的TurnResule.NotDone
。
使用这种方法 - 除了单次移动之外,列表moves
将被预先扩展为还包含移动(eat piece,eat piece)
。
此解决方案将使算法更加健壮,并允许您轻松进行未来修改。