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()

 

  

  

 

posted @ 2020-03-29 20:19  邓若言  阅读(748)  评论(0编辑  收藏  举报