汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
图1 十层汉诺塔
一、海龟绘图相关方法
(一) turtle.numinput()方法
此方法用于弹出一个用于输入数字的对话窗口。输入的数字必须在minval到maxval的范围内(如果已给出)。如果不是,则发出提示,对话框保持打开状态以进行更正。
语法结构如下:
turtle.numinput(title, prompt, default=None, minval=None, maxval=None)
(二) turtle.shapesize()方法
此方法用于返回或者设置turtle形状拉伸大小和轮廓线。turtle 的形状将根据其拉伸因子拉伸显示,并将调整大小模式设置为“user”。
语法结构如下:
turtle.shapesize(stretch_wid=None, stretch_len=None, outline=None)
turtle.turtlesize(stretch_wid=None, stretch_len=None, outline=None)
(三) turtle.fillcolor()方法
此方法用于返回或设置填充颜色。如果turtle shape是多边形,则使用新设置的fillcolor绘制该多边形的内部。
语法结构如下:
turtle.fillcolor(*args)
注:单位参数表示填充颜色(包括形状,海龟图标),可用标准颜色名,十六进制颜色,RGB颜色(分1.0模式和255模式)
(四) turtle.write()方法
此方法用于在当前位置写文本。
语法结构如下:
turtle.write(arg, move=false, align='left', font=('arial',8,'normal'))
(五) turtle.setx()方法
此方法用于设置Turtle的水平坐标为x,垂直坐标保持不变。
语法结构如下:
turtle.setx(x)
参数:x——一个数字(整数或浮点数) ,表示水平坐标位置。相当于单向goto()。
(六) turtle.sety()方法
此方法用于设置Turtle的垂直坐标为y,水平坐标保持不变。
语法结构如下:
turtle.sety(y)
参数:y——一个数字(整数或浮点数),表示垂直坐标位置。相当于单向goto()。
(七) turtle.onkey()方法
此方法用于将fun绑定到按键(key)的按键释放事件,等待用户按键并释放。为了能够注册按键事件,TurtleScreen必须具有焦点。
语法结构如下:
turtle.onkey(fun, key)
例 海龟绘图,绘制简单动画——汉诺塔圆盘移动动画演示(递归算法)。
本例根据海龟例子套件tdemo_minimal_hanoi.py改编而成,增加了自定义汉诺塔圆盘层数(3~20可选),增加了圆盘尺寸自适应(按圆盘层数多少自动调整圆盘尺寸)。
##############################################
# 设计 Zhang Ruilin 创建 2020-01-08 07:28 #
# 海龟绘制简单动画——汉诺塔圆盘移动动画演示 #
##############################################
'''根据海龟例子套件:tdemo_minimal_hanoi.py改编
一个“汉诺塔”的动画:盘片数(塔的层数)由用户输入,介于3~20之间
盘片用其侧面“方形”的海龟表示,大小盘子通过shapesize()拉伸为矩形,尺寸自适应。
'''
from turtle import *
_No = numinput(title='输入参数', prompt='请设置几层汉诺塔', default=6,
minval=3, maxval=20) # 用户输入汉诺塔层数
class Disc(Turtle): # 按第n层生成对应尺寸盘片(自适应)
def __init__(self, n):
global _n
Turtle.__init__(self, shape="square", visible=False) # 设置为方块形状
self.pu()
self.shapesize(1.5, _n*n*1.5, 2) # 按层从大到小拉伸方块为矩形
self.fillcolor(n/_No, 0, 1-n/_No) # 颜色为1.0模式,0~1.0,红蓝渐变
self.st() # 显示此方块形状(海龟图标)
class Tower(list):
'''汉诺塔, 内置子类类型列表'''
def __init__(self, x):
'''创建一个空塔。x是塔柱的位置'''
self.x = x
def push(self, d): # 移至尾部压入列表
d.setx(self.x)
d.sety(-150+34*len(self))
self.append(d)
def pop(self): # 移走从尾部弹出列表
d = list.pop(self)
d.sety(150)
return d
def hanoi(n, from_, with_, to_):
if n > 0: # 递归算法
hanoi(n-1, from_, to_, with_) # 将from_上n-1张盘片通过to_移至with_
to_.push(from_.pop()) # 最后1张盘片从源移至目标(弹出压入目标)
hanoi(n-1, with_, from_, to_) # n-1张盘片在with_上通过from_移至to_
def play():
onkey(None,"space") # 按空格开始
clear()
try:
hanoi(_No, t1, t2, t3)
write("关闭窗口退出", align="center", font=("simsun", 16, "bold"))
except Terminator:
pass
def main():
global t1, t2, t3, _No, _n
_n=1
if _No*1.5 > 250/32:
_n=250/32/_No # 盘片宽度比例因子(自适尺寸时用)
ht(); penup(); goto(0, -225) # 隐藏海龟图标,抬笔,移动到指定点
t1 = Tower(-250) # 定义三根塔柱对象
t2 = Tower(0)
t3 = Tower(250)
# 设置_No层的汉诺塔(在源柱,即t1上,先大后小压入t1(A柱))
for i in range(int(_No),0,-1):
t1.push(Disc(i))
# 操作提示 ;-)
write("按空格键开始游戏", align="center", font=("simhei", 16, "bold"))
onkey(play, "space")
listen()
return "事件循环"
if __name__=="__main__":
msg = main()
print(msg)
mainloop()
用户输入汉诺塔的层数(见图2)后,生成对应层汉诺塔圆盘全部在t1(A)柱(见图3),按空格键开始游戏,通过另外两根柱子进行移动(见图4),直到全部将圆盘全部移到t3(C)柱(见图5)。执行结果见图2~图5。
图2 输入汉诺塔层数
图3 初始状态
图4 中间过程
图5 最终状态