Привет, Дзен! Помните игру 2048? Та самая, где вы двигаете плитки с числами, надеясь собрать заветное число, а вместо этого случайно нажимаете не туда и всё ломаете? Я в неё залипал в метро, в очереди за кофе и даже на скучных лекциях (прости, профессор).
И вот однажды я подумал: «А почему бы не написать свою версию? На Python. Да ещё и с графикой через turtle — тот самый модуль, где черепашка рисует линии». Спойлер: получилось красиво, немного страшно, но играбельно. И сейчас я расскажу как.
🐢 Turtle? Серьёзно? А не pygame?
Я знаю, о чём вы думаете. Turtle — это для детей, которые рисуют квадратики и домики. Но вы не поверили: на нём можно сделать полноценный игровой интерфейс. Конечно, с костылями, зато без установки дополнительных библиотек (turtle идёт в комплекте с Python).
Почему не pygame? Потому что я мазохист и люблю сложные пути. А если серьёзно — turtle отлично подходит для быстрого прототипирования. К тому же, выглядит ретро-мило.
🕹️ Как работает 2048: напоминание для тех, кто жил под камнем
Поле 4×4. Каждый ход вы нажимаете стрелку (вверх/вниз/влево/вправо), все плитки сдвигаются в эту сторону. Если две одинаковые плитки встречаются — они сливаются в одну с удвоенным числом. После каждого хода на пустой клетке появляется новая плитка (2 или 4). Цель — набрать 2048, но можно играть дальше.
Звучит просто. На практике — нужно держать в голове логику сдвига, слияния и случайной генерации. И это до того, как вы начнёте рисовать клетки черепашкой.
🧱 Архитектура одного безумия
Я разбил код на несколько логических блоков:
- Модель (логика игры) — матрица 4×4, функции сдвига и слияния.
- Отрисовка — рисуем сетку, выводим числа в клетках (жирным шрифтом, чтобы выглядело дорого).
- Управление — слушаем клавиши-стрелки, пересчитываем состояние, перерисовываем экран.
- Состояние игры — проверка на победу (есть 2048) и на поражение (нет ходов).
Весь код я уместил в один файл — около 200 строк, включая пробелы и комментарии для самого себя (которые потом всё равно не читал).
💻 Код, который заставит вашу черепашку попотеть
Покажу основные моменты. Полный код выложил в комментариях (и в Telegram-канале ссылочка будет).
Шаг 1: Создаём поле и рисуем его
import turtle
import random
# Настройки окна
screen = turtle.Screen()
screen.title("2048 на черепашке")
screen.bgcolor("white")
screen.setup(500, 550)
screen.tracer(0) # Отключаем анимацию для скорости
# Класс одной клетки
class Cell:
def __init__(self, x, y, size=100):
self.x = x
self.y = y
self.size = size
self.value = 0
self.t = turtle.Turtle()
self.t.speed(0)
self.t.penup()
self.t.hideturtle()
def draw(self):
# Рисуем квадрат
self.t.goto(self.x, self.y)
self.t.pendown()
self.t.begin_fill()
for _ in range(4):
self.t.forward(self.size)
self.t.right(90)
self.t.end_fill()
self.t.penup()
# Пишем число, если оно не 0
if self.value != 0:
self.t.goto(self.x + self.size/2, self.y + self.size/2 - 10)
self.t.write(self.value, align="center", font=("Arial", 24, "bold"))
Видите? Ничего сложного. Черепашка рисует квадрат, заливает цветом (в зависимости от числа — от светло-бежевого до тёмно-оранжевого), и вписывает цифру.
Шаг 2: Логика движения — тут я поломал голову
Самый хитрый момент — сдвинуть ряд чисел, объединить одинаковые и не потерять порядок. Я написал универсальную функцию для линии (списка из 4 значений):
def merge_line(line):
# Убираем нули
filtered = [x for x in line if x != 0]
# Сливаем одинаковые соседние
for i in range(len(filtered)-1):
if filtered[i] == filtered[i+1]:
filtered[i] *= 2
filtered[i+1] = 0
# Снова убираем нули и дополняем до 4 элементов
filtered = [x for x in filtered if x != 0]
filtered += [0] * (4 - len(filtered))
return filtered
Потом для каждой строки или столбца применяем эту функцию — и готово. Поворачивая матрицу, можно обрабатывать все направления одной и той же функцией (я так и сделал, сэкономил 50 строк и немного нервов).
Шаг 3: Слушаем клавиши
def left():
move_and_merge_left()
add_new_tile()
draw_board()
check_game_over()
screen.listen()
screen.onkey(left, "Left")
screen.onkey(right, "Right")
screen.onkey(up, "Up")
screen.onkey(down, "Down")
screen.onkey(restart, "r")
Биндим стрелки — и вуаля. В отличие от веб-версии, здесь не нужно каждый раз обновлять страницу. Черепашка просто перерисовывает сетку.
🎲 Результат: что получилось
После пары часов отладки (и одного момента, когда все плитки превратились в «0» и игра умерла), я получил рабочий клон 2048 на чистом Python + turtle.
Что круто:
- Игра запускается из консоли одной командой, без интернета
- Работает на любом компьютере с Python (даже на Raspberry Pi)
- Можно менять цвета, размер поля, скорость — полёт фантазии
Что не очень:
- Черепашка тормозит при быстрых нажатиях (пришлось добавить screen.tracer(0) и ручной update())
- Отсутствует счётчик очков (но я добавил в финальной версии — текстовую метку сверху)
- Нет анимации плавного движения — плитки просто появляются на новом месте
Но для первой версии — отлично. Моя дочь (7 лет) даже смогла собрать 512, пока я варил кофе.
🛠️ Что можно улучшить? (ДЗ для вас)
Если захотите допилить игру самостоятельно:
- Добавить отображение текущего счёта и рекорда
- Сделать кнопку «Новая игра» мышкой
- Запоминать лучшее достижение в файл
- Переписать на pygame для производительности (но это уже не смешно)