Глава 19 · Финал

Snake Pro — финальная игра

Тот же самый прототип из раздела 19.1 — но теперь с моделью состояния, игровым тиком и архитектурой, которая выдержит рост проекта.

Итоговая программа

Финальное окно Snake Pro: несколько сегментов тела, яблоко, счёт и рекорд на тёмном поле
Реальное окно финальной версии — та же самая идея, что открывала главу в разделе 19.1, но теперь мы знаем, из чего она построена.

Файл целиком, самодостаточный и без невидимых зависимостей от других уроков:

projects/turtle/snake/snake.py

snake.py — структура
class Direction(Enum): ...
class GameStatus(Enum): ...

@dataclass
class GameState: ...

def next_head(head, direction): ...
def move_snake(snake, new_head, *, grow): ...
def is_wall_collision(head): ...
def is_self_collision(new_head, body_after_move): ...
def choose_food(snake, rng): ...
def calculate_delay(score): ...
def new_game_state(rng, *, high_score=0): ...

class SnakeApp:
    def __init__(self, *, rng=None): ...
    def bind_keys(self): ...
    def request_direction(self, direction): ...
    def game_tick(self): ...
    def toggle_pause(self): ...
    def restart(self): ...
    def render(self): ...
    def run(self): ...

def main():
    app = SnakeApp()
    app.run()

if __name__ == "__main__":
    main()
Запустите игру у себя
python snake.py в терминале. Стрелки или WASD — движение, Space — пауза, R — новая игра. Сравните с snake_basic.py (раздел 19.8) — та же идея игры, но совершенно другая внутренняя архитектура.

Чек-лист готового приложения

МОДЕЛЬ
  • GameState — snake, direction, food: Position | None, score, status, delay_ms, без Turtle внутри
  • чистые функции правил — next_head, move_snake, is_wall_collision, is_self_collision, choose_food, calculate_delay
  • новая голова + старое тело вместо цикла по сегментам
ЦИКЛ
  • тик через screen.ontimer(), без блокирующего цикла и time.sleep()
  • клавиатура запрашивает направление, тик его применяет
  • поколение (generation) инвалидируется сразу и при паузе, и при возобновлении — не только при restart()
  • ровно одна активная цепочка тиков в любой момент времени
ФУНКЦИИ ИГРЫ
  • pause/resume без пересоздания змейки
  • restart с сохранением рекорда
  • скорость растёт вместе со счётом, не опускаясь ниже минимума
  • заполненное поле — явный GameStatus.WON, а не еда внутри змейки
  • HUD — отдельная полоса над полем, а не поверх легальных клеток
ТЕСТИРОВАНИЕ
  • правила протестированы без единого настоящего окна
  • детерминированная еда через random.Random(seed)
  • render() переиспользует пул Turtle-сегментов

Палитра игры

Финальная игра использует всего пять цветов — не для того, чтобы выглядеть скромно, а потому что различать голову, тело и еду проще по контрасту, а не по количеству оттенков:

Фон
#000000
Голова
#FFFFFF
Тело
#4ECDC4
Еда
#FF5D5D
Текст
#FFFFFF
Практика: Snake Pro целиком
Модуль turtle открывает нативное окно Python — выполните локально в VS Code, PyCharm или Jupyter
Практика выполняется локально
Открыть практику →