Итак, я пытался создать игру-змейку, обучающуюся из репозитория github, и у меня возникла ошибка, когда я попытался запустить скрипт, я получил ошибку трассировки, в которой говорилось, что для значения установлено значение none.

import os
os.environ["DISPLAY"] = ": 0.0"
import pygame
import random
from enum import Enum
from collections import namedtuple

pygame.init()
font = pygame.font.Font('PermanentMarker-Regular.ttf', 25)

class Direction(Enum):
    RIGHT = 1
    LEFT = 2
    UP = 3
    DOWN = 4

Point = namedtuple('Point',('x,y'))

#rgb colors
WHITE = (255,255,255)
RED = (200,0,0)
BLUE1 = (0,0,255)
BLUE2 = (0,100,255)
BLACK = (0,0,0)

BLOCK_SIZE = 20
SPEED = 40

class SnakeGame:
    def __init__(self, w=640, h=480):
        self.w = w 
        self.h = h
        # init display
        self.display = pygame.display.set_mode((self.w, self.h))
        pygame.display.set_caption('Snake')
        self.clock = pygame.time.Clock()

        # init game state
        self.direction = Direction.RIGHT

        self.head = Point(self.w/2, self.h/2) # This will set self.head.x = self.w/2 and self.head.y = self.h/2
        self.snake = [self.head, Point(self.head.x-BLOCK_SIZE, self.head.y),Point(self.head.x-(2*BLOCK_SIZE), self.head.y)]

        
        self.score = 0
        self.food = None
        self._place_food()

    def _place_food(self):
        x = random.randint(0, (self.w-BLOCK_SIZE)//BLOCK_SIZE)*BLOCK_SIZE
        y = random.randint(0, (self.h-BLOCK_SIZE)//BLOCK_SIZE)*BLOCK_SIZE
        self.food = Point(x,y)
        if self.food in self.snake:
            self._place_food()

    def _play_step(self):
        # 1. Collect user input
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    self.direction = Direction.LEFT
                elif event.key == pygame.K_RIGHT:
                    self.direction == Direction.RIGHT
                elif event.key == pygame.K_UP:
                    self.direction == Direction.UP
                elif event.key == pygame.K_DOWN:
                    self.direction == Direction.DOWN

        # 2. move
        self._move(self.direction)
        self.snake.insert(0, self.head)

        # 3. check if game over
        game_over = False
        if self._is_collision():
            game_over = True
            return game_over, self.score

        # 4. place new food or just move
        if self.head == self.food:
            self.score += 1
            self._place_food()
        else:
            self.snake.pop()

        # 5. update ui and clock
        self._update_ui()
        self.clock.tick(SPEED)
        # 6. return game over and score

    def _is_collision(self):
        # hits boundary
        if self.head.x > self.w - BLOCK_SIZE or self.head.x < 0 or self.head.y > self.h - BLOCK_SIZE or self.head.y < 0:
            return True
        # hits itself
        if self.head in self.snake[1:]:
            return True
        
        return False

    def _update_ui(self):
        self.display.fill(BLACK)
        
        for pt in self.snake:
            pygame.draw.rect(self.display, BLUE1, pygame.Rect(pt.x, pt.y, BLOCK_SIZE, BLOCK_SIZE))
            pygame.draw.rect(self.display, BLUE2, pygame.Rect(pt.x+4, pt.y+4, 12,12))

        pygame.draw.rect(self.display, RED, pygame.Rect(self.food.x, self.food.y, BLOCK_SIZE, BLOCK_SIZE))

        text = font.render("Score: " + str(self.score), True, WHITE)
        self.display.blit(text, [0,0])
        pygame.display.flip()

    def _move(self, direction):
        x = self.head.x
        y = self.head.y
        if direction == Direction.RIGHT:
            x += BLOCK_SIZE
        elif direction == Direction.LEFT:
            x -= BLOCK_SIZE
        elif direction == Direction.UP:
            y -= BLOCK_SIZE
        elif direction == Direction.DOWN:
            y += BLOCK_SIZE

        self.head = Point(x, y)

if __name__ == '__main__':
    game = SnakeGame()

    # game loop
    while True:
        game_over, score = game._play_step()

        if game_over == True:
            break

    print("Score:", score)

И у меня есть ошибка:

Traceback (most recent call last):
  File "/home/user/Python/snakeAi/snake.py", line 137, in <module>
    game_over, score = game._play_step()
TypeError: cannot unpack non-iterable NoneType object

Я попробовал сравнить оригинальный сценарий с моим, и ничего не упало мне в глаза. Так что я очень запутался.

-2
n1tr0z3n 20 Май 2021 в 23:14

1 ответ

Лучший ответ

Если _play_step доходит до конца, а игра еще не закончена, он проваливается, и нет оператора возврата. Как говорится, это возвращает None. Вы должны что-то вернуть. Наверное, добавлю это:

    return game_over, self.score
1
Tim Roberts 20 Май 2021 в 20:18