Код игры Тетрис на Python для исследования
Код игры "Тетрис" на Python, который мне любезно сгенерировал ChatGPT для изучения логики и смыслов.
Чтобы создать что-то новое, необходимо суметь повторить что-то старое. Это я сам придумал только что 😆
А теперь детали:
Давай подробно разберем каждую часть кода для игры в Тетрис на Python с использованием библиотеки Tkinter. Я буду объяснять, что делает каждая строчка, чтобы вы могли лучше понять, как работает эта игра.
• Импортируем библиотеку tkinter, которая используется для создания графического интерфейса, и библиотеку random, которая поможет нам случайным образом выбирать фигуры.
• Определяем размеры игрового поля: ширина (GRID_WIDTH) и высота (GRID_HEIGHT) в клетках, а также размер каждой клетки (BLOCK_SIZE) в пикселях.
• Создаем список цветов, которые будут использоваться для различных фигур в игре.
• Определяем фигуры Тетриса в виде списков. Каждая фигура представлена в виде двумерного массива (списка списков), где 1 обозначает часть фигуры, а 0 — пустое пространство. Комментарии указывают на тип фигуры.
• Определяем класс Tetris, который будет содержать всю логику игры и графический интерфейс.
• Конструктор класса Tetris. Создаем главное окно приложения с помощью tk.Tk() и устанавливаем заголовок окна на "Тетрис".
• Создаем холст (Canvas), на котором будет рисоваться игровое поле. Устанавливаем его ширину и высоту, умножая количество клеток на размер каждой клетки. Затем добавляем холст в главное окно с помощью метода pack().
• Создаем метку (Label) для отображения текущего счета игрока и добавляем ее в главное окно.
• Инициализируем игровое поле (board) в виде двумерного списка (списка списков), заполненного нулями. Это будет представлять собой пустое поле.
• Инициализируем переменные для текущей фигуры (current_piece), ее цвета (current_color), координат фигуры на поле (current_x, current_y) и начального счета (score).
• Вызываем метод spawn_piece(), чтобы создать новую фигуру в начале игры.
• Запускаем метод update(), который будет обновлять состояние игры.
• Привязываем клавиши управления к соответствующим методам. Теперь при нажатии стрелок на клавиатуре будут вызываться методы для перемещения и вращения фигур.
• Запускаем главный цикл приложения Tkinter. Это позволяет окну оставаться открытым и обрабатывать события.
Метод spawn_piece
• Этот метод создает новую фигуру. Мы случайным образом выбираем фигуру из списка SHAPES и цвет из списка COLORS. Устанавливаем начальные координаты фигуры так, чтобы она появлялась в верхней части экрана по центру.
• Проверяем, можно ли разместить новую фигуру на игровом поле. Если нет — выводим сообщение об окончании игры и закрываем приложение.
Метод valid_move
• Этот метод проверяет, можно ли переместить текущую фигуру на заданные координаты. Мы проходим по всем частям фигуры и проверяем:
• Не выходит ли фигура за границы игрового поля.
• Не пересекается ли она с уже занятыми клетками на поле.
• Если хотя бы одно условие не выполняется — возвращаем False, иначе — True.
Метод merge
• Этот метод объединяет текущую фигуру с игровым полем. Он добавляет цвет текущей фигуры в соответствующие позиции на поле.
Метод clear_lines
• Этот метод проверяет каждую строку игрового поля. Если вся строка заполнена (все элементы не равны нулю), мы добавляем ее индекс в список строк для очистки.
• После того как мы нашли строки для очистки, удаляем их из поля и добавляем новые пустые строки сверху. Увеличиваем счет на 100 очков и обновляем текст метки счета.
Метод draw_board
• Этот метод очищает холст перед тем, как нарисовать текущее состояние игрового поля.
• Здесь мы проходим по всем клеткам игрового поля и рисуем прямоугольники для заполненных клеток с соответствующими цветами.
• Затем рисуем текущую фигуру на холсте с ее цветом и координатами.
Метод drop
• Этот метод отвечает за падение текущей фигуры вниз на одну клетку.
• Если фигура не может упасть дальше (например, достигла дна или столкнулась с другой фигурой), мы откатываем ее обратно на одну клетку вниз, объединяем с полем и очищаем линии. Затем создаем новую фигуру.
• Обновляем отображение игрового поля после падения фигуры.
Метод update
• Этот метод отвечает за обновление состояния игры. Он вызывает метод drop() для падения текущей фигуры и затем снова вызывает себя через одну секунду (1000 миллисекунд) с помощью метода after(). Это создает эффект постоянного падения фигур.
▎Методы управления фигурой
Каждый из этих методов отвечает за управление текущей фигурой:
Метод move_left
• Этот метод перемещает текущую фигуру влево. Если перемещение невозможно (например, фигура выходит за границы или сталкивается с другой фигурой), мы откатываем ее обратно вправо. Затем обновляем отображение поля.
Метод move_right
• Аналогично методу move_left, этот метод перемещает текущую фигуру вправо.
Метод move_down
• Этот метод вызывает метод drop(), чтобы быстро опустить фигуру вниз при нажатии клавиши вниз.
Метод rotate
• Этот метод вращает текущую фигуру. Мы создаем новую версию фигуры путем транспонирования и реверсирования текущей. Если новая позиция недопустима, мы возвращаем фигуру в оригинальное состояние. Затем обновляем отображение поля.
Эта игра является базовой реализацией Тетриса и может быть расширена различными функциями и улучшениями. Вы можете добавить уровни сложности, различные режимы игры или даже звук. Надеюсь, это объяснение помогло вам понять каждую часть кода! Если у вас есть дополнительные вопросы или вы хотите узнать больше о конкретных аспектах кода или его улучшениях, дайте знать!
Первая задача, переписать с нуля, для закрепления.
Чтобы создать что-то новое, необходимо суметь повторить что-то старое. Это я сам придумал только что 😆
Код игры на Python
import tkinter as tk
import random
# Определяем размеры игрового поля и блоков
GRID_WIDTH = 10
GRID_HEIGHT = 20
BLOCK_SIZE = 30
# Определяем цвета для фигур
COLORS = ["cyan", "blue", "orange", "yellow", "green", "purple", "red"]
# Определяем фигуры
SHAPES = [
[[1, 1, 1, 1]], # I
[[1, 1], [1, 1]], # O
[[0, 1, 0], [1, 1, 1]], # T
[[1, 0, 0], [1, 1, 1]], # L
[[0, 0, 1], [1, 1, 1]], # J
[[0, 1, 1], [1, 1, 0]], # S
[[1, 1, 0], [0, 1, 1]], # Z
]
class Tetris:
def __init__(self):
self.root = tk.Tk()
self.root.title("Тетрис")
self.canvas = tk.Canvas(self.root, width=GRID_WIDTH * BLOCK_SIZE,
height=GRID_HEIGHT * BLOCK_SIZE)
self.canvas.pack()
self.score_label = tk.Label(self.root, text="Очки: 0")
self.score_label.pack()
self.board = [[0] * GRID_WIDTH for _ in range(GRID_HEIGHT)]
self.current_piece = None
self.current_color = None
self.current_x = GRID_WIDTH // 2 - 1
self.current_y = 0
self.score = 0
self.spawn_piece()
self.update()
self.root.bind("<Left>", self.move_left)
self.root.bind("<Right>", self.move_right)
self.root.bind("<Down>", self.move_down)
self.root.bind("<Up>", self.rotate)
self.root.mainloop()
def spawn_piece(self):
shape = random.choice(SHAPES)
self.current_piece = shape
self.current_color = random.choice(COLORS)
self.current_x = GRID_WIDTH // 2 - len(shape[0]) // 2
self.current_y = 0
if not self.valid_move():
print("Игра окончена!")
self.root.quit()
def valid_move(self):
for y in range(len(self.current_piece)):
for x in range(len(self.current_piece[y])):
if (self.current_piece[y][x] and
(self.current_x + x < 0 or
self.current_x + x >= GRID_WIDTH or
self.current_y + y >= GRID_HEIGHT or
self.board[self.current_y + y][self.current_x + x])):
return False
return True
def merge(self):
for y in range(len(self.current_piece)):
for x in range(len(self.current_piece[y])):
if self.current_piece[y][x]:
self.board[self.current_y + y][self.current_x + x] = self.current_color
def clear_lines(self):
lines_to_clear = []
for y in range(GRID_HEIGHT):
if all(self.board[y]):
lines_to_clear.append(y)
for y in lines_to_clear:
del self.board[y]
self.board.insert(0, [0] * GRID_WIDTH)
self.score += 100
self.score_label.config(text=f"Очки: {self.score}")
def draw_board(self):
self.canvas.delete(tk.ALL)
for y in range(GRID_HEIGHT):
for x in range(GRID_WIDTH):
if self.board[y][x]:
color = self.board[y][x]
self.canvas.create_rectangle(x * BLOCK_SIZE,
y * BLOCK_SIZE,
(x + 1) * BLOCK_SIZE,
(y + 1) * BLOCK_SIZE,
fill=color, outline="black")
# Рисуем текущую фигуру
for y in range(len(self.current_piece)):
for x in range(len(self.current_piece[y])):
if self.current_piece[y][x]:
color = self.current_color
self.canvas.create_rectangle((self.current_x + x) * BLOCK_SIZE,
(self.current_y + y) * BLOCK_SIZE,
(self.current_x + x + 1) * BLOCK_SIZE,
(self.current_y + y + 1) * BLOCK_SIZE,
fill=color, outline="black")
def drop(self):
self.current_y += 1
if not self.valid_move():
self.current_y -= 1
self.merge()
self.clear_lines()
self.spawn_piece()
self.draw_board()
def update(self):
self.drop()
self.root.after(1000, self.update)
def move_left(self, event):
self.current_x -= 1
if not self.valid_move():
self.current_x += 1
self.draw_board()
def move_right(self, event):
self.current_x += 1
if not self.valid_move():
self.current_x -= 1
self.draw_board()
def move_down(self, event):
self.drop()
def rotate(self, event):
rotated_shape = list(zip(*self.current_piece[::-1]))
original_piece = self.current_piece
self.current_piece = rotated_shape
if not self.valid_move():
self.current_piece = original_piece
self.draw_board()
if __name__ == "__main__":
Tetris()
А теперь детали:
Давай подробно разберем каждую часть кода для игры в Тетрис на Python с использованием библиотеки Tkinter. Я буду объяснять, что делает каждая строчка, чтобы вы могли лучше понять, как работает эта игра.
import tkinter as tk
import random
• Импортируем библиотеку tkinter, которая используется для создания графического интерфейса, и библиотеку random, которая поможет нам случайным образом выбирать фигуры.
GRID_WIDTH = 10
GRID_HEIGHT = 20
BLOCK_SIZE = 30
• Определяем размеры игрового поля: ширина (GRID_WIDTH) и высота (GRID_HEIGHT) в клетках, а также размер каждой клетки (BLOCK_SIZE) в пикселях.
COLORS = ["cyan", "blue", "orange", "yellow", "green", "purple", "red"]
• Создаем список цветов, которые будут использоваться для различных фигур в игре.
SHAPES = [
[[1, 1, 1, 1]], # I
[[1, 1], [1, 1]], # O
[[0, 1, 0], [1, 1, 1]], # T
[[1, 0, 0], [1, 1, 1]], # L
[[0, 0, 1], [1, 1, 1]], # J
[[0, 1, 1], [1, 1, 0]], # S
[[1, 1, 0], [0, 1, 1]], # Z
]
• Определяем фигуры Тетриса в виде списков. Каждая фигура представлена в виде двумерного массива (списка списков), где 1 обозначает часть фигуры, а 0 — пустое пространство. Комментарии указывают на тип фигуры.
class Tetris:
• Определяем класс Tetris, который будет содержать всю логику игры и графический интерфейс.
def __init__(self):
self.root = tk.Tk()
self.root.title("Тетрис")
• Конструктор класса Tetris. Создаем главное окно приложения с помощью tk.Tk() и устанавливаем заголовок окна на "Тетрис".
self.canvas = tk.Canvas(self.root, width=GRID_WIDTH * BLOCK_SIZE,
height=GRID_HEIGHT * BLOCK_SIZE)
self.canvas.pack()
• Создаем холст (Canvas), на котором будет рисоваться игровое поле. Устанавливаем его ширину и высоту, умножая количество клеток на размер каждой клетки. Затем добавляем холст в главное окно с помощью метода pack().
self.score_label = tk.Label(self.root, text="Очки: 0")
self.score_label.pack()
• Создаем метку (Label) для отображения текущего счета игрока и добавляем ее в главное окно.
self.board = [[0] * GRID_WIDTH for _ in range(GRID_HEIGHT)]
• Инициализируем игровое поле (board) в виде двумерного списка (списка списков), заполненного нулями. Это будет представлять собой пустое поле.
self.current_piece = None
self.current_color = None
self.current_x = GRID_WIDTH // 2 - 1
self.current_y = 0
self.score = 0
• Инициализируем переменные для текущей фигуры (current_piece), ее цвета (current_color), координат фигуры на поле (current_x, current_y) и начального счета (score).
self.spawn_piece()
• Вызываем метод spawn_piece(), чтобы создать новую фигуру в начале игры.
self.update()
• Запускаем метод update(), который будет обновлять состояние игры.
self.root.bind("<Left>", self.move_left)
self.root.bind("<Right>", self.move_right)
self.root.bind("<Down>", self.move_down)
self.root.bind("<Up>", self.rotate)
• Привязываем клавиши управления к соответствующим методам. Теперь при нажатии стрелок на клавиатуре будут вызываться методы для перемещения и вращения фигур.
self.root.mainloop()
• Запускаем главный цикл приложения Tkinter. Это позволяет окну оставаться открытым и обрабатывать события.
Методы класса Tetris
Метод spawn_piece
def spawn_piece(self):
shape = random.choice(SHAPES)
self.current_piece = shape
self.current_color = random.choice(COLORS)
self.current_x = GRID_WIDTH // 2 - len(shape[0]) // 2
self.current_y = 0
• Этот метод создает новую фигуру. Мы случайным образом выбираем фигуру из списка SHAPES и цвет из списка COLORS. Устанавливаем начальные координаты фигуры так, чтобы она появлялась в верхней части экрана по центру.
if not self.valid_move():
print("Игра окончена!")
self.root.quit()
• Проверяем, можно ли разместить новую фигуру на игровом поле. Если нет — выводим сообщение об окончании игры и закрываем приложение.
Метод valid_move
def valid_move(self):
for y in range(len(self.current_piece)):
for x in range(len(self.current_piece[y])):
if (self.current_piece[y][x] and
(self.current_x + x < 0 or
self.current_x + x >= GRID_WIDTH or
self.current_y + y >= GRID_HEIGHT or
self.board[self.current_y + y][self.current_x + x])):
return False
return True
• Этот метод проверяет, можно ли переместить текущую фигуру на заданные координаты. Мы проходим по всем частям фигуры и проверяем:
• Не выходит ли фигура за границы игрового поля.
• Не пересекается ли она с уже занятыми клетками на поле.
• Если хотя бы одно условие не выполняется — возвращаем False, иначе — True.
Метод merge
def merge(self):
for y in range(len(self.current_piece)):
for x in range(len(self.current_piece[y])):
if self.current_piece[y][x]:
self.board[self.current_y + y][self.current_x + x] = self.current_color
• Этот метод объединяет текущую фигуру с игровым полем. Он добавляет цвет текущей фигуры в соответствующие позиции на поле.
Метод clear_lines
def clear_lines(self):
lines_to_clear = []
for y in range(GRID_HEIGHT):
if all(self.board[y]):
lines_to_clear.append(y)
• Этот метод проверяет каждую строку игрового поля. Если вся строка заполнена (все элементы не равны нулю), мы добавляем ее индекс в список строк для очистки.
for y in lines_to_clear:
del self.board[y]
self.board.insert(0, [0] * GRID_WIDTH)
self.score += 100
self.score_label.config(text=f"Очки: {self.score}")
• После того как мы нашли строки для очистки, удаляем их из поля и добавляем новые пустые строки сверху. Увеличиваем счет на 100 очков и обновляем текст метки счета.
Метод draw_board
def draw_board(self):
self.canvas.delete(tk.ALL)
• Этот метод очищает холст перед тем, как нарисовать текущее состояние игрового поля.
for y in range(GRID_HEIGHT):
for x in range(GRID_WIDTH):
if self.board[y][x]:
color = self.board[y][x]
self.canvas.create_rectangle(x * BLOCK_SIZE,
y * BLOCK_SIZE,
(x + 1) * BLOCK_SIZE,
(y + 1) * BLOCK_SIZE,
fill=color, outline="black")
• Здесь мы проходим по всем клеткам игрового поля и рисуем прямоугольники для заполненных клеток с соответствующими цветами.
# Рисуем текущую фигуру
for y in range(len(self.current_piece)):
for x in range(len(self.current_piece[y])):
if self.current_piece[y][x]:
color = self.current_color
self.canvas.create_rectangle((self.current_x + x) * BLOCK_SIZE,
(self.current_y + y) * BLOCK_SIZE,
(self.current_x + x + 1) * BLOCK_SIZE,
(self.current_y + y + 1) * BLOCK_SIZE,
fill=color, outline="black")
• Затем рисуем текущую фигуру на холсте с ее цветом и координатами.
Метод drop
def drop(self):
self.current_y += 1
• Этот метод отвечает за падение текущей фигуры вниз на одну клетку.
if not self.valid_move():
self.current_y -= 1
self.merge()
self.clear_lines()
self.spawn_piece()
• Если фигура не может упасть дальше (например, достигла дна или столкнулась с другой фигурой), мы откатываем ее обратно на одну клетку вниз, объединяем с полем и очищаем линии. Затем создаем новую фигуру.
self.draw_board()
• Обновляем отображение игрового поля после падения фигуры.
Метод update
def update(self):
self.drop()
self.root.after(1000, self.update)
• Этот метод отвечает за обновление состояния игры. Он вызывает метод drop() для падения текущей фигуры и затем снова вызывает себя через одну секунду (1000 миллисекунд) с помощью метода after(). Это создает эффект постоянного падения фигур.
▎Методы управления фигурой
Каждый из этих методов отвечает за управление текущей фигурой:
Метод move_left
def move_left(self, event):
self.current_x -= 1
if not self.valid_move():
self.current_x += 1
self.draw_board()
• Этот метод перемещает текущую фигуру влево. Если перемещение невозможно (например, фигура выходит за границы или сталкивается с другой фигурой), мы откатываем ее обратно вправо. Затем обновляем отображение поля.
Метод move_right
def move_right(self, event):
self.current_x += 1
if not self.valid_move():
self.current_x -= 1
self.draw_board()
• Аналогично методу move_left, этот метод перемещает текущую фигуру вправо.
Метод move_down
def move_down(self, event):
self.drop()
• Этот метод вызывает метод drop(), чтобы быстро опустить фигуру вниз при нажатии клавиши вниз.
Метод rotate
def rotate(self, event):
rotated_shape = list(zip(*self.current_piece[::-1]))
original_piece = self.current_piece
self.current_piece = rotated_shape
if not self.valid_move():
self.current_piece = original_piece
self.draw_board()
• Этот метод вращает текущую фигуру. Мы создаем новую версию фигуры путем транспонирования и реверсирования текущей. Если новая позиция недопустима, мы возвращаем фигуру в оригинальное состояние. Затем обновляем отображение поля.
Заключение
Эта игра является базовой реализацией Тетриса и может быть расширена различными функциями и улучшениями. Вы можете добавить уровни сложности, различные режимы игры или даже звук. Надеюсь, это объяснение помогло вам понять каждую часть кода! Если у вас есть дополнительные вопросы или вы хотите узнать больше о конкретных аспектах кода или его улучшениях, дайте знать!
Первая задача, переписать с нуля, для закрепления.