You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何终止其他函数运行?贪吃蛇方向控制冲突问题

解决贪吃蛇多方向移动冲突问题

你的问题核心在于:每个方向的移动方法里都通过window.after()创建了持续递归的定时任务,切换方向时旧任务没有被终止,导致多个方向的移动逻辑同时执行。要解决这个问题,只需要追踪并取消当前运行的定时任务即可。

具体修改方案

  1. 在Snake类中添加一个属性,用于存储当前定时任务的ID,方便后续取消:
self.after_id = None  # 存储当前移动的定时任务ID
  1. 每个移动方法执行前,先取消之前的定时任务(如果存在),再启动新的任务:
    比如修改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()
  1. 对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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 08:05:38