Tic-Tac-Toe AI:如何制作树?

时间:2010-04-30 12:04:16

标签: c++ tree artificial-intelligence tic-tac-toe

在制作Tic-Tac-Toe机器人时,我正试图了解“树木”。我理解这个概念,但我无法想出来实现它们。

有人能告诉我一个如何为这种情况生成树的示例吗?还是一个关于生成树木的好教程?我想难以产生部分树木。我知道如何实现生成整棵树,但不是它的一部分。

5 个答案:

答案 0 :(得分:15)

想象一下,在tic-tac-toe板的任何一点,每一个可能的移动都是一个分支。董事会的当前状态是根。一举是一个分支。现在假装(一次一个),每个分支成为当前状态。每个可能的移动都成为新的分支。树的叶子是最后一次移动并且板已满的时候。

你需要拥有一棵树的原因是,一旦它被构建,你需要弄清楚哪个分支的叶子是“WIN”场景。你构建了所有可能结果的分支,将WINs的总数加起来,然后进行有机会获得最多胜利的移动。

使树像这样:

class Node {
public:
   std::list< Node > m_branches;
   BoardState m_board;
   int m_winCount;
}

std::list< Node > tree;

现在,您遍历树中的分支列表,并为每个分支迭代其分支。这可以通过递归函数完成:

int recursiveTreeWalk( std::list< Node >& partialTree)
{

   for each branch in tree
       if node has no branches
           calculate win 1/0;
       else
           recursiveTreeWalk( branch );

   partialTree.m_winCount = sum of branch wins;
}

// initial call
recursiveTreeWalk( tree )

非常伪代码。

答案 1 :(得分:5)

我认为你不需要在记忆中保留一棵树。您只需要实现一个类似于:

的递归函数
Move getBestMove(Board state, boolean myTurn)

然后你只需要递归,直到你达到胜利,失败或平局状态。

如果你把它写在纸上,那么随着时间的推移,调用堆会看起来像一棵树。你应该返回导致对手(绝对/最有可能)失去的节点的移动(即使他也使用getBestMove进行游戏)

对于像tic-tac-toe这样的状态空间,你可以简单地做一个具有最佳动作的完整查找表! : - )

答案 2 :(得分:4)

您可能会发现此代码项目文章很有趣:

Solve Tic Tac Toe with the MiniMax algorithm

它在C#中,但在C ++中适应它不会有任何问题。

当我尝试用C ++实现我的第一个Tic-Tac-Toe游戏时,这篇文章对我来说也是一个很好的读物:

Minimax Explained

答案 3 :(得分:0)

如果你想在内存中生成树(这是不必要的),也许可以使用如下算法(伪代码):

GenTree(State s):
  T <- empty tree  // T is a tree of States
  SetRoot(T, s)

  ForEach (s' in Successors(s)):
    AddChild(T, GenTree(s'))

  return T

// Call it
GenTree(currentMove)

,其中

Successors(s)  // returns a list of successor states of s
AddChild(p, n)  // adds n to the list of p's children

答案 4 :(得分:0)

实施Tic Tac Toe游戏可能是就AI而言要解决的最简单问题 和搜索空间。

关键是要使用MinimaxIterative deepening Depth-first searchAlpha-beta pruning算法来解决问题。

这是我用Python编写的游戏implementation,它只有约200行代码,并具有以Human vs. HumanHuman vs. Computer和{{1} }。它还可以统计到达/修剪的节点的深度和数量,从而达到最佳移动效果。

我强烈推荐Computer vs. Computer人工智能course,它提供了有关当前AI主题和解决方案的基础知识。