python汉诺塔问题
python汉诺塔问题
实现python汉诺塔动画,需要分成两个部分来进行:
(1)绘制塔和圆盘
(2)移动绘制后的形状
这里需要用到递归
1、递归的定义:间接或直接调用自身的函数被称为递归函数。
2、递归三原则:
(1)要有个基础条件,来退出递归
(2)递归过程要向1靠拢
(3)要不断的调用自身
一、思路分析
移动过程
设 A塔是圆盘出发的塔,称之为起点塔
C塔是圆盘最终要达到的塔,称之为目标塔
B塔起辅助中转作用,称之为中转塔
当n=1时,只需要将盘1从起点塔A移动到目标塔C即可。
当n=2时,需要将盘1从起点塔A移动到中转塔B,
再将盘2从起点塔A移动到目标塔C,
最后将盘1从中转塔B移动到目标塔C即可。
当n=3时,先将盘12看做一个整体从起点塔A移动到中转塔B,
再将盘3从起点塔A移动到目标塔C,
最后将盘12作为一个整体从中转塔B移动到目标塔C即可。
(参照n=2)
当n=k时, 先将盘1到k-1看做一个整体从起点塔A移动到中转塔B,
再将盘k从起点塔A移动到目标塔C,
最后将盘1到k-1作为一个整体从中转塔B移动到目标塔C即可。
以下以三层汉诺塔为例。
1、首先,定义一个moveDisk(diskIndex,fromPole,toPole)
函数:移动指定层圆盘diskIndex,从fromPole出发,到达toPole
def moveDisk(diskIndex, fromPole, toPole): print_str = 'Move disk %s form %s to %s' % (diskIndex,fromPole,toPole) print(print_str)
2、接下来,定义一个movetower函数,其中,WithPole表示中转塔B
def moveDisk(diskIndex,fromPole,toPole): print_str = 'Move disk %s form %s to %s' % (diskIndex, fromPole,,toPole) print(print_str) def moveTower(height, fromPole, withPole,,toPole): if height == 1 : moveDisk(1,fromPole,,toPole) else: moveTower(height-1,fromPole,,toPole, withPole) moveDisk(height,fromPole,,toPole) moveTower(height-1, withPole,fromPole,,toPole) if __name__ == '__main__': moveTower(3, "A", "B", "C")
3、绘制塔和圆盘
turtle函数 | 作用 |
turtle.begin_poly() | 开始记录多边形的顶点。当前的乌龟位置是多边形的第一个顶点。 |
turtle.end_poly() | 停止记录多边形的顶点。当前的乌龟位置是多边形的最后一个顶点。将与第一个顶点相连。 |
turtle.get_poly() | 返回最后记录的多边形。 |
turtle.hideturtle() | 隐藏画笔的turtle形状 |
register函数用于注册程序退出时的回调函数,然后在回调函数中做一些资源清理的操作
import turtle size = 20 TowerP=5 # Tower的线宽 TowerW=100 # Tower的底座宽度 TowerH=200 # Tower的高度 TowerSpace=260 # Tower的之间的距离,从中心到中心 HORIZON=-100 # Tower的底座高度,用于定位 towerD = 250 towerA = -100 # 设置圆盘形状 def set_plate(i): l = size * (i+2) t = turtle.Turtle() t.hideturtle() t.penup() t.begin_poly() t.left(90) t.forward(l) t.circle(size, 180) t.forward(l * 2) t.circle(size, 180) t.forward(l) t.end_poly() p = t.get_poly() turtle.register_shape("plate_%s"%i, p) # 设置塔柱形状 def set_tower(): t = turtle.Turtle() t.hideturtle() t.penup() t.begin_poly() t.left(90) t.forward(TowerW) t.circle(-TowerP, 180) t.forward(TowerW) t.forward(TowerW) t.circle(-TowerP, 180) t.forward(TowerW-TowerP/2) t.left(90) t.forward(TowerH) t.circle(-TowerP, 180) t.forward(TowerH) t.end_poly() p = t.get_poly() SCR.register_shape('tower', p) # 绘制塔柱 def draw_towers(): set_tower() tower = turtle.Turtle("tower") tower.penup() tower.goto(-towerD,towerA) tower.stamp() tower.goto(0,towerA) tower.stamp() tower.goto(towerD,towerA) # 绘制圆盘 def draw_plates(pn): plates=[] for i in range(pn): set_plate(i) _plate='plate_%s'%i pi=turtle.Turtle(_plate) pi.penup() plates.append(pi) return plates
最后,将绘制函数和移动函数结合起来
import turtle size = 20 TowerP=5 # Tower的线宽 TowerW=100 # Tower的底座宽度 TowerH=200 # Tower的高度 TowerSpace=260 # Tower的之间的距离,从中心到中心 HORIZON=-100 # Tower的底座高度,用于定位 towerD = 250 towerA = -100 #记录塔的位置 tower_loc = { "A":-1, "B":0, "C":1, } #记录塔上有几个圆盘 tower_poles = { "A":[], "B":[], "C":[], } # 建立窗体 SCR=turtle.Screen() # SCR.tracer() SCR.setup(800,600) #设置窗体大小 # 设置圆盘形状 def set_plate(i): l = size * (i+2) t = turtle.Turtle() t.hideturtle() t.penup() t.begin_poly() t.left(90) t.forward(l) t.circle(size, 180) t.forward(l * 2) t.circle(size, 180) t.forward(l) t.end_poly() p = t.get_poly() turtle.register_shape("plate_%s"%i, p) # 设置塔柱形状 def set_tower(): t = turtle.Turtle() t.hideturtle() t.penup() t.begin_poly() t.left(90) t.forward(TowerW) t.circle(-TowerP, 180) t.forward(TowerW) t.forward(TowerW) t.circle(-TowerP, 180) t.forward(TowerW-TowerP/2) t.left(90) t.forward(TowerH) t.circle(-TowerP, 180) t.forward(TowerH) t.end_poly() p = t.get_poly() SCR.register_shape('tower', p) # 绘制塔柱 def draw_towers(): set_tower() tower = turtle.Turtle("tower") tower.penup() tower.goto(-towerD,towerA) tower.stamp() tower.goto(0,towerA) tower.stamp() tower.goto(towerD,towerA) # 绘制圆盘 def draw_plates(pn): plates=[] for i in range(pn): set_plate(i) _plate='plate_%s'%i pi=turtle.Turtle(_plate) pi.penup() plates.append(pi) return plates # 绘制移动过程 def draw_move(plate,fromPole,toPole): to_x = tower_loc[toPole] * towerD toPole_count = len(tower_poles[toPole]) to_y = towerA +2 * TowerP + toPole_count * size * 2 if fromPole: tower_poles[fromPole].remove(plate) plate.goto(to_x,to_y) tower_poles[toPole].append(plate) # 移动指定层圆盘diskIndex,从fromPole出发,到达toPole def moveDisk(diskIndex,fromPole,toPole): draw_move(diskIndex, fromPole, toPole) # 核心函数,入口 def moveTower(height,fromPole, withPole, toPole,plates): if height == 1: draw_move(plates[0],fromPole, toPole) else: moveTower(height-1,fromPole,toPole,withPole,plates) draw_move(plates[height-1],fromPole,toPole) moveTower(height-1,withPole,fromPole,toPole,plates) if __name__ == '__main__': draw_towers() n=3 plates=draw_plates(n) for i in range(n): draw_move(plates[n-1-i],'','A') moveTower(n,"A","B","C",plates) turtle.done()