梵塔规则
有a、b、c三个柱子,a从上到下,从小到大有n个盘子。要求把a上所有盘子移动到c,一次只能移动一个盘子,且大盘子不能放小盘子上
分析梵塔解决过程
(1)将最上面的n-1个圆盘从a移动到b
(2)将初始位的最底下的一个圆盘移动到c
(3)将b的n-1个圆盘移动到c
例如
当移动两个盘子的时候,得需要三步才能完成。例如:把a上的两个盘子移动到c
第一步:先把a上的1个移动到b
第一步:再把a上最后1个移动到c
第一步:再把b上仅有的一个移动到c
当移动三个盘子的时候,就可以分解成先移动两个盘子(可以看成当移动2个盘子时),再移动一个盘子,再将两个盘子移动(3步)
当移动四个盘子的时候,就可以分解为先移动三个盘子(又可以看成当移动3个盘子时),再移动一个盘子。再移动三个盘子(3步)
所以当移动两个或者两个以上的盘子时,可以用归约法将问题依次分解,每次分解都是3步,分解直至当移动两个盘子,而移动2个盘子也需要3步,因此这就是一个递归的问题,同样的,用递归实现即可
代码
# n:层数,a:初始柱,b:过度柱,c:目标柱
def move(n,a,b,c):
# 如果层数为1,可以直接到目标柱
if n==1:
print(a,"-->",c)
# n-1:分解
else:
move(n-1,a,c,b) # 第一步
move(1,a,b,c) # 第二步
move(n-1,b,a,c) # 第三步
if __name__=="__main__":
n=int(input("请输入层数:"))
move(n,"A","B","C")
效果图:
动画效果代码
import turtle
class Stack:
def __init__(self):
self.items = []
def isEmpty(self):
return len(self.items) == 0
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
if not self.isEmpty():
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
def drawpole_3(): #画出汉诺塔的poles
t = turtle.Turtle()
t.hideturtle()
def drawpole_1(k):
t.up()
t.pensize(10)
t.speed(100)
t.goto(400*(k-1), 100)
t.down()
t.goto(400*(k-1), -100)
t.goto(400*(k-1)-20, -100)
t.goto(400*(k-1)+20, -100)
drawpole_1(0) #画出汉诺塔的poles[0]
drawpole_1(1) #画出汉诺塔的poles[1]
drawpole_1(2) #画出汉诺塔的poles[2]
def creat_plates(n): #制造n个盘子
plates=[turtle.Turtle() for i in range(n)]
for i in range(n):
plates[i].up()
plates[i].hideturtle()
plates[i].shape("square")
plates[i].shapesize(1,8-i)
plates[i].goto(-400,-90+20*i)
plates[i].showturtle()
return plates
def pole_stack(): #制造poles的栈
poles=[Stack() for i in range(3)]
return poles
def moveDisk(plates,poles,fp,tp):#把poles[fp]顶端的盘子plates[mov]从poles[fp]移到poles[tp]
mov=poles[fp].peek()
plates[mov].goto((fp-1)*400,150)
plates[mov].goto((tp-1)*400,150)
l=poles[tp].size() #确定移动到底部的高度(恰好放在原来最上面的盘子上面)
plates[mov].goto((tp-1)*400,-90+20*l)
def moveTower(plates,poles,height,fromPole, toPole, withPole):#递归放盘子
if height >= 1:
moveTower(plates,poles,height-1,fromPole,withPole,toPole)
moveDisk(plates,poles,fromPole,toPole)
poles[toPole].push(poles[fromPole].pop())
moveTower(plates,poles,height-1,withPole,toPole,fromPole)
myscreen=turtle.Screen()
drawpole_3()
n=int(input("请输入汉诺塔的层数并回车:\n"))
plates=creat_plates(n)
poles=pole_stack()
for i in range(n):
poles[0].push(i)
moveTower(plates,poles,n,0,2,1)
myscreen.exitonclick()