
Тетрис (ну и Змейка) — это «Hello World» в мире геймдева. Казалось бы, испортить его сложно, но автор этого репозитория очень старался. Разбираем проект, который преподносится как «обучающий материал для начинающих». Да, код рабочий, проект законченный, даже видео на YouTube есть. Но на деле там учат вредным привычкам.
1️⃣ Отсутствие точки входа
В
main.py код просто навален в корень файла. Никакого if __name__ == "__main__":. Если вы попробуете импортировать что-то из этого файла (хотя зачем?), у вас сразу инициализируется Pygame и откроется окно. 2️⃣ Беда с пространством имен
В
game.py мы видим прекрасное: from blocks import *. Запомните: каждый раз, когда вы используете
import *, вы забиваете пространство имен мусором. Какие классы прилетели? Откуда? Никто не знает. 3️⃣ Класс-оркестр
Класс
Game — это и швец, и жнец. Он управляет логикой, считает очки, загружает звуки, проигрывает музыку и... отрисовывает блоки. Нарушение SRP (Single Responsibility Principle) на лицо. Логика игры не должна знать о существовании
pygame.mixer или о том, как рисовать прямоугольники. # В недрах Game.__init__
self.rotate_sound = pygame.mixer.Sound("Sounds/rotate.ogg")
pygame.mixer.music.load("Sounds/music.ogg")Хотите поменять звуковую библиотеку? Удачи переписывать всё ядро игры.
4️⃣ ООП головного мозга: Наследование ради... ничего
В
blocks.py мы видим классическую ошибку: создание семи разных классов (LBlock, JBlock и т.д.), которые наследуются от Block только ради того, чтобы в __init__ вписать словарик с координатами.Это классический оверинжиниринг. Все эти классы не имеют уникального поведения, только разные данные.
Как надо: Один класс
Block, который принимает тип фигуры или конфиг при инициализации. Данные отдельно, логика отдельно.5️⃣ Класс Position — зачем?
class Position:
def __init__(self, row, column):
self.row = row
self.column = columnСоздавать целый класс для хранения двух целых чисел — это избыточно. В Python есть
namedtuple, dataclasses или, в конце концов, просто кортежи (row, col). 6️⃣ Магические числа и хардкод
if self.next_block.id == 3:
self.next_block.draw(screen, 255, 290)
elif self.next_block.id == 4:
self.next_block.draw(screen, 255, 280)Это «костыльный» UI в чистом виде. Вместо того чтобы вычислить центр области предпросмотра, автор просто подогнал координаты под конкретные ID блоков. Добавите новый блок — и вся верстка поплывет.
7️⃣ Обработка счета из эпохи мамонтов
В
game.py мы видим это:def update_score(self, lines_cleared, move_down_points):
if lines_cleared == 1:
self.score += 100
elif lines_cleared == 2:
self.score += 300
# ... и так далееКак надо: Обычный словарь или список коэффициентов сделал бы этот код в одну строку.
elif-цепочки для простых соответствий — верный признак того, что автор не умеет в структуры данных.🧑⚖️ Вердикт:
Как учебный проект — пойдет. Если учитесь по таким туториалам, помните: их цель — показать результат за 20 минут видео, а не научить вас писать нормальный код. Не тащите эти паттерны в продакшен.
#жарим_код






