Artean

Создание змейки на Python: инструкция для начинающих

О чём это руководство и какой результат вы получите

В этой статье мы создаем с нуля рабочую игру Snake («Змейка») на Python с помощью библиотеки pygame. В конце у вас будет готовый файл с кодом, который можно запустить, изменить под себя, превратить в промо-игру или учебный проект. Это не просто набор фрагментов кода: каждое решение разобрано так, чтобы вы понимали, как устроена логика игрового цикла, движения, столкновения и обработки нажатий клавиш.

Как создать игру змейка на Python с нуля — пошаговое руководство

Минимум, который стоит знать до начала:

  • что такое переменные и типы данных (int, list, set, bool);
  • как работают условные операторы if / elif / else;
  • как писать циклы for и while;
  • как объявляется функция через def и что такое параметры и возврат значения.

Если вы уже пробовали писать небольшие скрипты на Python, но ещё не собирали цельную игру, это руководство закроет разрыв между «знаю синтаксис» и «умею собрать законченную game». Если вы опытный разработчик, статья пригодится как быстрый шаблон: можно за вечер получить работающую змейку и дальше использовать её как основу под мини-игру в веб-сервисе, мобильном приложении, CRM или промо-кампании.

Логика, которую вы осваиваете здесь, напрямую переносится в коммерческую разработку: структура игрового цикла похожа на цикл обработки событий в интерфейсах, работа с координатами — на расчёт позиций элементов на экране, система счёта и скорости — на механику прогрессии и метрик в реальных продуктах. Ту же архитектуру легко масштабировать до мини-игр в интернет-магазине или обучающих модулей внутри корпоративной системы.

Инструменты и подходы: как лучше начать создание змейки на Python

Для реализации игры используем стек:

  • Python 3.x — любой актуальный релиз;
  • библиотека pygame — для окна, отрисовки, событий клавиатуры и таймера.

Почему pygame, а не что-то другое:

  • он специально создан для 2D-игр и простых анимаций;
  • даёт полный контроль над игрового цикла: события (event), отрисовка, управление скоростью обновления;
  • устанавливается одной командой и работает на Windows, macOS и Linux;
  • код получается компактным: всё — в одном файле, без сложных сцен, инспекторов и редакторов.

Установка сведётся к двум шагам:

  • установить Python c официального сайта, отметив пункт «Add Python to PATH»;
  • в командной строке выполнить: pip install pygame.

Альтернативы, о которых стоит знать:

  • Консольная змейка на чистом Python — без окон и графики. Полезна, если хотите отточить алгоритмы: работа со списком координат, поиск столкновения, генерация еды через модуль random. Но нет ощущения полноценной игры и визуальной реакции.
  • tkinter — стандартная библиотека для окон. Можно сделать простое поле, но для анимации и стабильной частоты кадров придётся больше бороться с ограничениями, чем заниматься логикой игры.
  • Веб-вариант на JavaScript и canvas — правильный путь, если целитесь именно в браузерную игру. Однако для первого проекта на Python проще собрать игровые механики, а уже потом переносить идею.
  • Мобильные движки (Unity, Godot) — мощнее, но перегружены функциями. Чтобы вывести «квадратик-змейку», придётся разбираться с десятками сущностей. Для учебной задачи это избыточно.

Понять, что pygame вам подходит, легко:

  • вам нужен простой 2D без физики и 3D-графики;
  • вы хотите управлять всем из кода, а не через визуальный редактор;
  • важнее быстро получить результат, чем тратить время на освоение тяжёлого движка.

Минимальная структура проекта на старте:

  • один файл, например snake_game.py, в котором последовательно идут: блок import (pygame, random, time при необходимости), блок констант, функции отрисовки и логики, затем основной блок запуска с игровым циклом;
  • по мере роста проекта можно разнести код на модули: отдельный файл для настроек, отдельный — для объекта змейки, отдельный — для экрана меню.

Логика игры «Змейка» как система: из чего она состоит

Прежде чем писать код, полезно собрать мысленную модель игры: из каких компонентов она состоит и как они взаимодействуют в каждом кадре обновления.

