我制作了一个井字游戏A.I.。给定每种棋盘状态,我的A.I.会返回一个确切的位置进行移动。我还制作了一个函数,该函数会循环遍历所有可能的A.I.的移动方式。
这是一个递归函数,它允许A.I.在给定棋盘上进行移动,然后让另一个玩家进行所有可能的移动,并在每个可能的移动中调用自身的递归函数,生成新的棋盘状态。
我对A.I.先手和对方先手的情况都进行了这种操作,并将结果相加。最终,我得到了418种可能的胜利,115种可能的平局,以及0种可能的失败。
但现在我的问题是,如何最大化胜利的数量?我需要将这个统计数据与某些东西进行比较,但我不知道该与什么进行比较。
回答:
你应该首先注意到,第9步总是被迫的:棋盘上只剩下一个空格。第8步也可以被认为是被迫的,因为在进行了七次移动后,可能存在以下三种情况:
O
可以在下一步获胜,在这种情况下它会赢得胜利- 在剩下的两个空格中放置
X
会让X
赢得游戏,在这种情况下无论O
下一步做什么,它都已经输了 X
有零个或一个获胜路径,在这种情况下O
会封堵以强制平局
这意味着游戏最多在七步后结束。
还要注意的是,只有三种开局移动:中心、角落或边。无论你选择四个角落或边的哪一个都没有关系,因为棋盘可以旋转以匹配“标准”开局(左上角或顶部中间)。
现在你可以构建你的状态分析代码。从三种可能的开局开始,使用回溯法搜索最多六个额外的移动,利用在你移动时仍然开放的所有方格。在每次移动后,分析位置以查看X
或O
是否已经获胜;将X
的胜利标记为Wx,将O
的胜利标记为Wo。其余位置为未决定。
不要在Wx或Wo之后探索位置:只需返回到前一步,报告相应一方的胜利。
当你到达第七步时,静态分析位置以决定是否适用于上述描述的三种情况之一,将位置标记为Wx、Wo或平局。
现在是最重要的一步:当你回溯到玩家p
的N-1
步时,
- 如果你尝试的移动之一使得下一级的所有位置都成为Wp,则声明当前位置也为Wp。
- 如果所有你尝试的移动都导致对手获胜,则声明当前位置为对手的胜利
- 否则,声明当前位置为平局,并返回到前一级别。
如果你做得正确,所有三个开局位置都将被分类为平局。你应该能看到在三步后的一些强制性胜利。
运行此程序会将每个位置分类为Wx、Wo或平局。如果你的A.I.在被分类为Wp的位置上为玩家p
赢得胜利,或者在被分类为平局的位置上获得平局,那么你的A.I.就是完美的。另一方面,如果存在一些静态分类为Wp的位置,而A.I.只能为p
获得平局,那么你的A.I.引擎需要改进。
附加阅读:你可以在这篇文章中找到关于井字游戏的更多见解,该文章描述了计算可能的井字游戏的方法。