用于 alpha-beta 修剪的树通常是隐式的。这是一种防止您的 AI 搜索算法将时间浪费在错误解决方案上的方法。这是来自维基百科的伪代码:
function alphabeta(node, depth, α, β, Player)
if depth = 0 or node is a terminal node
return the heuristic value of node
if Player = MaxPlayer
for each child of node
α := max(α, alphabeta(child, depth-1, α, β, not(Player) ))
if β ≤ α
break (* Beta cut-off *)
return α
else
for each child of node
β := min(β, alphabeta(child, depth-1, α, β, not(Player) ))
if β ≤ α
break (* Alpha cut-off *)
return β
(* Initial call *)
alphabeta(origin, depth, -infinity, +infinity, MaxPlayer)
该函数递归地评估棋盘位置。“节点”是当前位置,它所说的“对于节点的每个子节点”是您生成新棋盘位置的位置,这些新棋盘位置是由当前位置的每个可能移动产生的。深度参数控制您想要评估树的距离,因为分析移动到无限深度可能是不切实际的。
尽管如此,如果您必须在出于教育目的修剪之前构建一棵给定深度的树,那么具有可变数量子节点的树的结构非常简单,可能看起来像这样:
struct Node
{
Node ** children;
int childCount;
double value;
};
Node * tree;
这children
是一个带有 childCount 成员的 Node 数组。叶节点将具有childCount=0
. 要构建树,您将搜索可用的板位置,如下所示:
Node * CreateTree(Board board, int depth)
{
Node * node = new Node();
node.childCount = board.GeAvailableMoveCount();
node.value = board.GetValue;
if (depth > 0 && node.childCount > 0)
{
node.children = new Node * [node.childCount];
for (int i = 0; i != node.childCount; ++i)
node.children[i] = CreateTree(board.Move(i), depth - 1);
}
else
{
node.children = NULL;
}
return node;
}
void DeleteTree(Node * tree)
{
for (int i = 0; i != tree.childCount; ++i)
DeleteTree(tree.children[i]);
delete [] tree.children; // deleting NULL is OK
delete tree;
}