Python迷宫游戏重启功能实现报错,寻求解决方法
问题
我是Python初学者,开发迷宫游戏时无法实现重新开始游戏的功能,尝试多种方法均以报错告终。我尝试销毁承载迷宫的frame_top后调用new_game函数生成新迷宫,但触发了错误,相关代码及错误栈如下:
import tkinter as tk import random from tkinter import messagebox global SIZE global ROW global COLUMN SIZE = 10 COLUMN = 7 ROW = 7 departure = [[1, 1]] playerX = 1 playerY = 1 beforeX = 1 beforeY = 1 maze = [] for y in range(ROW) : sub = [] for x in range(COLUMN) : if y==0 or y==ROW-1 or x==0 or x==COLUMN-1 : sub.append("WALL") else : sub.append("FIELD") maze.append(sub) def dig(x, y) : maze[y][x] = "PATH" canMove = [] if maze[y-1][x]=="FIELD" and maze[y-2][x]=="FIELD" : canMove.append("UP") if maze[y+1][x]=="FIELD" and maze[y+2][x]=="FIELD" : canMove.append("DOWN") if maze[y][x-1]=="FIELD" and maze[y][x-2]=="FIELD" : canMove.append("LEFT") if maze[y][x+1]=="FIELD" and maze[y][x+2]=="FIELD" : canMove.append("RIGHT") if len(canMove)==0 : return direction = random.choice(canMove) if direction=="UP" : maze[y-1][x]="PATH" maze[y-2][x]="PATH" y -= 2 if direction=="DOWN" : maze[y+1][x]="PATH" maze[y+2][x]="PATH" y += 2 if direction=="LEFT" : maze[y][x-1]="PATH" maze[y][x-2]="PATH" x -= 2 if direction=="RIGHT" : maze[y][x+1]="PATH" maze[y][x+2]="PATH" x += 2 departure.append([x, y]) dig(x, y) def keyPress(event) : global playerX,playerY,beforeX,beforeY if event.keysym=="Up" and maze[playerY-1][playerX]=="PATH" : beforeX = playerX beforeY = playerY playerY -=1 if event.keysym=="Down" and maze[playerY+1][playerX]=="PATH" : beforeX = playerX beforeY = playerY playerY +=1 if event.keysym=="Left" and maze[playerY][playerX-1]=="PATH" : beforeX = playerX beforeY = playerY playerX -=1 if event.keysym=="Right" and maze[playerY][playerX+1]=="PATH" : beforeX = playerX beforeY = playerY playerX +=1 def move() : can.create_oval(beforeX*SIZE+1, beforeY*SIZE+1, (beforeX+1)*SIZE-1, (beforeY+1)*SIZE-1, fill="white", width=0) can.create_oval(playerX*SIZE+2, playerY*SIZE+2, (playerX+1)*SIZE-2, (playerY+1)*SIZE-2, fill="blue") if playerX==COLUMN-2 and playerY==ROW-2 : messagebox.showinfo("INFORMATION", "CONGRATULATIONS!!!") frame_top.destroy() new_game() can.after(100, move) def new_game(): departure = [[1, 1]] playerX = 1 playerY = 1 beforeX = 1 beforeY = 1 maze = [] canMove = [] print (maze) for y in range(ROW) : sub = [] for x in range(COLUMN) : if y==0 or y==ROW-1 or x==0 or x==COLUMN-1 : sub.append("WALL") else : sub.append("FIELD") maze.append(sub) while len(departure)!=0 : start = departure.pop(0) x = start[0] y = start[1] dig(x, y) print(x) print(y) for y in range(ROW): for x in range(COLUMN): if maze[y][x]=="PATH" : color = "white" else : color = "black" can.create_rectangle(x*SIZE, y*SIZE, (x+1)*SIZE, (y+1)*SIZE, fill=color, width=0) can.create_rectangle((COLUMN-2)*SIZE, (ROW-2)*SIZE, (COLUMN-1)*SIZE, (ROW-1)*SIZE ,fill="red") move() global win win = tk.Tk() frame_top = tk.Frame(win) frame_top.pack() global can can = tk.Canvas(frame_top, width=COLUMN*SIZE, height=ROW*SIZE) can.pack() m = tk.Menu(win) win.config(menu=m) om = tk.Menu(m, tearoff=0) m.add_cascade(label='Options', menu=om) om.add_command(label='New Game',command= new_game ) om.add_command(label='Settings', ) while len(departure)!=0 : start = departure.pop(0) x = start[0] y = start[1] dig(x, y) print(x) print(y) for y in range(ROW): for x in range(COLUMN): if maze[y][x]=="PATH" : color = "white" else : color = "black" can.create_rectangle(x*SIZE, y*SIZE, (x+1)*SIZE, (y+1)*SIZE, fill=color, width=0) can.create_rectangle((COLUMN-2)*SIZE, (ROW-2)*SIZE, (COLUMN-1)*SIZE, (ROW-1)*SIZE ,fill="red") move() win.bind("<Any-KeyPress>", keyPress) win.mainloop() main()
错误栈:
Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 1921, in __call__ return self.func(*args) File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 839, in callit func(*args) File "C:/Users/Admin/AppData/Local/Programs/Python/Python310/fileend.py", line 92, in move new_game() File "C:/Users/Admin/AppData/Local/Programs/Python/Python310/fileend.py", line 128, in new_game can.create_rectangle(x*SIZE, y*SIZE, (x+1)*SIZE, (y+1)*SIZE, fill=color, width=0) File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 2835, in create_rectangle return self._create('rectangle', args, kw) File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 2805, in _create return self.tk.getint(self.tk.call( _tkinter.TclError: invalid command name ".!frame.!canvas"
解决方案
错误根源
- 销毁
frame_top后,内部的Canvas组件can被彻底删除,但new_game仍尝试调用该组件的绘图方法,触发无效命令错误。 move函数通过after持续循环,即使组件销毁,循环仍会执行,引发后续错误。new_game中未声明全局变量,导致局部变量覆盖全局状态,逻辑混乱。- 存在缩进错误、按键绑定转义错误、多余函数调用等语法问题。
修复后的关键修改
- 保留Canvas组件:用
can.delete("all")清空画布内容,替代销毁frame_top,避免组件失效。 - 终止循环:新增
after_id变量保存after的ID,在new_game中用can.after_cancel(after_id)终止之前的move循环。 - 全局变量声明:在
new_game中添加全局变量声明,确保修改的是全局状态而非局部变量。 - 修复语法问题:修正
beforeX的缩进错误,将<Any-KeyPress>改为<Any-KeyPress>,移除多余的main()调用。
完整修复代码
import tkinter as tk import random from tkinter import messagebox SIZE = 10 COLUMN = 7 ROW = 7 departure = [[1, 1]] playerX = 1 playerY = 1 beforeX = 1 beforeY = 1 after_id = None maze = [] for y in range(ROW) : sub = [] for x in range(COLUMN) : if y==0 or y==ROW-1 or x==0 or x==COLUMN-1 : sub.append("WALL") else : sub.append("FIELD") maze.append(sub) def dig(x, y) : maze[y][x] = "PATH" canMove = [] if maze[y-1][x]=="FIELD" and maze[y-2][x]=="FIELD" : canMove.append("UP") if maze[y+1][x]=="FIELD" and maze[y+2][x]=="FIELD" : canMove.append("DOWN") if maze[y][x-1]=="FIELD" and maze[y][x-2]=="FIELD" : canMove.append("LEFT") if maze[y][x+1]=="FIELD" and maze[y][x+2]=="FIELD" : canMove.append("RIGHT") if len(canMove)==0 : return direction = random.choice(canMove) if direction=="UP" : maze[y-1][x]="PATH" maze[y-2][x]="PATH" y -= 2 if direction=="DOWN" : maze[y+1][x]="PATH" maze[y+2][x]="PATH" y += 2 if direction=="LEFT" : maze[y][x-1]="PATH" maze[y][x-2]="PATH" x -= 2 if direction=="RIGHT" : maze[y][x+1]="PATH" maze[y][x+2]="PATH" x += 2 departure.append([x, y]) dig(x, y) def keyPress(event) : global playerX, playerY, beforeX, beforeY if event.keysym=="Up" and maze[playerY-1][playerX]=="PATH" : beforeX = playerX beforeY = playerY playerY -=1 if event.keysym=="Down" and maze[playerY+1][playerX]=="PATH" : beforeX = playerX beforeY = playerY playerY +=1 if event.keysym=="Left" and maze[playerY][playerX-1]=="PATH" : beforeX = playerX beforeY = playerY playerX -=1 if event.keysym=="Right" and maze[playerY][playerX+1]=="PATH" : beforeX = playerX beforeY = playerY playerX +=1 def move() : global after_id can.create_oval(beforeX*SIZE+1, beforeY*SIZE+1, (beforeX+1)*SIZE-1, (beforeY+1)*SIZE-1, fill="white", width=0) can.create_oval(playerX*SIZE+2, playerY*SIZE+2, (playerX+1)*SIZE-2, (playerY+1)*SIZE-2, fill="blue") if playerX==COLUMN-2 and playerY==ROW-2 : messagebox.showinfo("INFORMATION", "CONGRATULATIONS!!!") new_game() after_id = can.after(100, move) def new_game(): global departure, playerX, playerY, beforeX, beforeY, maze, after_id # 终止之前的move循环 if after_id is not None: can.after_cancel(after_id) # 清空画布所有内容 can.delete("all") # 重置游戏状态 departure = [[1, 1]] playerX = 1 playerY = 1 beforeX = 1 beforeY = 1 maze = [] # 重新生成迷宫初始矩阵 for y in range(ROW) : sub = [] for x in range(COLUMN) : if y==0 or y==ROW-1 or x==0 or x==COLUMN-1 : sub.append("WALL") else : sub.append("FIELD") maze.append(sub) # 重新挖迷宫 while len(departure)!=0 : start = departure.pop(0) x = start[0] y = start[1] dig(x, y) # 绘制新迷宫 for y in range(ROW): for x in range(COLUMN): color = "white" if maze[y][x]=="PATH" else "black" can.create_rectangle(x*SIZE, y*SIZE, (x+1)*SIZE, (y+1)*SIZE, fill=color, width=0) # 绘制终点 can.create_rectangle((COLUMN-2)*SIZE, (ROW-2)*SIZE, (COLUMN-1)*SIZE, (ROW-1)*SIZE, fill="red") # 重新启动移动循环 move() # 初始化界面 win = tk.Tk() frame_top = tk.Frame(win) frame_top.pack() can = tk.Canvas(frame_top, width=COLUMN*SIZE, height=ROW*SIZE) can.pack() # 菜单设置 m = tk.Menu(win) win.config(menu=m) om = tk.Menu(m, tearoff=0) m.add_cascade(label='Options', menu=om) om.add_command(label='New Game', command=new_game) om.add_command(label='Settings') # 初始生成迷宫 while len(departure)!=0 : start = departure.pop(0) x = start[0] y = start[1] dig(x, y) # 绘制初始迷宫 for y in range(ROW): for x in range(COLUMN): color = "white" if maze[y][x]=="PATH" else "black" can.create_rectangle(x*SIZE, y*SIZE, (x+1)*SIZE, (y+1)*SIZE, fill=color, width=0) # 绘制初始终点 can.create_rectangle((COLUMN-2)*SIZE, (ROW-2)*SIZE, (COLUMN-1)*SIZE, (ROW-1)*SIZE, fill="red") # 启动移动循环 after_id = can.after(100, move) win.bind("<Any-KeyPress>", keyPress) win.mainloop()
内容的提问来源于stack exchange,提问作者UNTAKEU
相关产品推荐
相关产品推荐

