C++抽象编程——回溯算法(4)——回溯在游戏中的应用

回溯法与游戏

虽然回溯算法是最容易在迷宫的背景下进行说明的,但这个策略却应用的相当普遍。例如,我们可以对大多数双人游戏应用回溯。第一个玩家有一些初步选择。根据选择哪个动作,第二玩家则具有一组特定的响应。这些反应中的每一个都反过来导致了第一个玩家的新选择,这个过程一直持续到游戏结束。游戏中每个回合的不同的可能位置形成一个分支结构,其中每个选项打开越来越多的可能性。
现在我们来说说什么叫回溯算法。回溯算法(Backtracking,algorithm)也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。这也是我们解决迷宫问题的关键。
如果要设计计算机来作为双人游戏的一方,一种方法是使计算机遵循可能性列表中的所有分支。在进行第一步之前,电脑会尝试所有可能的选择。对于每个这些选择,它将尝试确定其对手的回应是什么。要做到这一点,它将遵循相同的逻辑:尝试一切可能性并评估可能的反作用。如果电脑可以比对手看的更远,那么就可以对手处于劣势的位置。(也就是在你走下一步的时候,我就已经知道了你下一步要走的的所有可能,那么我肯定占据了上风
在理论上,这个策略可以应用于任何双人游戏。在实践中,即使对于现代计算机,查看所有可能的动作并且做出相应的响应,对这些响应的响应的过程也需要太多的时间和内存。但是,有几个游戏通过观察所有的可能性可能足够简单,足够复杂,以至于解决方案对于我们来说都并不是很确定的。

Nim游戏

为了了解递归回溯如何应用于双人游戏,我们考虑一个简单的例子。
Nim游戏是整个类游戏的通用名称,玩家轮流从一些初始配置中删除对象。在这个特定版本中,游戏开始这里有13个硬币。 每一回合,玩家从这堆中拿出一个,两个或三个硬币,放在一边。游戏的目标是避免拿到最后的那个硬币。 下图显示了这个游戏的简单运行:

你如何写一个程序来玩Nim的游戏并且使得它一定会赢? 硬币数量,要求玩家进行合法的移动,确定游戏的结束等等是一个简单的编程任务。该计划的有趣部分包括如何给计算机一个玩最好的游戏的策略。(也就是说怎么让你写的程序赢的可能最大
寻找一个成功的Nim策略不是特别困难,特别是如果你从游戏结束时落后。Nim的规则表明,谁拿下最后一枚硬币,那么谁就输了。因此,如果你发现自己只有一枚硬币在桌子上,你就处于不利地位。你必须拿这个硬币那么这样你就输了。另一方面,如果你发现自己有两个,三个或四个硬币,那么事情会很好。 在任何这些情况下,你可以随时拿走剩下的一个硬币,让对手处于只有一个硬币的不利位置。
但是如果桌子上有五个硬币呢?那你能干什么? 经过一番思考,很容易看出,如果你留下五个硬币,你也要注意。不管你做什么,你必须留给你的对手有两个,三个或四个硬币,这个时候你刚才发现的情况也就意味着从你对手的角度来看这是个好的情况。如果你的对手玩的很聪明,那么你的下一回合肯定会留下一枚硬币。由于你之前没有好的举动,剩下五枚硬币显然是一个糟糕的境地。
这个非正式的分析揭示了对Nim游戏的重要见解。在每一回合,你都要寻找一个好的举动。一个好的举动是让你的对手处于不利的位置。但是什么是不利的位置? 不利的位置就是没有好的举动。
尽管这些好的举动和不利的定位是循环的,但他们仍然构成了一个完美的Nim游戏策略,只需要依赖递归的力量。如果你有一个功能findGoodMove,以硬币的数量为参数,它所要做的就是尝试一切可能性,寻找一个为对手留下不利的位置。然后,您可以调用函数isBadPosition判断此时是否处于不利的位置,这两个函数来回调用,在游戏进行时评估所有可能的分支
相互递归的函数findGoodMove和isBadPosition提供了Nim程序需要玩的完美游戏的所有策略。要完成这个程序,你需要做的就是编写一个代码,用于Nim的机制。 该代码负责设置游戏,打印指示,跟踪其游戏到哪里,询问用户进行移动,检查移动是否合法,更新硬币数量,了解游戏结束时间, 并让用户知道谁赢了。
虽然这些任务在概念上都不是困难的,但是Nim应用程序是挺大的,因此采用我们之前中类的描述的实现来实现这个策略,其中程序被定义为一个类而不是一个自由函数的集合。 游戏的代码封装在一个名为SimpleNim的类中,以及跟踪游戏进度的两个实例变量:

  • 整数变量nCoins记录堆中的硬币数量。
  • 一个变量whoseTurn,它表示哪个玩家即将移动。该值使用枚举类型Player存储,该类型定义常量HUMAN和COMPUTER。在每一回合结束时,play方法的代码通过将对方下一个玩家。

代码我会在下一篇的博客中写上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值