汉诺塔——递归的典型应用

有一个很著名的问题叫汉诺塔问题
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如下图)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。
在这里插入图片描述

这个问题似乎每一次移动都可以用很多种移动方法,但实际上我们简化一下就会发现,如果A上一共有n个圆盘,那么我们首先要做的就是利用C把上面的n-1个圆盘移动到B上,然后A上的最后一个圆盘移动到C,之后再对B上的n-1个圆盘,利用空出来的A进行同样的操作,直到最后一个圆盘移动完毕。看起来这似乎是一个循环而不是递归,但实际上仔细分析一下,对于n个圆盘,我们要先移动上方的n-1个,而对于n-1个我们要先移动上方的n-2个…对于两个,我们要先移动上方的一个,对于1个我们可以直接移动。这是一个递归的过程,而递归的终点就是只有一个圆盘的情况。

这是在学习python时的一道练习题,那就用python来写吧

# n 代表要移动的圆盘个数,a,b,c表示三根圆柱
# a 表示起始柱(圆盘都在这跟柱子上)
# b 表示辅助柱,用于辅助移动的中间柱
# c 表示最终柱,最终所有的圆盘都要移动到这跟柱子
def hanoMove(n, a, b, c):
    if n == 1:
        print(a + "-->" + c)  # 只i移动一个时,可以直接移动到C柱
    else:
        # 首先将起始柱的n-1个圆盘移动到辅助柱
        # 注意我们此时要移动到B柱,因此B柱是此时的最终柱,C是辅助作用
        hanoMove(n - 1, a, c, b)
        # 然后将起始柱上的最后一个移动到最终柱
        # 此时我们将A柱上的移动到C柱,C是最终柱,B是辅助作用
        hanoMove(1, a, b, c)
        # 最后将B柱上的移动到C柱
        # 此时B柱为起始柱,C柱为最终柱,A辅助,这其实是对上述两步的再次执行
        hanoMove(n - 1, b, a, c)


# 试一下5个圆盘的移动
hanoMove(5, "A", "B", "C")

执行之后打印出来的结果是

A-->C
A-->B
C-->B
A-->C
B-->A
B-->C
A-->C
A-->B
C-->B
C-->A
B-->A
C-->B
A-->C
A-->B
C-->B
A-->C
B-->A
B-->C
A-->C
B-->A
C-->B
C-->A
B-->A
B-->C
A-->C
A-->B
C-->B
A-->C
B-->A
B-->C
A-->C

天知道对不对🤣

Java语言编写的汉诺塔程序,形象直观; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Tower extends Frame implements ActionListener,Runnable { HannoiTower tower=null; Button renew,auto=null; char towerName[]={'A','B','C'}; int 盘子数目,盘宽,盘高; Thread thread; TextArea 信息条=null; public Tower() { thread=new Thread(this); 盘子数目=5; 盘宽=80; 盘高=18; 信息条=new TextArea(12,12); 信息条.setText(null); tower=new HannoiTower(盘子数目,盘宽,盘高,towerName,信息条); renew=new Button("重新开始"); auto=new Button("自动演示搬盘子"); renew.addActionListener(this); auto.addActionListener(this); add(tower,BorderLayout.CENTER); add(renew,BorderLayout.SOUTH); add(auto,BorderLayout.NORTH); add(信息条,BorderLayout.EAST); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); setVisible(true); setBounds(60,20,670,540); validate(); } public void actionPerformed(ActionEvent e) { if(e.getSource()==renew) { if(!(thread.isAlive())) { this.remove(tower); 信息条.setText(null); tower=new HannoiTower(盘子数目,盘宽,盘高,towerName,信息条); add(tower,BorderLayout.CENTER); validate(); } else { } } if(e.getSource()==auto) { if(!(thread.isAlive())) { thread=new Thread(this); } try { thread.start(); } catch(Exception eee) { } } } public void run() { this.remove(tower); 信息条.setText(null); tower=new HannoiTower(盘子数目,盘宽,盘高,towerName,信息条); add(tower,BorderLayout.CENTER); validate(); tower.自动演示搬运盘子(盘子数目,towerName[0] ,towerName[1],towerName[2]); } public static void main(String args[]) { new Tower(); } }
所上传的为Eclipse工作空间 在一片广阔的草地上。。。被无数的树精入侵。。。 而出生在这片草地的你。。必然要拯救这片草地^^ 哈哈。。。我也会编泡菜剧情拉。。。。 这个。。测试版地游戏。。。 只有这一个地图。。。再加上BOSS和其他的地图。。就可以成为一款完整的游戏了 在游戏中数字键1使用火球术 数字键2使用抗拒火环(如果已经习得的话),该技能攻击人物附近的所有敌人,并推开敌人,随着等级的增长攻击力越高,对于这个之后树精的地图。。我特别推荐这个技能。。吼吼 数字键3使用雷电术(如果已经习得的话),该技能攻击屏幕内的3个敌人,并使其晕悬1秒,随着等级的增长攻击的人数越多,攻击力也越高,晕悬时间越长。。。在未来的地图中。。大量的远程怪。。这个技能就显的很有用拉。。。而在这个地图上。。。呵呵。。。一点用处没有-- 按F1键 使用气血丹,补充气血(如果有的话) 按F2键 使用凝神丹,补充技力(如果有的话) 按F3键。。。哈哈。。。。当地图上的所有怪都杀光之后你是否觉得没杀够呢。。不要紧。。按F3键就会重新再刷出一地图的树精!!!哈哈哈。。 ESC键可以查看人物属性 和使用道具 嘿嘿。。道具是如何获得的呢。。。每杀死一个怪物就会得到2G。。。。而所有的道具都是在NPC那买地 NPC在哪呢???在地图的中央 。。自己去找吧。。。哦。。对。。。站在NPC的身上 按空格键。。就可以购买物品拉。。。。。ESC键退出和NPC的对话。。。 恩。。。已经介绍的差不多拉。。。。 本引擎是完全由本人制作。。。。一点点的摸索。。花了尽1个月的时间哦。。。 接受高手的批评。。。QQ89631718,群18978079 喜欢用JAVA做游戏的朋友+我的QQ,或者群大家一起讨论。。。自己摸索实在摸索不出个所以然来。。更欢迎高手光临指导~~~ (提醒。。。本游戏为javaApplet,bin目录下start.html执行游戏。。。。没有JAVA平台和浏览器支持是运行不了的)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值