Первый элемент — игровое поле. Вместо работы с каждым пикселем мы используем дискретную сетку: клетки одинакового размера, например 20×20 пикселей. Экран (window) шириной 600×400 пикселей превращается в поле 30×20 клеток. Это сразу решает несколько задач:

  • координаты змейки и еды проще хранить как (x, y) в клетках, а не в пикселях;
  • движения всегда на одну клетку, игра выглядит «ровной» и предсказуемой;
  • меньше шансов на ошибки со «сдвигами» и полукоординатами.

Дальше — сама змейка. Удобное представление — список координат:

  • каждый элемент списка — кортеж (x, y);
  • первый элемент — голова, последний — хвост;
  • одно движение — это добавление новой головы и, чаще всего, удаление последнего элемента.

Если двигаться вправо, то новые координаты головы: (head_x + 1, head_y). Направления движения удобно кодировать как пары dx, dy: right = (1, 0), left = (-1, 0), up = (0, -1), down = (0, 1). Тогда каждая итерация цикла — это head_x + dx, head_y + dy. Важно сразу договориться, что единица — это одна клетка.

Еда в игре — это одна свободная клетка поля. Типичный подход:

  • вычислить все возможные координаты поля;
  • убрать из них клетки, занятые телом змейки (можно использовать set для ускорения проверки);
  • выбрать случайную свободную клетку через random.choice или random.randrange.

Проверка, что еда не появилась «внутри» змейки, решается автоматически, если мы генерируем её только из множества свободных клеток. Если свободных клеток нет, значит змейка заняла поле целиком — это тоже интересный конец игры.

Следующий блок — столкновения. Нас интересуют два типа:

  • Столкновение со стеной: голова вышла за границы поля. Если координаты головы меньше 0 или больше либо равны числу клеток по оси X/Y, игра заканчивается. В вариантах с «телепортом» можно не завершать игру, а переносить голову на противоположную сторону.
  • Столкновение с собой: голова вошла в клетку, где уже есть часть тела. Это можно проверить через условие: если новая позиция головы есть в списке тела или в множестве (set) координат.

Управление движением — это обработка нажатий клавиш. В pygame это делается через очередь событий: в каждом кадре цикла мы проходим по pygame.event.get() и ищем события типа KEYDOWN. Если нажата стрелка left, меняем направление на (-1, 0), если right — на (1, 0) и так далее. Важный нюанс: нельзя разрешать мгновенный разворот на 180 градусов (с right на left и наоборот), иначе игрок может случайно «врезаться сам в себя» в одну и ту же клетку.

Скорость игры управляется частотой обновления экрана. В pygame обычно используют объект clock: clock = pygame.time.Clock(), а в конце каждой итерации вызывают clock.tick(FPS). Значение FPS задаёт максимально возможное количество кадров в секунду. Для змейки достаточно 10–15 FPS на старте, дальше можно плавно увеличивать скорость в зависимости от количества очков.

Всё это связывает игровой цикл — сердце игры:

  • обработать ввод (event): закрытие окна, нажатия клавиш, изменение направления;
  • обновить состояние: сдвинуть голову змейки, проверить столкновения, перерасчёт счёта и скорости;
  • отрисовать: очистить фон, нарисовать поле, змейку, еду, текст счёта, обновить экран.

Если этот цикл сделать «размазанным» по коду, игра начнёт вести себя странно: FPS будет плавать, задержки нажатий увеличатся, появятся случайные ускорения. Чёткая последовательность операций внутри одного while-цикла — основа предсказуемой и управляемой игры.

Подготовка проекта на Python: каркас игры без деталей

Создаём файл проекта, например snake_game.py. Первый шаг — базовый каркас без логики змейки.

В начале файла пишем блок import:

  • import pygame
  • import random
  • import time (по необходимости, если будете замерять паузы)

Дальше инициализируем pygame и создаём окно:

  • pygame.init()
  • window_width = 600, window_height = 400
  • window = pygame.display.set_mode((window_width, window_height))
  • pygame.display.set_caption(«Snake»)
  • clock = pygame.time.Clock()

