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

Pygame贪吃蛇游戏绘制食物时触发AttributeError问题求助

解决你的Pygame贪吃蛇AttributeError及其他代码问题

先直接解决你遇到的AttributeError:
在第134行,你写了:

pygame.draw.rect(window.pygame.Color("RED"), pygame.Rect(int(foodpos[0]), int(foodpos[1]), 10, 10))

这里的问题是把参数顺序搞混了,还错误地在window后面追加了.pygame.Color。pygame.draw.rect的正确参数顺序是:绘制目标Surface(也就是你的window)、颜色、矩形对象。所以正确写法应该是:

pygame.draw.rect(window, pygame.Color("RED"), pygame.Rect(int(foodpos[0]), int(foodpos[1]), 10, 10))

你之前的写法把颜色放在了第一个参数的位置,还试图从window这个Surface对象里获取pygame属性,这就是报错'pygame.Surface' object has no attribute 'pygame'的核心原因。

接下来,你的代码里还有不少其他bug,不修复的话游戏还是无法正常运行,我逐一帮你指出并修正:

1. Snake类方法定义与逻辑错误

(1) change_direction_to方法命名冲突

你在__init__里定义了self.change_direction_to = self.direction,后面又定义了同名的方法,这会导致方法被覆盖。把__init__里的那行删掉,保留方法名change_direction_to,同时游戏主循环里的调用要改成对应的名字(你现在写的是snake.change_dir_to,要改成snake.change_direction_to)。

(2) move方法方向逻辑错误

你的move方法里,UP和DOWN方向修改的是self.position[0](x坐标),这会导致蛇上下移动时变成左右走,正确的应该是修改self.position[1](y坐标):

def move(self):
    if self.direction == "RIGHT":
        self.position[0] += 10
    if self.direction == "LEFT":
        self.position[0] -= 10
    if self.direction == "UP":
        self.position[1] -= 10  # 这里改成position[1]
    if self.direction == "DOWN":
        self.position[1] += 10  # 这里改成position[1]

(3) body_insert方法语法错误

这个方法的定义完全不对,参数应该是self,而且逻辑要调整:它应该在蛇移动后插入新的头部,吃到食物就不删除尾部,没吃到就删除尾部。正确的写法应该是:

def body_insert(self):
    # 把新头部插入身体列表开头
    self.body.insert(0, list(self.position))
    if self.position == foodpos:
        return 1  # 吃到食物,返回1表示加分
    else:
        self.body.pop()  # 没吃到,删除尾部
        return 0

另外,你之前的写法里参数写了0,这是完全错误的,类方法第一个参数必须是self。

(4) check_collision方法逻辑错误

  • 判断撞墙时,self.position < 0是错误的,应该分别判断x和y坐标是否超出范围;
  • 检查撞自身的代码缩进错误,它应该是check_collision方法里的一部分,而不是类的顶级代码。
    修正后的check_collision:
def check_collision(self):
    # 检查撞墙(对应700x600窗口,蛇块10px)
    if self.position[0] > 690 or self.position[0] < 0:
        return 1
    if self.position[1] > 590 or self.position[1] < 0:
        return 1
    # 检查撞自身
    for body_part in self.body[1:]:
        if self.position == body_part:
            return 1
    return 0

2. FoodSpawner类错误

(1) 食物位置初始化错误

你初始化self.position时用了逗号,变成了元组([x], [y]),这会导致后面取foodpos[0]和foodpos[1]时得到的是列表,而不是数值。正确的写法应该是:

def __init__(self):
    self.position = [random.randrange(1, 70) * 10, random.randrange(1, 60) * 10]  # 对应700x600窗口
    self.is_food_on_screen = True

spawn_food方法里也要改成同样的写法:

def spawn_food(self):
    if not self.is_food_on_screen:
        self.position = [random.randrange(1, 70) * 10, random.randrange(1, 60) * 10]
        self.is_food_on_screen = True
    return self.position

(2) set_food_on_screen方法拼写错误

你写的是self.is_food_on_sceen = b,少了一个r,应该是self.is_food_on_screen = b。

3. 游戏主循环错误

(1) 方向控制重复错误

你在键盘事件处理里,多次写了event.key == pygame.K_RIGHT,导致UP和DOWN方向永远触发不了,正确的应该是:

elif event.type == pygame.KEYDOWN:
    if event.key == pygame.K_RIGHT:
        snake.change_direction_to("RIGHT")
    elif event.key == pygame.K_LEFT:
        snake.change_direction_to("LEFT")
    elif event.key == pygame.K_UP:
        snake.change_direction_to("UP")
    elif event.key == pygame.K_DOWN:
        snake.change_direction_to("DOWN")

用elif而不是多个if,避免多个方向同时触发。

(2) snake.move()调用错误

你写的是if snake.move(foodpos) == 1:,但move方法不需要参数,而且判断是否吃到食物应该调用body_insert方法:

