如何创建测试以查看我的A.I.是完美的?

时间:2012-12-02 06:35:49

标签: c# recursion artificial-intelligence greedy

我做了一个tic tac toe A.I.鉴于每个董事会成员国,我的A.I.将返回1个准确移动的地方。 我还创建了一个函数,循环使用A.I。

进行所有可能的播放

所以它是一个递归函数,让A.I.为一个给定的棋盘移动,然后让另一个游戏进行所有可能的移动,并在每个可能的移动中使用新的棋盘自己调用递归函数。

我这样做的时候A.I先行,而另一个先行......然后将它们加在一起。我结束了418次可能的胜利和115次可能的关系,以及0次可能的失败。

但现在我的问题是,如何最大限度地赢得胜利?我需要将这个统计数据与某些东西进行比较,但我无法弄清楚要将它与之进行比较。

8 个答案:

答案 0 :(得分:6)

我的感觉是你引用的统计数据已经非常好了。两位专业的Tic-Tac-Toe玩家总是以平局结束,如果你的对手知道如何玩游戏,就没有办法强制获胜。

<强>更新

可能有更优雅的方式证明你的A.I.的正确性,但最直接的方法是蛮力的方法。只需将所有可能的董事会职位列为游戏树,并修剪直接导致亏损的分支机构。然后,对于树中的每个分支,您可以计算出跟随该分支导致的获胜概率。然后你只需要测试你的A.I.在每个董事会的位置,并确保它以最高的获胜概率选择分支。

答案 1 :(得分:3)

你应该首先观察移动9总是被迫:棋盘上只有一个空方块。移动也可以被视为强迫,因为在七次移动之后可能只有三种情况:

  • O可以在下一步获胜,在这种情况下需要获胜
  • 在其余两个方格中的任何一个方格中放置X赢得X的游戏,在这种情况下O已失去,无论其下一步行动
  • X有一条或一条胜利之路,在这种情况下O阻止强制平局

这意味着游戏在最多七次移动后结束

同时观察只有三个开启动作:中心,角落或侧面。你采取的四个角或侧面中的哪一个都无关紧要,因为可以旋转板以匹配“规范”开口(左上角或顶部中间)。

您现在可以构建状态分析代码。从三个可能的开口中的每一个开始,使用在您移动时打开的所有方格,使用回溯最多六个附加移动进行搜索。每次移动后,分析位置以查看XO是否已获胜;标记以X作为Wx获胜,并以O作为Wo获胜。剩下的职位尚未确定。

不要在Wx或Wo之后探索位置:只需返回上一步,报告相应方的胜利。

当你到达第七步时,静态分析位置以决定它是否适用于上述三种情况之一,标记位置为Wx,Wo或Draw。

现在到了最重要的一步:当你向玩家N-1回溯到移动p时,

  • 如果你尝试的其中一个动作使得下一个等级的所有位置都变为Wp,那么也将当前位置声明为Wp。
  • 如果您尝试的所有动作都会导致对手获胜,则声明当前位置是对手的胜利
  • 否则,将当前位置声明为Draw,并返回上一级。

如果你这样做,所有三个空缺职位将被归类为平局。三次移动后你应该看到一些强制胜利。

运行此过程会将每个位置分类为Wx,Wo或Draw。如果你的AI让你在分类为Wp的位置上获得了p的胜利,或者在分类为抽奖的位置获得了平局,那么你的AI就是完美的。另一方面,如果存在静态分类为Wp的位置,其中AI仅获得p平局,那么您的AI引擎需要改进。

<小时/> 补充阅读:您可以在this article中找到有关计算Tic-Tac-Toe可能游戏的方法的其他游戏见解。

答案 2 :(得分:2)

你所做的是线性优化比A.I ...我不会在这里描述井字游戏的所有线性代数,网上有很多例子。

因此,使用线性代数,您无需证明您的结果(搜索魔法统计数据等),因为您的结果可以通过原始方程中的简单解决方案注入来验证。

总之,有两种情况:

  • 您正在使用简单的“演绎”逻辑(实际上是非形式线性代数公式):我们找不到一个现成的方法来检查您的结果,而无需查看您的代码。 编辑:正如Andrew Cooper建议的那样,蛮力可以是一种随时可用的方法,而无需查看您的代码。

  • 您正在使用正式的线性代数公式:您的结果可以通过原始方程中的简单解决方案注入来验证。

答案 3 :(得分:0)