Определяем ключевые константы:

  • cell_size = 20 — размер клетки в пикселях;
  • cols = window_width // cell_size, rows = window_height // cell_size — размер поля в клетках;
  • colors: background_color, snake_color, food_color, text_color — лучше вынести в отдельные переменные, чтобы легко менять оформление;
  • start_speed = 10 — базовый FPS, от которого будет зависеть скорость движения.

Важно сразу описать минимальный игровой цикл:

  • running = True;
  • while running:
  • обработка событий: если event.type == pygame.QUIT, то running = False;
  • очистка экрана: window.fill(background_color);
  • обновление экрана: pygame.display.flip();
  • управление временем: clock.tick(start_speed).

На этом этапе у вас уже открывается окно, корректно закрывается по нажатию на крестик, фон перерисовывается каждый кадр. Это кажется мелочью, но именно такой «правильный» каркас защищает от множества будущих багов, связанных с зависаниями или неверной частотой обновления.

Даже сейчас есть смысл разбить код на функции, чтобы не получить сплошной «спагетти-код»:

  • функция draw_grid(window) — если захотите рисовать сетку;
  • функция draw_snake(window, snake_body) — отрисовка змейки по списку координат;
  • функция draw_food(window, food_pos);
  • функция main() — внутри неё весь игровой цикл; внизу файла условие запуска: if __name__ == «__main__»: def main() вызов.

Такой каркас легко расширять: вы добавляете новую функцию — например, рендер счёта через pygame.font.Font — не ломая структуру всего файла.

