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

Python Tkinter贪吃蛇游戏故障:苹果不显示、蛇身异常增长

解决你的Tkinter贪吃蛇问题:苹果不显示与蛇身增长异常

嘿,我仔细看了你的代码,找到了导致你遇到的两个问题的根源,咱们一步步来修复:

问题1:苹果生成后画布上看不到

你的apple_make函数里有三个明显的问题:

  • 你用create_line画苹果时,起点和终点是同一个坐标,这样画出来的线长度为0,当然看不到!换用create_oval画圆形苹果更符合预期,也能正常显示。
  • apple_y1被硬编码成了10,没有随机生成y坐标,就算能显示,苹果也只会固定在顶部。
  • 没有删除之前的苹果,多次生成后会有多个苹果留在画布上。

修复后的apple_make函数:

def apple_make(self):
    global apple_x1, apple_y1
    # 先删掉之前的苹果,给苹果加个固定标签方便操作
    can.delete("apple")
    # 生成和蛇身对齐的随机坐标(必须是etch_len的倍数,不然蛇永远吃不到苹果)
    apple_x1 = random.randint(10, 59) * etch_len
    apple_y1 = random.randint(10, 59) * etch_len
    # 画一个红色圆形苹果
    can.create_oval(apple_x1-5, apple_y1-5, apple_x1+5, apple_y1+5, fill="red", tag="apple")

问题2:蛇身增长需要多次移动,且次数递增

这个问题有两个核心原因:

  1. 拼写错误:move_down函数里的条件判断写的是y3==apple,这里应该是apple_y1!导致向下移动时吃到苹果根本不会触发增长,只有其他方向才会,这会让你误以为增长延迟。
  2. 逻辑错误:你当前的逻辑是每次移动都添加一段蛇身,然后删除最旧的一段。就算吃到苹果增加了body_len,remove_last还是会执行,相当于这次移动加了一段又删了一段,蛇身并没有立刻变长。后续remove_last会因为body_len变大,删除更早的标签,导致需要多次移动才能体现出增长,而且每次增长后需要多移动一次。

正确的逻辑应该是:吃到苹果时,只加新段不删旧段;没吃到时,加新段同时删旧段。

以move_up为例,修改后的代码:

def move_up(self): 
    global x3, y3, num, apple_x1, apple_y1, body_len
    num += 1
    tag = str(num)
    # 先添加新的蛇身段
    can.create_line(x3, y3, x3, y3-etch_len, width=etch_wid, fill=colour[0], tag=tag)
    body_tags.append(tag)  # 用列表存蛇身标签,更易管理
    y3 -= etch_len
    
    # 判断是否吃到苹果
    if x3 == apple_x1 and y3 == apple_y1:
        body_len += 1
        apple_make(self)
    else:
        # 没吃到才删除最后一段
        remove_last()

另外,我给你加了一个body_tags列表来存储蛇身的标签,代替原来用num计算的方式,这样删除最旧段的逻辑更清晰,避免计算错误:

# 全局定义列表
body_tags = []

# remove_last函数修改为
def remove_last():
    if len(body_tags) > body_len:
        old_tag = body_tags.pop(0)
        can.delete(old_tag)

额外优化:初始化蛇身

原来的代码没有初始化蛇身,一开始蛇只有一段,我加了初始化代码,让游戏开始时就有设定长度的蛇:

# 初始化蛇身
for i in range(body_len):
    tag = str(num)
    can.create_line(x3, y3 + i*etch_len, x3, y3 + (i+1)*etch_len, width=etch_wid, fill=colour[0], tag=tag)
    body_tags.append(tag)
    num += 1

完整修复后的代码

from tkinter import * 
import random 

window = Tk() 
window.title("snake") 
window.geometry("600x600") 
can = Canvas(window, height=600, width=600, background="white") 
can.pack() 

# 全局变量
num = 1
x3 = 100 
y3 = 100 
etch_len = 10 
etch_wid = 10 
body_len = 2 
apple_x1 = 0 
apple_y1 = 0 
colour = ["black"]
body_tags = []  # 存储蛇身标签的列表,方便管理

# 初始化蛇身
for i in range(body_len):
    tag = str(num)
    can.create_line(x3, y3 + i*etch_len, x3, y3 + (i+1)*etch_len, width=etch_wid, fill=colour[0], tag=tag)
    body_tags.append(tag)
    num += 1

def move_up(self): 
    global x3, y3, num, apple_x1, apple_y1, body_len
    num += 1
    tag = str(num)
    # 添加新的蛇身段
    can.create_line(x3, y3, x3, y3 - etch_len, width=etch_wid, fill=colour[0], tag=tag)
    body_tags.append(tag)
    y3 -= etch_len
    
    # 判断是否吃到苹果
    if x3 == apple_x1 and y3 == apple_y1:
        body_len += 1
        apple_make(self)
    else:
        remove_last()

def move_down(self): 
    global x3, y3, num, apple_x1, apple_y1, body_len
    num += 1
    tag = str(num)
    # 添加新的蛇身段
    can.create_line(x3, y3, x3, y3 + etch_len, width=etch_wid, fill=colour[0], tag=tag)
    body_tags.append(tag)
    y3 += etch_len
    
    # 修复拼写错误:apple -> apple_y1
    if x3 == apple_x1 and y3 == apple_y1:
        body_len += 1
        apple_make(self)
    else:
        remove_last()

def move_left(self): 
    global x3, y3, num, apple_x1, apple_y1, body_len
    num += 1
    tag = str(num)
    # 添加新的蛇身段
    can.create_line(x3, y3, x3 - etch_len, y3, width=etch_wid, fill=colour[0], tag=tag)
    body_tags.append(tag)
    x3 -= etch_len
    
    if x3 == apple_x1 and y3 == apple_y1:
        body_len += 1
        apple_make(self)
    else:
        remove_last()

def move_right(self): 
    global x3, y3, num, apple_x1, apple_y1, body_len
    num += 1
    tag = str(num)
    # 添加新的蛇身段
    can.create_line(x3, y3, x3 + etch_len, y3, width=etch_wid, fill=colour[0], tag=tag)
    body_tags.append(tag)
    x3 += etch_len
    
    if x3 == apple_x1 and y3 == apple_y1:
        body_len += 1
        apple_make(self)
    else:
        remove_last()

def remove_last():
    # 删除最旧的蛇身段,保持蛇身长度为body_len
    if len(body_tags) > body_len:
        old_tag = body_tags.pop(0)
        can.delete(old_tag)

def apple_make(self):
    global apple_x1, apple_y1
    # 删除之前的苹果
    can.delete("apple")
    # 生成与蛇身对齐的随机坐标(10的倍数)
    apple_x1 = random.randint(10, 59) * etch_len
    apple_y1 = random.randint(10, 59) * etch_len
    # 绘制圆形苹果
    can.create_oval(apple_x1-5, apple_y1-5, apple_x1+5, apple_y1+5, fill="red", tag="apple")

# 绑定按键事件
window.bind("w", move_up) 
window.bind("s", move_down) 
window.bind("a", move_left) 
window.bind("d", move_right) 
window.bind("<Up>", apple_make) 

# 游戏开始时生成第一个苹果
apple_make(None)

window.mainloop()

现在运行这个代码,苹果会正常显示,蛇吃到苹果后会立刻增长,不会再有延迟的问题啦!

内容的提问来源于stack exchange,提问作者Alex fradle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:00:08