当使用Minimax进行Alpha-Beta修剪时,是否可以将alpha和beta作为类变量而不是通过递归发送它们?
而不是:
private ValuedMove AlphaBetaSearch(Board state)
{
return MaxValue(state, 0, int.MinValue, int.MaxValue);
}
private ValuedMove MaxValue(Board state, int d, int alpha, int beta)
{
if (d == depth || state.GameRunning == false)
return new ValuedMove(Heuristic.BoardValue(state, Player));
ValuedMove v = new ValuedMove(int.MinValue);
foreach (Move move in LegalMoves)
{
ValuedMove minCheck = MinValue(state.ImagineMove(move), d + 1, alpha, beta);
if (v.Value >= beta)
return v;
alpha = Max(alpha, v.Value);
}
return v;
}
private ValuedMove MinValue(Board state, int d, int alpha, int beta)
{
//Minimax and Alpha-Beta logic here
}
我可以写:
int alpha, beta;
private ValuedMove AlphaBetaSearch(Board state)
{
alpha = int.MinValue;
beta = int.MaxValue;
return MaxValue(state, 0);
}
private ValuedMove MaxValue(Board state, int d)
{
//Minimax and Alpha-Beta logic here
}
private ValuedMove MinValue(Board state, int d)
{
//Minimax and Alpha-Beta logic here
}
我在问,因为当我尝试通过这样做来优化代码时(我的想法是,如果我不需要向每次递归发送整数,我可能能够剥离一点时间),我的国际象棋选手突然变成了白痴,牺牲了他的女王杀死了一个棋子,并做了其他愚蠢的错误。
他经常表现得比他的“常规Alpha-Beta”对手差很多,我想这是因为他也只搜索树的一小部分与他的对手相比(他们都使用相同的深度,但修改后的玩家似乎修剪更积极,从而减少访问的节点数量)。我现在做了两次这样做,以确保,我不会改变任何其他东西,而不是我在这里发现的东西。
如果我理解Alpha-Beta算法是正确的,这应该没有任何区别,但对于我的国际象棋棋手来说,它确实如此。我做错了吗?
所以,我现在的主要问题不是它是优化明智还是代码实践明智的好事,而是它是否应该可行。
答案 0 :(得分:4)
你真的不能这样做。 AlphaBeta是一种递归算法。这意味着它自称。每次它自己调用它时(可能)有不同的alpha和beta值。每个递归都需要自己的变量版本,这些变量将包含不同的值。如果在类中包含变量,则只能在对AlphaBeta的所有(递归)调用之间共享一组变量。
这就是说,用类成员替换函数参数可能不是一个好的优化。这两种技术都有成本。在调用之前需要在堆栈上推送参数,并且需要通过指针(隐藏的this
指针)间接访问成员。让我们忘记哪个成本越高。这种微观优化可能太微不足道了,根本没有任何区别。