Python中如何终止其他函数运行?贪吃蛇方向控制冲突问题
解决贪吃蛇多方向移动冲突问题
你的问题核心在于:每个方向的移动方法里都通过window.after()创建了持续递归的定时任务,切换方向时旧任务没有被终止,导致多个方向的移动逻辑同时执行。要解决这个问题,只需要追踪并取消当前运行的定时任务即可。
具体修改方案
- 在
Snake类中添加一个属性,用于存储当前定时任务的ID,方便后续取消:
self.after_id = None # 存储当前移动的定时任务ID
- 每个移动方法执行前,先取消之前的定时任务(如果存在),再启动新的任务:
比如修改moveup方法:
def moveup(self, event): global eaten # 取消之前的定时任务 if self.after_id is not None: window.after_cancel(self.after_id) self.topy -= 40 self.bottomy -= 40 if not eaten: self.cavas.delete(self.squares[-1]) self.newsnake = self.cavas.create_rectangle(self.topx, self.topy, self.bottomx, self.bottomy, fill='green') self.squares.append(self.newsnake) # 保存新的定时任务ID self.after_id = window.after(100, self.moveup, event) window.update()
- 对
movedown、moveright、moveleft做同样的修改,在方法开头添加取消旧任务的代码,并更新self.after_id。
优化后的完整代码
count = 1 from time import * direction = None eaten = False WIDGIT_SIZE = 40 def declareup(): global direction if count == 1: direction = "up" def declaredown(): global direction if count == 1: direction = "down" def declareright(): global direction if count == 1: direction = "right" def declareleft(): global direction if count == 1: direction = "left" class Snake(): def __init__(self, canvas, topx, topy): self.cavas = canvas self.topx = topx self.topy = topy self.bottomx = WIDGIT_SIZE self.bottomy = WIDGIT_SIZE self.snake = self.cavas.create_rectangle(self.topx, self.topy, self.bottomx, self.bottomy, fill='green') self.squares = [self.snake] self.after_id = None # 新增:存储当前移动的定时任务ID def movedown(self, event): global eaten # 取消之前的定时任务 if self.after_id is not None: window.after_cancel(self.after_id) self.topy += 40 self.bottomy += 40 if not eaten: self.cavas.delete(self.squares[-1]) self.newsnake = self.cavas.create_rectangle(self.topx, self.topy, self.bottomx, self.bottomy, fill='green') self.squares.append(self.newsnake) # 保存新任务ID self.after_id = window.after(100, self.movedown, event) window.update() def moveup(self, event): global eaten if self.after_id is not None: window.after_cancel(self.after_id) self.topy -= 40 self.bottomy -= 40 if not eaten: self.cavas.delete(self.squares[-1]) self.newsnake = self.cavas.create_rectangle(self.topx, self.topy, self.bottomx, self.bottomy, fill='green') self.squares.append(self.newsnake) self.after_id = window.after(100, self.moveup, event) window.update() def moveright(self, event): global eaten if self.after_id is not None: window.after_cancel(self.after_id) self.topx += 40 self.bottomx += 40 if not eaten: self.cavas.delete(self.squares[-1]) self.newsnake = self.cavas.create_rectangle(self.topx, self.topy, self.bottomx, self.bottomy, fill='green') self.squares.append(self.newsnake) self.after_id = window.after(100, self.moveright, event) window.update() def moveleft(self, event): global eaten if self.after_id is not None: window.after_cancel(self.after_id) self.topx -= 40 self.bottomx -= 40 if not eaten: self.cavas.delete(self.squares[-1]) self.newsnake = self.cavas.create_rectangle(self.topx, self.topy, self.bottomx, self.bottomy, fill='green') self.squares.append(self.newsnake) self.after_id = window.after(100, self.moveleft, event) window.update() from tkinter import * window = Tk() window.geometry('520x520') window.config(background='black') window.resizable(False, False) canvas = Canvas(window, width=520, height=520, bg='black') gamesnake = Snake(canvas, 0, 0) window.bind('<Down>', gamesnake.movedown) window.bind('<Up>', gamesnake.moveup) window.bind('<Right>', gamesnake.moveright) window.bind('<Left>', gamesnake.moveleft) canvas.pack() window.mainloop()
额外优化建议
你可以把四个方向的移动逻辑合并成一个统一的方法,减少重复代码。比如添加一个move方法,根据方向参数处理坐标变化,然后在按键绑定里设置方向后调用这个统一方法,这样代码更简洁易维护。
内容的提问来源于stack exchange,提问作者Rama Zain
相关产品推荐
相关产品推荐

