我正和我的一位朋友一起参加人工智能方法课程,我们已经参加了最后一个项目,该项目正在编写奥赛罗& amp;使用C ++和OpenGL的AI。
到目前为止,我们已经拥有了主板和奥赛罗引擎(我正在使用MVC类型的方法)。但事实证明难以理解的一件事是人工智能。
我们应该编写一个在树上使用Alpha-Beta修剪的AI来快速计算它应该进行的下一步移动。
就游戏而言,Alpha-Beta修剪的概念,以及用于检测哪些方块比其他方块更有价值的算法。
但是,我和我的伙伴还没有参加数据结构课程,因此我们不知道如何在C ++中正确创建树,甚至不知道从哪里开始。
所以我的问题是,Stack Overflow是:我在哪里开始快速(并且有效地)编写和遍历C ++中的Alpha-Beta修剪树而不使用STL 。 (我们的任务规定我们不允许使用STL)。
感谢所有的帮助,谢谢!
答案 0 :(得分:2)
用于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;
}