唯一可以比较的是对另一个人的潜在举动。每当计算机轮流移动时,让它从那一点开始播放所有可能的游戏,并选择导致最高胜利数量的移动。你不能总是赢,但你可以给对手更多的机会做出不好的举动。

答案 4 :(得分:0)

或者,您可以随时在以下链接中尝试tic tac toe算法:

Tic Tac Toe perfect AI algorithm: deeper in "create fork" step

答案 5 :(得分:0)

鉴于我们知道

  • 一个人不能强迫胜利
  • 以最佳策略不容错过

你的AI已被证明是最佳的

  • 你在与它对战时搜索完整的树
  • 并且你的AI是确定性的(如果它在某些阶段滚动骰子你将不得不对抗所有组合)
它没有失败,你不能要求它赢。它所做的胜利不计算在内,因为你的完整树搜索也包含不良动作。就是这样,你已经完成了。

只是为了好玩:
如果你没有关于赢得/抽签/输掉比赛的机会的先验知识,那么共同的策略就是坚持不懈地保存失去的位置。在下一场比赛中你会试着避开它们。如果你无法避免转移到失去的位置,你会发现另一个。通过这种方式,您可以学会不要违背某种策略(如果可能)或避免策略中的错误。

答案 6 :(得分:0)

为了证明你的井字游戏AI是正确的,它需要满足两个条件:

  1. 绝不能丢失。
  2. 当对手偏离最佳比赛时,必须获胜。
  3. 这两个条件都源于这样一个事实,即如果两个球员都发挥得最佳,那么井字游戏总是以平局结束。

    确定您的程序是否满足这两个条件的一种自动方法是构建每个可能的井字游戏的所谓“极小极大树”。 minimax树完全表征了每个玩家的最佳移动,因此您可以使用它来查看您的程序是否始终选择最佳移动。这意味着我的回答基本上归结为:“写一个完美的AI,然后看看它是否和你自己的AI一样。”但是,minimax算法对于了解是非常有用的,据我所知,这是测试AI实际上是否达到最佳状态的唯一方法。

    以下是minimax算法的工作原理(有关gif说明,请参阅WikipediaWikipedia article on minimax中还有一些伪代码。):

    1. 从正在考虑的井字游戏设置开始,构建一个包含所有可能后续移动的树。根节点的初始位置。在树的最低级别,您拥有所有可能的最终位置。

    2. 将值+1分配给第一个玩家获胜的所有最终位置,将值-1分配给第二个玩家获胜的所有移动,将值0分配给所有关系。

    3. 现在我们将这些值在树中传播到根节点。假设每个玩家都玩得最佳。在最后一步中,玩家一将选择任何值为+1的移动,即赢得游戏的移动。如果没有移动的值为+1,则玩家一将选择值为0的移动,将游戏绑定。因此,玩家一号移动的节点被分配了他们任何子节点的最大值。相反,当玩家2的移动时,他们更喜欢选择值为-1的移动,从而赢得游戏。如果没有可用的获胜动作,他们更愿意打平比赛。因此,为Player Two转弯的节点被分配一个等于其子节点最小值的值。使用此规则,您可以将值从树中最深层传播到根节点。

    4. 如果根节点的值为+1,则第一个玩家应以最佳游戏获胜。如果它的值为-1,则第二个玩家应该获胜。如果它的值为0,则最佳游戏会导致平局。

    5. 现在,您可以在每种情况下确定您的算法是否选择最佳移动。在tic-tac-toe中构造一个包含所有可能移动的树,并使用minimax算法为每个移动分配+1,0或-1。如果你的程序是Player One,那么它总是选择具有最大值的移动是最佳的。如果它作为玩家二玩,那么它总是选择具有最小值的移动是最佳的。

      然后,您可以循环遍历树中的每个动作,并让您的AI选择一个动作。以上内容告诉您如何确定它选择的移动是否最佳。

答案 7 :(得分:0)

我会用decision tree来解决这个问题。

简单来说,决策树是一种递归计算最终结果的期望(和机会)的方法。树中的每个“分支”都是一个决定,该预期是根据此决定的sum of (value * chance)计算的。

有限选项场景(如tic-tac-toe)中,您可以预先计算整个树,因此在每次移动人类玩家(机会)后,您可以选择(决定) )下一个分支女巫的期望值最高。

国际象棋游戏中,解决方案类似,但树不是预先构建的:在每次移动后,计算机计算每个可能移动的值n深度向前。根据玩家选择的游戏难度选择最佳,第二好或第n个最佳期望值。