使用 Python 实现汉诺塔问题可视化有多种方法,以下为你介绍两种常见的实现方式:
### 使用`turtle`库实现可视化
`turtle`库是 Python 内置的一个简单绘图库,可通过动画形式展示汉诺塔的移动过程。以下是示例代码:
```python
import turtle
# 绘制三个柱子
def drawpole_3():
t = turtle.Turtle()
t.hideturtle()
for i in range(3):
t.penup()
t.goto(-200 + 200 * i, -100)
t.pendown()
t.goto(-200 + 200 * i, 100)
# 创建盘子
def creat_plates(n):
plates = []
for i in range(n):
plate = turtle.Turtle()
plate.shape("square")
plate.shapesize(1, 8 - i)
plate.penup()
plate.goto(-200, -90 + 20 * i)
plates.append(plate)
return plates
# 定义栈类
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return len(self.items) == 0
def push(self, item):
self.items.append(item)
def pop(self):
if not self.is_empty():
return self.items.pop()
def peek(self):
if not self.is_empty():
return self.items[-1]
# 初始化栈
def pole_stack():
poles = []
for _ in range(3):
pole = Stack()
poles.append(pole)
return poles
# 移动盘子
def moveDisk(plates, poles, fp, tp):
plate = poles[fp].pop()
plates[plate].goto(-200 + 200 * tp, -90 + 20 * len(poles[tp].items))
poles[tp].push(plate)
# 递归移动塔
def moveTower(plates, poles, n, source, target, auxiliary):
if n == 1:
moveDisk(plates, poles, source, target)
else:
moveTower(plates, poles, n - 1, source, auxiliary, target)
moveDisk(plates, poles, source, target)
moveTower(plates, poles, n - 1, auxiliary, target, source)
# 主程序
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()
```
此代码通过`turtle`库创建了一个图形窗口,在窗口中绘制了三个柱子和相应数量的盘子,然后以动画形式展示盘子的移动过程 [^2]。
### 使用`Tkinter`库实现可视化
`Tkinter`是 Python 的标准 GUI 库,可创建交互式的可视化界面。以下是一个简单示例:
```python
import tkinter as tk
class Start:
def __init__(self):
self.root = tk.Tk()
self.root.title("汉诺塔可视化")
self.canvas = tk.Canvas(self.root, width=600, height=400)
self.canvas.pack()
self.A_tp_list = []
self.B_tp_list = []
self.C_tp_list = []
self.flag = 0
self.count_num = 0
self.con = 0
self.key_list = []
self.label = tk.Label(self.root, text="请输入盘子数量:")
self.label.pack()
self.entry = tk.Entry(self.root)
self.entry.pack()
self.prepare_button = tk.Button(self.root, text="准备", command=self.prepare)
self.prepare_button.pack()
self.step_button = tk.Button(self.root, text="单步", command=self.step)
self.step_button.pack()
self.start_button = tk.Button(self.root, text="开始", command=self.start)
self.start_button.pack()
self.reset_button = tk.Button(self.root, text="重置", command=self.reset)
self.reset_button.pack()
def prepare(self):
n = int(self.entry.get())
for i in range(n):
plate = self.canvas.create_rectangle(200 - 10 * i, 350 - 20 * i, 200 + 10 * i, 370 - 20 * i, fill=f"#{i * 10:02x}0000")
self.A_tp_list.append(plate)
self.get_key(n, 'A', 'C', 'B')
def step(self):
if self.flag < len(self.key_list):
move = self.key_list[self.flag]
if move == 'A_B':
self.A_B()
elif move == 'A_C':
self.A_C()
elif move == 'B_A':
self.B_A()
elif move == 'B_C':
self.B_C()
elif move == 'C_A':
self.C_A()
elif move == 'C_B':
self.C_B()
self.flag += 1
self.count_num += 1
self.root.title(f"汉诺塔可视化 - 步数: {self.count_num}")
def start(self):
self.con = 1
while self.flag < len(self.key_list):
self.step()
self.root.update()
def A_B(self):
plate = self.A_tp_list.pop()
x1, y1, x2, y2 = self.canvas.coords(plate)
new_x1 = 300 - (x2 - x1) / 2
new_x2 = 300 + (x2 - x1) / 2
new_y = 350 - 20 * len(self.B_tp_list)
self.canvas.coords(plate, new_x1, new_y, new_x2, new_y + 20)
self.B_tp_list.append(plate)
def A_C(self):
plate = self.A_tp_list.pop()
x1, y1, x2, y2 = self.canvas.coords(plate)
new_x1 = 400 - (x2 - x1) / 2
new_x2 = 400 + (x2 - x1) / 2
new_y = 350 - 20 * len(self.C_tp_list)
self.canvas.coords(plate, new_x1, new_y, new_x2, new_y + 20)
self.C_tp_list.append(plate)
def B_A(self):
plate = self.B_tp_list.pop()
x1, y1, x2, y2 = self.canvas.coords(plate)
new_x1 = 200 - (x2 - x1) / 2
new_x2 = 200 + (x2 - x1) / 2
new_y = 350 - 20 * len(self.A_tp_list)
self.canvas.coords(plate, new_x1, new_y, new_x2, new_y + 20)
self.A_tp_list.append(plate)
def B_C(self):
plate = self.B_tp_list.pop()
x1, y1, x2, y2 = self.canvas.coords(plate)
new_x1 = 400 - (x2 - x1) / 2
new_x2 = 400 + (x2 - x1) / 2
new_y = 350 - 20 * len(self.C_tp_list)
self.canvas.coords(plate, new_x1, new_y, new_x2, new_y + 20)
self.C_tp_list.append(plate)
def C_A(self):
plate = self.C_tp_list.pop()
x1, y1, x2, y2 = self.canvas.coords(plate)
new_x1 = 200 - (x2 - x1) / 2
new_x2 = 200 + (x2 - x1) / 2
new_y = 350 - 20 * len(self.A_tp_list)
self.canvas.coords(plate, new_x1, new_y, new_x2, new_y + 20)
self.A_tp_list.append(plate)
def C_B(self):
plate = self.C_tp_list.pop()
x1, y1, x2, y2 = self.canvas.coords(plate)
new_x1 = 300 - (x2 - x1) / 2
new_x2 = 300 + (x2 - x1) / 2
new_y = 350 - 20 * len(self.B_tp_list)
self.canvas.coords(plate, new_x1, new_y, new_x2, new_y + 20)
self.B_tp_list.append(plate)
def reset(self):
for plate in self.A_tp_list + self.B_tp_list + self.C_tp_list:
self.canvas.delete(plate)
self.A_tp_list = []
self.B_tp_list = []
self.C_tp_list = []
self.flag = 0
self.count_num = 0
self.con = 0
self.key_list = []
self.root.title("汉诺塔可视化")
def get_key(self, n, a, c, b):
if n == 1:
if a == 'A' and c == 'B':
self.key_list.append('A_B')
elif a == 'A' and c == 'C':
self.key_list.append('A_C')
elif a == 'B' and c == 'A':
self.key_list.append('B_A')
elif a == 'B' and c == 'C':
self.key_list.append('B_C')
elif a == 'C' and c == 'A':
self.key_list.append('C_A')
elif a == 'C' and c == 'B':
self.key_list.append('C_B')
else:
self.get_key(n - 1, a, b, c)
self.get_key(1, a, c, b)
self.get_key(n - 1, b, c, a)
app = Start()
app.root.mainloop()
```
该代码创建了一个`Tkinter`窗口,包含输入框、按钮等交互元素,用户可输入盘子数量,选择单步或连续模式展示盘子的移动过程 [^3]。