Update hanoi.py - bug fix, speed adjustment.

This commit is contained in:
George 2020-04-26 23:56:08 -07:00
parent 08ccb4c68a
commit f974ac14df

View File

@ -13,6 +13,7 @@ GAP = 2
CANVAS_W = 500 CANVAS_W = 500
CANVAS_H = 400 CANVAS_H = 400
gbl_speed = 0.001 # in seconds gbl_speed = 0.001 # in seconds
gbl_step = 2
gbl_pegs = [] gbl_pegs = []
gbl_pegstate = [[], [], []] gbl_pegstate = [[], [], []]
gbl_disks = [] gbl_disks = []
@ -24,13 +25,15 @@ gbl_ready = True
def setup_gui(): def setup_gui():
global gbl_canvas global gbl_canvas
def get_ent(event): def ent_return(event):
event.widget.tk_focusNext().focus()
def get_ent_focus(event):
global gbl_num_disks global gbl_num_disks
try: try:
new_num = int(ent_disks.get()) new_num = int(ent_disks.get())
gbl_num_disks = new_num gbl_num_disks = new_num
event.widget.tk_focusNext().focus()
draw_init_setting() draw_init_setting()
except Exception as err: except Exception as err:
ent_disks.delete(0, tk.END) ent_disks.delete(0, tk.END)
@ -43,40 +46,44 @@ def setup_gui():
tk.Label(tk_row, text="No. of Disks: ").pack(side=tk.LEFT) tk.Label(tk_row, text="No. of Disks: ").pack(side=tk.LEFT)
ent_disks = tk.Entry(tk_row, width=5) ent_disks = tk.Entry(tk_row, width=5)
ent_disks.insert(0, str(gbl_num_disks)) ent_disks.insert(0, str(gbl_num_disks))
ent_disks.bind('<Return>', get_ent) ent_disks.bind('<Return>', ent_return)
ent_disks.bind('<FocusOut>', get_ent) ent_disks.bind('<FocusOut>', get_ent_focus)
ent_disks.pack(side=tk.LEFT, padx=5) ent_disks.pack(side=tk.LEFT, padx=5)
btn_start = tk.Button(tk_row, text="Start", width=6) btn_start = tk.Button(tk_row, text="Start", width=6, command=run_hanoi)
btn_start.bind('<ButtonRelease-1>', run_hanoi) # btn_start.bind('<ButtonRelease-1>', run_hanoi)
btn_start.pack(side=tk.LEFT, padx=5) btn_start.pack(side=tk.LEFT, padx=5)
btn_reset = tk.Button(tk_row, text="Reset", width=6) btn_reset = tk.Button(tk_row, text="Reset", width=6, command=reset_hanoi)
btn_reset.bind('<ButtonRelease-1>', reset_hanoi) # btn_reset.bind('<ButtonRelease-1>', reset_hanoi)
btn_reset.pack(side=tk.LEFT, padx=5) btn_reset.pack(side=tk.LEFT, padx=5)
tk.Label(tk_row, text="Speed: ").pack(side=tk.LEFT) tk.Label(tk_row, text="Speed: ").pack(side=tk.LEFT)
tk_var = tk.StringVar(gbl_tkroot) tk_var = tk.StringVar(gbl_tkroot)
tk_var.set('normal') tk_var.set('normal')
tk_opt_menu = tk.OptionMenu(tk_row, tk_var, tk_opt_menu = tk.OptionMenu(tk_row, tk_var,
*{'slow', 'normal', 'fastest'}) *{'slow', 'normal', 'fastest'})
tk_opt_menu.config(width = 6) tk_opt_menu.config(width=6, takefocus=True)
tk_opt_menu.pack(side=tk.LEFT) tk_opt_menu.pack(side=tk.LEFT)
tk_row.pack(side=tk.TOP, pady=5) tk_row.pack(side=tk.TOP, pady=5)
# animation canvas # animation canvas
gbl_canvas = tk.Canvas(gbl_tkroot, width=CANVAS_W, height=CANVAS_H) gbl_canvas = tk.Canvas(gbl_tkroot, width=CANVAS_W, height=CANVAS_H)
gbl_canvas.pack() gbl_canvas.pack()
btn_start.focus_set()
def change_speed(*args): def change_speed(*args):
global gbl_speed global gbl_speed, gbl_step
speed_opt = {'slow': 0.002, 'normal': 0.001, 'fastest': 0} speed_opt = {'slow': 0.001, 'normal': 0.001, 'fastest': 0}
step_opt = {'slow': 1, 'normal': 2, 'fastest': 1}
gbl_speed = speed_opt.get(tk_var.get()) gbl_speed = speed_opt.get(tk_var.get())
gbl_step = step_opt.get(tk_var.get())
# print(gbl_speed) # print(gbl_speed)
tk_var.trace('w', change_speed) tk_var.trace('w', change_speed)
def run_hanoi(event): def run_hanoi():
global gbl_ready global gbl_ready
# t0 = time.time()
if gbl_ready: if gbl_ready:
gbl_ready = False gbl_ready = False
try: try:
@ -85,9 +92,11 @@ def run_hanoi(event):
print(f'forced reset: {repr(err)}') print(f'forced reset: {repr(err)}')
else: else:
pass pass
# t1 = time.time()
# print(t1-t0)
def reset_hanoi(event): def reset_hanoi():
draw_init_setting() draw_init_setting()
@ -133,6 +142,7 @@ def draw_init_setting():
gbl_ready = True gbl_ready = True
def move_disk(i, a, b): def move_disk(i, a, b):
global gbl_pegstate, gbl_canvas global gbl_pegstate, gbl_canvas
disk_num = gbl_pegstate[a].pop() disk_num = gbl_pegstate[a].pop()
@ -147,7 +157,7 @@ def move_disk(i, a, b):
x1, y1, x2, y2 = gbl_canvas.bbox(disk) x1, y1, x2, y2 = gbl_canvas.bbox(disk)
if y2 < py1: if y2 < py1:
break break
gbl_canvas.move(disk, 0, -1) gbl_canvas.move(disk, 0, -gbl_step)
gbl_tkroot.update_idletasks() gbl_tkroot.update_idletasks()
gbl_tkroot.update() gbl_tkroot.update()
time.sleep(gbl_speed) time.sleep(gbl_speed)
@ -155,18 +165,24 @@ def move_disk(i, a, b):
# Move to peg b # Move to peg b
px1, py1, px2, py2 = gbl_canvas.bbox(gbl_pegs[b]) px1, py1, px2, py2 = gbl_canvas.bbox(gbl_pegs[b])
new_center = (px1 + px2) // 2 new_center = (px1 + px2) // 2
while True:
x1, y1, x2, y2 = gbl_canvas.bbox(disk) x1, y1, x2, y2 = gbl_canvas.bbox(disk)
center = (x1 + x2) // 2 center = (x1 + x2) // 2
if center == new_center:
break while center < new_center:
if center > new_center: gbl_canvas.move(disk, gbl_step, 0)
gbl_canvas.move(disk, -1, 0)
else:
gbl_canvas.move(disk, 1, 0)
gbl_tkroot.update_idletasks() gbl_tkroot.update_idletasks()
gbl_tkroot.update() gbl_tkroot.update()
time.sleep(0.7*gbl_speed) # faster time.sleep(0.7*gbl_speed) # faster
x1, y1, x2, y2 = gbl_canvas.bbox(disk)
center = (x1 + x2) // 2
while center > new_center:
gbl_canvas.move(disk, -gbl_step, 0)
gbl_tkroot.update_idletasks()
gbl_tkroot.update()
time.sleep(0.7*gbl_speed) # faster
x1, y1, x2, y2 = gbl_canvas.bbox(disk)
center = (x1 + x2) // 2
# Drop down # Drop down
disk_h = y2 - y1 disk_h = y2 - y1
@ -175,7 +191,7 @@ def move_disk(i, a, b):
x1, y1, x2, y2 = gbl_canvas.bbox(disk) x1, y1, x2, y2 = gbl_canvas.bbox(disk)
if y2 >= new_bottom: if y2 >= new_bottom:
break break
gbl_canvas.move(disk, 0, 1) gbl_canvas.move(disk, 0, gbl_step)
gbl_tkroot.update_idletasks() gbl_tkroot.update_idletasks()
gbl_tkroot.update() gbl_tkroot.update()
time.sleep(gbl_speed) time.sleep(gbl_speed)
@ -188,7 +204,6 @@ def hanoi(n, a, b, c):
Hanoi algorithm: move n pieces from a to c, using b as buffer. Hanoi algorithm: move n pieces from a to c, using b as buffer.
For each move, call animate() to show the move For each move, call animate() to show the move
''' '''
if n < 0: if n < 0:
return return
hanoi(n-1, a, c, b) hanoi(n-1, a, c, b)