Пошаговое создание змейки на Python: от первой клетки до готовой игры

  1. Шаг 1. Представление змейки в коде
  2. Сначала описываем структуру данных для тела змейки и направления движения. Внутри функции main задаём стартовое положение:
  • snake = [(cols // 2, rows // 2)] — список, в котором пока одна клетка-голова посередине поля;
  • direction = (1, 0) — движемся вправо (right);
  • можно завести переменную для хранения последнего направления, чтобы контролировать допустимые повороты.
  1. Задайте также флаг, который покажет, идёт ли игра: game_over = False. Это пригодится для экрана окончания игры и рестарта.
  2. Шаг 2. Движение змейки по полю
  3. Каждую итерацию цикла вычисляем новые координаты головы:
  • head_x, head_y = snake[0];
  • dx, dy = direction;
  • new_head = (head_x + dx, head_y + dy);
  • snake.insert(0, new_head) — добавляем новую голову в начало списка.
  1. Если змейка не ест еду в этом ходе, удаляем последний элемент списка: snake.pop(). Что произойдёт, если этого не сделать? Длина змейки будет расти на 1 клетку каждый кадр, игра превратится в непрерывное расширение без движения. Так мы разделяем два эффекта: «движение» (голова добавилась, хвост удалился) и «рост» (голова добавилась, хвост остался).
  2. Чтобы проверить, что змейка двигается ровно, удобно временно включить вывод координат в консоль: print(snake). Если всё правильно, список координат будет «сдвигаться» по оси X или Y на единицу без скачков.
  3. Шаг 3. Отрисовка змейки и поля с помощью pygame
  4. Теперь связываем координаты сетки с пикселями экрана (экран — в пикселях, логика — в клетках). Каждая клетка (x, y) превращается в прямоугольник:
  • pixel_x = x * cell_size;
  • pixel_y = y * cell_size;
  • pygame.draw.rect(window, snake_color, (pixel_x, pixel_y, cell_size, cell_size)).
  1. Эту логику лучше спрятать в отдельную функцию draw_snake(window, snake). Так легче менять внешний вид: например, рисовать голову другим цветом или со скруглёнными углами. Для аккуратного вида используйте контрастные, но не ядовитые цвета: тёмный фон, светлая змейка и заметная еда.
  2. Если хотите, чтобы игра выглядела ещё аккуратнее, можно добавить сетку поля: в цикле по колонкам и строкам нарисовать линии. Но это необязательно и иногда только отвлекает.
  3. Шаг 4. Еда и рост змейки
  4. Нужно создать функцию, которая генерирует координаты еды в свободной клетке. Подход:
  • завести множество занятых клеток: occupied = set(snake);
  • в цикле по всем клеткам поля собрать список free_cells, куда добавлять клетки, которых нет в occupied;
  • выбрать еду: food = random.choice(free_cells).
  1. Храните food как одну координату (x, y). В игровом цикле, после движения головы, проверяйте: если new_head == food, значит, змейка съела еду. В этом случае не вызываем snake.pop() — хвост не удаляется, длина увеличивается на 1. После этого генерируем новую еду через описанную выше функцию.
  2. Если змейка не растёт или растёт рывками, проверяйте порядок действий в цикле:
  • сначала двигаем голову (insert);
  • затем проверяем, съели ли еду (сравнение с food);
  • и только потом решаем, удалять хвост или нет.
  1. Перепутанный порядок легко даёт эффект, когда хвост удаляется ещё до проверки, и визуально рост становится неровным.
  2. Шаг 5. Столкновения и окончание игры
  3. После вычисления new_head и до отрисовки проверяем два типа столкновений.
  • Столкновение со стеной: если new_head_x меньше 0 или больше либо равен cols, или new_head_y меньше 0 или больше либо равен rows, считаем, что игра закончилась. В этом случае game_over = True.
  • Столкновение с собой: если new_head уже есть в теле змейки. Тут удобен set: body = set(snake), но важно не включать в него только что вставленную голову. Практичнее проверить по старому списку: если new_head in snake, до вставки головы.
  1. После установки game_over можно сделать две стратегии:
  • моментальный выход из основного while-цикла и завершение программы;
  • переход в экран «Game Over»: отдельный while, где рисуется текст и ждётся нажатие клавиши для рестарта или выхода.
  1. Для текста используем pygame.font. Например: font = pygame.font.Font(None, 36), а затем рендер: text_surface = font.render(«Game Over. Press R to restart», True, text_color). Это базовый пример того, как font и render интегрируются в игровой экран.
  2. Шаг 6. Счёт, скорость и сложность
  3. Самый частый запрос в поиске: «как сделать счёт в змейке на python pygame». Счёт удобно хранить как целое число score. Каждый раз, когда змейка съела еду, делаем score += 1. Для вывода счёта на экран:
  • инициализируем шрифт: score_font = pygame.font.Font(None, 24);
  • в каждом кадре рендерим текст: score_surface = score_font.render(f»Score: {score}», True, text_color);
  • затем рисуем его: window.blit(score_surface, (10, 10)) — фиксированная позиция слева (left) сверху.
  1. Скорость игры можно постепенно увеличивать: например, каждые 5 очков добавлять 1 к текущему FPS. Пусть у нас есть переменная speed = start_speed; при изменении счёта — если score % 5 == 0, увеличиваем speed. В вызове clock.tick(speed) эта скорость начнёт сказываться на темпе движения. Главное — не переборщить. На практике комфортные значения для pygame snake: 8–10 кадров в секунду на старте и максимум 20–25 на пике сложности.
  2. Шаг 7. Минимальный «полиш»: шрифты, цвета, небольшие эффекты
  3. Даже простая змейка выглядит лучше, если уделить внимание мелочам, но без фанатизма.
  • Шрифт: вместо дефолтного можно подключить собственный файл font, чтобы игра соответствовала бренду или стилю проекта. Вызов: pygame.font.Font(«my_font.ttf», 24).
  • Цветовая схема: подобрать 2–3 основных цвета, которые согласуются между собой и не режут глаза. Например, тёмно-синий фон, зелёная змейка, красная еда.
  • Рамка поля: нарисовать прямоугольник по периметру экрана; это помогает визуально «закрепить» границы. В случае коммерческой мини-игры внутренняя рамка может совпадать с цветами сайта или мобильного приложения.
  • Лёгкая анимация «Game Over»: перед показом надписи сделать короткую паузу time.sleep(0.3) и вспоминать, что всё ещё находитесь в основном цикле — паузы лучше реализовывать аккуратно, чтобы не заморозить event-обработку.
  1. Главный принцип: сначала доводим игру до состояния, когда любая партия от начала до конца проходит без ошибок, и только потом постепенно украшаем. Если вы видите, что игра запускается, змейка двигается, ест еду, растёт, правильно умирает от столкновений, а счёт увеличивается, — значит, основа собрана верно, можно переходить к экспериментам.

Типичные ошибки при создании змейки на Python и как их быстро находить

При разработке даже такой простой игры всплывают типичные баги. Ниже — самые частые запросы и способы диагностики.

Логические ошибки:

  • Змейка «проходит» сквозь стены. Чаще всего причина — проверка границ после вставки головы и удаления хвоста, либо неверное сравнение (использовали размеры окна в пикселях вместо размеров поля в клетках). Проверьте, что сравниваете new_head_x с cols, а не с window_width.
  • Еда появляется внутри тела змейки. Это почти всегда генерация позиции через random.randrange без проверки занятости. Используйте сет занятых координат и свободный список клеток; если всё же хотите быстрый способ, делайте цикл while: генерируете позицию и повторяете, пока клетка не свободна, но следите, чтобы не попасть в бесконечный цикл на почти заполненном поле.
  • Игра не заканчивается при столкновении. Часто условие есть, но вы только печатаете сообщение в консоль и не меняете game_over. Убедитесь, что после game_over вы реально выходите из игрового while, либо переходите в отдельный цикл экрана окончания.

Проблемы с управлением:

  • Задержки реакции на клавиши. Распространённая ошибка — использовать pygame.key.get_pressed() и обрабатывать управление вне основного цикла событий, при этом забывая про clock.tick. В результате изменение направления происходит чаще или реже, чем кадры отрисовки. Стабильнее обрабатывать KEYDOWN внутри pygame.event.get() и держать постоянный FPS.
  • Смена направления «внутрь себя». Игрок нажимает left сразу после right, и голова попадает в следующую клетку хвоста. Предотвратить это просто: перед сменой направления проверяйте, что новое направление не является противоположным текущему. Например, if new_dx == -dx and new_dy == -dy: игнорируем нажатие.

Производительность и стабильность:

  • Игра то ускоряется, то замедляется. Как правило, это результат отсутствия clock.tick или его вызова в нескольких местах. Весь цикл обновления должен завершаться одним вызовом clock.tick(speed). Не используйте time.sleep внутри игрового цикла для «замедления» — это ломает равномерность обработки событий.
  • Пропуски кадров при доработках. Если вы начали рисовать сложные элементы, добавили несколько тяжёлых вычислений, они могут занимать больше времени, чем отведено одним кадром при высоком FPS. Решение: оптимизировать расчёты (например, один раз посчитать set координат, а не пересоздавать его в глубоком цикле) или снизить FPS до комфортного значения.

Приёмы самопроверки и отладки:

  • Печать ключевых значений в консоль: длина змейки, текущие координаты головы, позиция еды, значение скорости. Когда поведение кажется странным, вывод в консоль сразу показывает, на каком шаге значения «ломаются».
  • Временные подсказки на экране. Можно вывести значения координат головы прямо на поле с помощью font.render. Это помогает, когда консоль недоступна или вы тестируете игру в полноэкранном режиме.
  • Разбиение кода на маленькие функции. Проверяйте отдельно генерацию еды, отдельно — проверку столкновений. Чем меньше каждая функция, тем легче написать небольшой тест или вывести промежуточные значения.

Как развивать проект: от учебной змейки до полезного продукта

Когда базовая змейка готова и стабильна, начинается самое интересное — развитие проекта. Здесь появляются задачи, которые ближе к реальной коммерческой разработке игр, веб-сервисов и CRM.

Полезные доработки для роста как разработчика:

  • Главное меню. Перед началом игры показываете экран с логотипом, названием и кнопками: «Начать игру», «Выбор режима», «Выход». Реализуется как отдельный цикл, который по событию (event KEYDOWN или клик мыши) запускает игру.
  • Экран паузы. По нажатию, например, клавиши P ставите игру на паузу: движение останавливается, но отрисовка и обработка событий идут. Это уже похоже на поведение серьёзных игр.
  • Таблица рекордов. Сохранение максимального счёта в файл или базу. Даже простой highscore.txt, куда вы пишете лучший результат, даёт игроку цель. В коммерческих продуктах этот же принцип развивается в полноценную систему прогрессии и ачивок.
  • Уровни сложности и режимы. Например: режим без стен (телепорт через границу), режим с препятствиями на поле, режим с бонусами, которые дают временное ускорение или «слом» управления. Всё это тренирует архитектурное мышление: вы учитесь добавлять новые варианты поведения без переписывания всего кода.

Если «Змейка» — часть реального продукта, появляются другие приоритеты:

  • Брендирование. Цвета, шрифты, логотип, фон — всё должно совпадать с фирменным стилем. pygame позволяет легко подключить собственный font, логотип, задний фон в виде картинки. Это превращает учебную игру в узнаваемый промо-инструмент.
  • Интеграция с веб-сервисом или CRM. Результаты игры можно отправлять на сервер через API: записывать очки в профиль пользователя, выдавать бонусы в интернет-магазине, отмечать активность в обучающей системе. Логика «snake» здесь выступает как мини-модуль в общей экосистеме.
  • Сценарии использования. Промо-игра на лендинге, внутренняя геймификация для сотрудников (набрал N очков — получил бейдж), обучающая игра, помогающая изучать клавиши управления или реакции. Код и подходы, описанные в этой статье, легко встраиваются в такие сценарии.

Дальнейший перенос игры:

  • Мобильные платформы. Логику игры (координаты, столкновения, рост) можно перенести на другой язык программирования: Java/Kotlin для Android, Swift для iOS, JavaScript для мобильного webview. Сам цикл «ввод → обновление → отрисовка» остаётся тем же.
  • Веб-реализация. Используя тот же алгоритм, можно переписать snake на JavaScript и canvas или WebGL. При наличии готовой серверной части (например, Python backend, CRM, интернет-магазин) игра становится частью общего пользовательского пути.
  • Переход к сложным проектам. Освоенный здесь набор инструментов — библиотека для работы с окнами, обработка event, управление time и FPS, продуманная структура кода — напрямую переносится на более серьёзные системы: от интерактивных дашбордов до симуляторов и обучающих приложений.

Если вы сейчас уверенно управляете движением змейки и понимаете, где в коде реализованы столкновения, генерация еды и логика game over, вы уже мыслите как разработчик интерактивных систем, а не только как автор маленького скрипта.

Когда стоит поручить разработку игры команде и как мы можем помочь

Есть задачи, для которых самостоятельное создание змейки на Python — идеальный выбор:

  • личное обучение и прокачка навыков программирования;
  • быстрый прототип игровой механики для внутреннего обсуждения;
  • хобби-проект, который можно показать друзьям или добавить в портфолио.

Но как только речь заходит о продукте, который должны использовать реальные пользователи, масштаб требований меняется. Выгоднее привлечь команду, если:

  • нужен стабильный продукт под нагрузкой: много одновременных игроков, интеграция с базой данных, аналитика;
  • игра должна быть частью существующего сайта, CRM, мобильного приложения или интернет-магазина и обмениваться данными (баллы, бонусы, прогресс);
  • важны продуманный дизайн, анимация, система уровней, монетизация, сбор статистики, безопасная работа с аккаунтами.

Наша команда как раз работает на стыке игр, веб-сервисов и прикладных систем. Мы:

  • берём учебную идею snake-игры и превращаем её в промо-игру с фирменным стилем, адаптацией под мобильные устройства и удобной панелью администратора;
  • интегрируем игровые механики в сайты, CRM, корпоративные порталы и интернет-магазины: от авторизации и подсчёта очков до выдачи купонов и бонусов;
  • подбираем стек под задачу: Python и pygame для прототипа, web-технологии и мобильные фреймворки — для боевого запуска.

Если вы уже собрали свою змейку по этому руководству и чувствуете, что хотите шагнуть дальше — добавить режимы, перенести игру в web или связать её с вашим сервисом, — просто опишите нам идею. Мы предложим варианты реализации, оценим сроки и поможем превратить учебный проект в продукт, который приносит пользу пользователям и бизнесу.