как запрограммировать тетрис на питоне?

Создано: 21 мая 2025 г.

Отвечено с использованием O3 от Chat01

Вопрос

как запрограммировать тетрис на питоне?

Мысль

Providing Tetris code in Python

The user wants a guide on programming Tetris in Python and requested a response in Russian. I'll walk through a simple explanation, using the Pygame library, and share some relevant code snippets. Key concepts include piece representation, grid setup, collision detection, rotation, and scoring. I'll keep the code brief and clear. We avoid using features like the canvas since they’re disabled

Thought for 8 seconds

Ответ

Ниже — пошаговый план и минимальный, но рабочий пример Tetris на Python с использованием pygame. Код компактный (≈200 строк), чтобы было легче разбираться и расширять.


1. Установка

bash
pip install pygame

2. Как устроен Tetris (кратко)

  1. Игровое поле — матрица (10 × 20), где 0 — пустая клетка, а числа 1-7 обозначают цвет/тип фигуры.
  2. Фигуры (тетромино) храним как список матриц 4 × 4 — для каждого угла поворота.
  3. Падение: каждую «тик»-итерацию активная фигура пробует сдвинуться вниз. Если столкновение — фиксация в поле, проверка заполненных линий, создание новой фигуры.
  4. Управление: клавиши ← → ↓, пробел (моментальное падение), ↑ (поворот).
  5. Счёт: +100 очков за линию; несколько линий за раз — бонус.

3. Минимальный код

python
import pygame, random, sys # ----- настройка игры ----- W, H = 10, 20 # размер сетки SIZE = 30 # пикселей на клетку FPS = 60 COLORS = [(0,0,0), (0,240,240), (0,0,240), (240,160,0), (240,240,0), (0,240,0), (160,0,240), (240,0,0)] # тетромино (четыре поворота каждой фигуры) SHAPES = [ [[ [0,1,0,0], [0,1,0,0], [0,1,0,0], [0,1,0,0]], # I [ [0,0,0,0], [1,1,1,1], [0,0,0,0], [0,0,0,0]]], [[ [2,0,0], [2,2,2], [0,0,0]], # J [ [0,2,2], [0,2,0], [0,2,0]], [ [0,0,0], [2,2,2], [0,0,2]], [ [0,2,0], [0,2,0], [2,2,0]]], [[ [0,0,3], [3,3,3], [0,0,0]], # L [ [0,3,0], [0,3,0], [0,3,3]], [ [0,0,0], [3,3,3], [3,0,0]], [ [3,3,0], [0,3,0], [0,3,0]]], [[ [4,4], [4,4]], # O [ [4,4], [4,4]]], [[ [0,5,5], [5,5,0], [0,0,0]], # S [ [0,5,0], [0,5,5], [0,0,5]]], [[ [0,6,0], [6,6,6], [0,0,0]], # T [ [0,6,0], [0,6,6], [0,6,0]], [ [0,0,0], [6,6,6], [0,6,0]], [ [0,6,0], [6,6,0], [0,6,0]]], [[ [7,7,0], [0,7,7], [0,0,0]], # Z [ [0,0,7], [0,7,7], [0,7,0]]] ] def rotate(shape, r): return SHAPES[shape][r % len(SHAPES[shape])] class Piece: def __init__(self): self.type = random.randrange(len(SHAPES)) self.rot = 0 self.x = W // 2 - 2 self.y = 0 @property def blocks(self): return rotate(self.type, self.rot) def collision(board, piece, dx=0, dy=0, drot=0): grid = rotate(piece.type, piece.rot + drot) for y,row in enumerate(grid): for x,val in enumerate(row): if val: nx = piece.x + x + dx ny = piece.y + y + dy if nx < 0 or nx >= W or ny >= H or (ny >= 0 and board[ny][nx]): return True return False def merge(board, piece): for y,row in enumerate(piece.blocks): for x,val in enumerate(row): if val: board[piece.y + y][piece.x + x] = val def clear_lines(board): cleared = [row for row in board if any(v==0 for v in row)] lines = H - len(cleared) while len(cleared) < H: cleared.insert(0,[0]*W) return cleared, lines def draw_board(screen, board, score): screen.fill((20,20,20)) for y,row in enumerate(board): for x,val in enumerate(row): pygame.draw.rect(screen, COLORS[val], (x*SIZE, y*SIZE, SIZE-1, SIZE-1)) font = pygame.font.SysFont(None, 36) txt = font.render(f"Score: {score}", True, (255,255,255)) screen.blit(txt, (W*SIZE + 10, 10)) def main(): pygame.init() screen = pygame.display.set_mode((W*SIZE+140, H*SIZE)) clock = pygame.time.Clock() board = [[0]*W for _ in range(H)] fall_delay, fall_timer = 500, 0 current = Piece() score = 0 while True: dt = clock.tick(FPS) fall_timer += dt for e in pygame.event.get(): if e.type == pygame.QUIT: sys.exit() if e.type == pygame.KEYDOWN: if e.key == pygame.K_LEFT and not collision(board,current,-1): current.x -= 1 elif e.key == pygame.K_RIGHT and not collision(board,current,1): current.x += 1 elif e.key == pygame.K_DOWN and not collision(board,current,0,1): current.y += 1 elif e.key == pygame.K_UP and not collision(board,current,0,0,1): current.rot += 1 elif e.key == pygame.K_SPACE: while not collision(board,current,0,1): current.y += 1 if fall_timer > fall_delay: fall_timer = 0 if not collision(board,current,0,1): current.y += 1 else: merge(board,current) board, lines = clear_lines(board) score += lines * 100 current = Piece() if collision(board,current): print("Game over!"); return draw_board(screen, board, score) # рисуем активную фигуру for y,row in enumerate(current.blocks): for x,val in enumerate(row): if val and current.y+y>=0: pygame.draw.rect(screen, COLORS[val], ((current.x+x)*SIZE, (current.y+y)*SIZE, SIZE-1, SIZE-1)) pygame.display.flip() if __name__ == "__main__": main()

Что можно улучшить

  • Добавить уровень сложности — уменьшать fall_delay со временем.
  • Предпросмотр следующей фигуры и «холда» (запасной фигуры).
  • Звуки (pygame.mixer).
  • Система очков из оригинального Tetris (+400 за T-Spin, +800 за Tetris и т.д.).
  • Окно паузы/меню, таблица рекордов (JSON).

4. Советы по отладке

  1. Выводите в консоль координаты активной фигуры или всю матрицу, чтобы понять, где происходит коллизия.
  2. Сначала протестируйте только перемещение без поворотов.
  3. Добавляйте новые фичи постепенно: «сначала работает - потом красиво».

5. Полезные ресурсы

  • Документация Pygame: https://www.pygame.org/docs/
  • Разбор механики Tetris (англ.): The Tetris Guideline.
  • Книга «Invent Your Own Computer Games with Python» (гл. 20 — Tetromino).

Успехов в разработке! Если будут вопросы по конкретной части кода или хотите добавить новые функции — спрашивайте.

Поделиться этим Q&A