snake.move()  # 先让蛇移动
# 然后处理身体插入和食物判断
foodpos = food_spawner.spawn_food()
if snake.body_insert() == 1:
    score += 1
    food_spawner.set_food_on_screen(False)

(3) 标题更新拼写错误

你写的是pygme.display.set_caption,少了一个a,应该是pygame.display.set_caption。

修正后的完整代码(关键部分已修复)

import pygame, sys, random, time
BLACK = (0, 0, 0)
WHITE = (225, 225, 225)
BLUE = (0, 0, 225)
RED = (225, 0, 0)

class Snake(object):
    def __init__(self):
        self.position = [100, 50]  # 设置蛇的初始位置
        self.body = [[100, 50], [90, 50], [80, 50]]  # 设置蛇初始身体长度为3段
        self.direction = "RIGHT"

    # ---------------------------- 允许改变方向,但不能直接反向
    def change_direction_to(self, dir):
        if dir == "RIGHT" and not self.direction == "LEFT":
            self.direction = "RIGHT"
        elif dir == "LEFT" and not self.direction == "RIGHT":
            self.direction = "LEFT"
        elif dir == "UP" and not self.direction == "DOWN":
            self.direction = "UP"
        elif dir == "DOWN" and not self.direction == "UP":
            self.direction = "DOWN"
    # ----------------------------

    # -------------------------------- 设置蛇的移动速度
    def move(self):
        if self.direction == "RIGHT":
            self.position[0] += 10
        if self.direction == "LEFT":
            self.position[0] -= 10
        if self.direction == "UP":
            self.position[1] -= 10
        if self.direction == "DOWN":
            self.position[1] += 10
    # ---------------------------------

    # ----------------------------- 检查蛇是否吃到食物
    def body_insert(self):
        self.body.insert(0, list(self.position))
        if self.position == foodpos:
            return 1
        else:
            self.body.pop()
            return 0
    # -----------------------------

    # ---------------------------------检查蛇是否撞墙和自身
    def check_collision(self):
        # 撞墙判断
        if self.position[0] > 690 or self.position[0] < 0:
            return 1
        if self.position[1] > 590 or self.position[1] < 0:
            return 1
        # 撞自身判断
        for body_part in self.body[1:]:
            if self.position == body_part:
                return 1
        return 0
    # ----------------------------------

    def get_head_position(self):
        return self.position
    def get_body(self):
        return self.body

class FoodSpawner:
    def __init__(self):
        self.position = [random.randrange(1, 70) * 10, random.randrange(1, 60) * 10]
        self.is_food_on_screen = True
    def spawn_food(self):
        if not self.is_food_on_screen:
            self.position = [random.randrange(1, 70) * 10, random.randrange(1, 60) * 10]
            self.is_food_on_screen = True
        return self.position
    def set_food_on_screen(self, b):
        self.is_food_on_screen = b  # 修正了拼写错误

window = pygame.display.set_mode((700, 600))
pygame.display.set_caption("Definitely Not Snake")
fps = pygame.time.Clock()
score = 0
snake = Snake()
food_spawner = FoodSpawner()

def game_over():
    pygame.quit()
    sys.exit()

while True:
    for event in pygame.event.get():
        # ------------------------- 退出游戏
        if event.type == pygame.QUIT:
            game_over()
        # -------------------------
        # ------------------------- 蛇的移动控制
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                snake.change_direction_to("RIGHT")
            elif event.key == pygame.K_LEFT:
                snake.change_direction_to("LEFT")
            elif event.key == pygame.K_UP:
                snake.change_direction_to("UP")
            elif event.key == pygame.K_DOWN:
                snake.change_direction_to("DOWN")
        # -------------------------
    # ----------------------------- 蛇移动与吃到食物判断
    snake.move()
    foodpos = food_spawner.spawn_food()
    if snake.body_insert() == 1:
        score += 1
        food_spawner.set_food_on_screen(False)
    # ------------------------------
    # ------------------------------ 绘制屏幕、蛇和食物
    window.fill(pygame.Color("BLACK"))
    for pos in snake.get_body():
        pygame.draw.rect(window, pygame.Color("BLUE"), pygame.Rect(pos[0], pos[1], 10, 10))
    # 修正了draw.rect的参数顺序
    pygame.draw.rect(window, pygame.Color("RED"), pygame.Rect(int(foodpos[0]), int(foodpos[1]), 10, 10))
    # ------------------------------
    if snake.check_collision() == 1:
        game_over()
    # 修正了拼写错误
    pygame.display.set_caption("Definitely not Snake | Score : " + str(score))
    pygame.display.flip()
    fps.tick(24)

现在你可以运行修正后的代码,应该能正常启动贪吃蛇游戏了。如果还有其他问题,可以继续调试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 11:17:46