Python实现汉诺塔问题的可视化(以动画的形式展示移动过程)

学习Python已经有一段时间了,也学习了递归的方法,而能够实践该方法的当然就是汉诺塔问题了,但是这次我们不只是要完成对汉诺塔过程的计算,还要通过turtle库来体现汉诺塔中每一层移动的过程。

一、设计一个类(Class)

类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

下面是此程序需用到的类(Class)代码:

 1 class Stack:
 2     def __init__(self):
 3         self.items = []
 4     def isEmpty(self):
 5         return len(self.items) == 0
 6     def push(self, item):
 7         self.items.append(item)
 8     def pop(self):
 9         return self.items.pop()
10     def peek(self):
11         if not self.isEmpty():
12             return self.items[len(self.items) - 1]
13     def size(self):
14         return len(self.items)

二、设计汉诺塔的底座

为了还原汉诺塔的移动过程,增强可视化程度,我们给它加上三个底座,代码如下:

 1 def drawpole_3():#画出汉诺塔的poles
 2     t = turtle.Turtle()
 3     t.hideturtle()
 4     def drawpole_1(k):
 5         t.up()
 6         t.pensize(10)
 7         t.speed(100)
 8         t.goto(400*(k-1), 100)
 9         t.down()
10         t.goto(400*(k-1), -100)
11         t.goto(400*(k-1)-20, -100)
12         t.goto(400*(k-1)+20, -100)
13     drawpole_1(0)#画出汉诺塔的poles[0]
14     drawpole_1(1)#画出汉诺塔的poles[1]
15     drawpole_1(2)#画出汉诺塔的poles[2]

三、制造汉诺塔的盘子

汉诺塔当然少不了盘子了,我们要写一段代码来绘制若干个盘子,代码如下:

 1 def creat_plates(n):#制造n个盘子
 2     plates=[turtle.Turtle() for i in range(n)]
 3     for i in range(n):
 4         plates[i].up()
 5         plates[i].hideturtle()
 6         plates[i].shape("square")
 7         plates[i].shapesize(1,8-i)
 8         plates[i].goto(-400,-90+20*i)
 9         plates[i].showturtle()
10     return plates

四、制造一个底座的栈

栈:栈作为一种数据结构,是一种只能在一端进行插入和删除操作。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。

此处使用的栈并非Python中真正意义上的栈,而是与之意思相仿的说法,我们都知道,汉诺塔必须将最上的盘子取走方可移动第二层的盘子,以此类推,不移动上方的盘子,就无法移动下方的盘子,废话不多说,来看看这个代码吧:

1 def pole_stack():#制造poles的栈
2     poles=[Stack() for i in range(3)]
3     return poles

五、设计移动盘子的代码

准备完前面的工作,现在就要开始移动盘子了,代码如下:

1 def moveDisk(plates,poles,fp,tp):#把poles[fp]顶端的盘子plates[mov]从poles[fp]移到poles[tp]
2     mov=poles[fp].peek()
3     plates[mov].goto((fp-1)*400,150)
4     plates[mov].goto((tp-1)*400,150)
5     l=poles[tp].size()#确定移动到底部的高度(恰好放在原来最上面的盘子上面)
6     plates[mov].goto((tp-1)*400,-90+20*l)

六、设计操控盘子移动方向的代码

可以移动盘子了当然还不够,只是胡乱地移动无法解决汉诺塔问题,我们要让盘子向着能够解决问题的方向移动,代码如下:

1 def moveTower(plates,poles,height,fromPole, toPole, withPole):#递归放盘子
2     if height >= 1:
3         moveTower(plates,poles,height-1,fromPole,withPole,toPole)
4         moveDisk(plates,poles,fromPole,toPole)
5         poles[toPole].push(poles[fromPole].pop())
6         moveTower(plates,poles,height-1,withPole,toPole,fromPole)

七、调用

终于完成了全部准备工作,现在就来调用函数,让他们一起发挥作用吧!

 1 import turtle
 2  
 3 class Stack:
 4     def __init__(self):
 5         self.items = []
 6     def isEmpty(self):
 7         return len(self.items) == 0
 8     def push(self, item):
 9         self.items.append(item)
10     def pop(self):
11         return self.items.pop()
12     def peek(self):
13         if not self.isEmpty():
14             return self.items[len(self.items) - 1]
15     def size(self):
16         return len(self.items)
17  
18 def drawpole_3():#画出汉诺塔的poles
19     t = turtle.Turtle()
20     t.hideturtle()
21     def drawpole_1(k):
22         t.up()
23         t.pensize(10)
24         t.speed(100)
25         t.goto(400*(k-1), 100)
26         t.down()
27         t.goto(400*(k-1), -100)
28         t.goto(400*(k-1)-20, -100)
29         t.goto(400*(k-1)+20, -100)
30     drawpole_1(0)#画出汉诺塔的poles[0]
31     drawpole_1(1)#画出汉诺塔的poles[1]
32     drawpole_1(2)#画出汉诺塔的poles[2]
33  
34 def creat_plates(n):#制造n个盘子
35     plates=[turtle.Turtle() for i in range(n)]
36     for i in range(n):
37         plates[i].up()
38         plates[i].hideturtle()
39         plates[i].shape("square")
40         plates[i].shapesize(1,8-i)
41         plates[i].goto(-400,-90+20*i)
42         plates[i].showturtle()
43     return plates
44  
45 def pole_stack():#制造poles的栈
46     poles=[Stack() for i in range(3)]
47     return poles
48  
49 def moveDisk(plates,poles,fp,tp):#把poles[fp]顶端的盘子plates[mov]从poles[fp]移到poles[tp]
50     mov=poles[fp].peek()
51     plates[mov].goto((fp-1)*400,150)
52     plates[mov].goto((tp-1)*400,150)
53     l=poles[tp].size()#确定移动到底部的高度(恰好放在原来最上面的盘子上面)
54     plates[mov].goto((tp-1)*400,-90+20*l)
55  
56 def moveTower(plates,poles,height,fromPole, toPole, withPole):#递归放盘子
57     if height >= 1:
58         moveTower(plates,poles,height-1,fromPole,withPole,toPole)
59         moveDisk(plates,poles,fromPole,toPole)
60         poles[toPole].push(poles[fromPole].pop())
61         moveTower(plates,poles,height-1,withPole,toPole,fromPole)
62  
63 myscreen=turtle.Screen()
64 drawpole_3()
65 n=int(input("请输入汉诺塔的层数并回车:\n"))
66 plates=creat_plates(n)
67 poles=pole_stack()
68 for i in range(n):
69     poles[0].push(i)
70 moveTower(plates,poles,n,0,2,1)
71 myscreen.exitonclick()

八、效果

首先输入一下我们想测试的汉诺塔层数,为节省时间我就选择了3层

下面是移动过程

看来效果还不错,这样汉诺塔的可视化就实现啦!

 

posted @ 2019-03-25 19:17  Regan_White_Lin  阅读(4515)  评论(1编辑  收藏  举报