This commit is contained in:
sShemet
2025-12-22 14:03:10 +05:00
commit ade2833df7
74 changed files with 42924 additions and 0 deletions

256
tet/tetris.py Normal file
View File

@@ -0,0 +1,256 @@
import pygame
import random
# Инициализация pygame
pygame.init()
# Цвета
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (70, 70, 70)
COLORS = [
(0, 255, 255), # I - голубой
(0, 0, 255), # J - синий
(255, 165, 0), # L - оранжевый
(255, 255, 0), # O - желтый
(0, 255, 0), # S - зеленый
(128, 0, 128), # T - фиолетовый
(255, 0, 0) # Z - красный
]
# Настройки игры
BLOCK_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20
SCREEN_WIDTH = BLOCK_SIZE * (GRID_WIDTH + 6)
SCREEN_HEIGHT = BLOCK_SIZE * GRID_HEIGHT
GAME_AREA_LEFT = BLOCK_SIZE
# Фигуры тетрамино
SHAPES = [
[[1, 1, 1, 1]], # I
[[1, 0, 0], [1, 1, 1]], # J
[[0, 0, 1], [1, 1, 1]], # L
[[1, 1], [1, 1]], # O
[[0, 1, 1], [1, 1, 0]], # S
[[0, 1, 0], [1, 1, 1]], # T
[[1, 1, 0], [0, 1, 1]] # Z
]
# Создание экрана
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Тетрис")
# Часы для управления FPS
clock = pygame.time.Clock()
class Tetris:
def __init__(self):
self.grid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
self.current_piece = self.new_piece()
self.game_over = False
self.score = 0
self.level = 1
self.fall_speed = 0.5 # секунды между падением на 1 клетку
self.fall_time = 0
def new_piece(self):
# Выбираем случайную фигуру
shape = random.choice(SHAPES)
color = COLORS[SHAPES.index(shape)]
# Начальная позиция (по центру сверху)
x = GRID_WIDTH // 2 - len(shape[0]) // 2
y = 0
return {"shape": shape, "color": color, "x": x, "y": y}
def valid_move(self, piece, x_offset=0, y_offset=0):
for y, row in enumerate(piece["shape"]):
for x, cell in enumerate(row):
if cell:
new_x = piece["x"] + x + x_offset
new_y = piece["y"] + y + y_offset
if (new_x < 0 or new_x >= GRID_WIDTH or
new_y >= GRID_HEIGHT or
(new_y >= 0 and self.grid[new_y][new_x])):
return False
return True
def rotate_piece(self):
# Получаем текущую фигуру
piece = self.current_piece
# Транспонируем матрицу фигуры (поворот на 90 градусов)
rotated = [[piece["shape"][y][x] for y in range(len(piece["shape"])-1, -1, -1)]
for x in range(len(piece["shape"][0]))]
old_shape = piece["shape"]
piece["shape"] = rotated
# Если после поворота фигура выходит за границы или пересекается с другими блоками,
# отменяем поворот
if not self.valid_move(piece):
piece["shape"] = old_shape
def lock_piece(self):
piece = self.current_piece
for y, row in enumerate(piece["shape"]):
for x, cell in enumerate(row):
if cell:
# Проверяем, не выходит ли фигура за верхнюю границу (игра окончена)
if piece["y"] + y < 0:
self.game_over = True
else:
self.grid[piece["y"] + y][piece["x"] + x] = piece["color"]
# Проверяем заполненные линии
self.clear_lines()
# Создаем новую фигуру
self.current_piece = self.new_piece()
# Если новая фигура сразу не может разместиться, игра окончена
if not self.valid_move(self.current_piece):
self.game_over = True
def clear_lines(self):
lines_cleared = 0
for y in range(GRID_HEIGHT):
if all(self.grid[y]):
lines_cleared += 1
# Удаляем линию и сдвигаем все вышележащие линии вниз
for y2 in range(y, 0, -1):
self.grid[y2] = self.grid[y2-1][:]
self.grid[0] = [0 for _ in range(GRID_WIDTH)]
# Обновляем счет
if lines_cleared == 1:
self.score += 100 * self.level
elif lines_cleared == 2:
self.score += 300 * self.level
elif lines_cleared == 3:
self.score += 500 * self.level
elif lines_cleared == 4:
self.score += 800 * self.level
# Обновляем уровень (каждые 10 линий)
self.level = 1 + self.score // 1000
# Увеличиваем скорость (максимум 0.05 секунды между падениями)
self.fall_speed = max(0.05, 0.5 - (self.level - 1) * 0.05)
def update(self, delta_time):
if self.game_over:
return
self.fall_time += delta_time
# Автоматическое падение фигуры
if self.fall_time >= self.fall_speed:
self.fall_time = 0
if self.valid_move(self.current_piece, 0, 1):
self.current_piece["y"] += 1
else:
self.lock_piece()
def draw(self):
# Очищаем экран
screen.fill(BLACK)
# Рисуем игровую область
pygame.draw.rect(screen, WHITE, (GAME_AREA_LEFT, 0, BLOCK_SIZE * GRID_WIDTH, SCREEN_HEIGHT), 1)
# Рисуем сетку
for x in range(GRID_WIDTH):
for y in range(GRID_HEIGHT):
pygame.draw.rect(screen, GRAY,
(GAME_AREA_LEFT + x * BLOCK_SIZE, y * BLOCK_SIZE,
BLOCK_SIZE, BLOCK_SIZE), 1)
# Рисуем статичные блоки
for y in range(GRID_HEIGHT):
for x in range(GRID_WIDTH):
if self.grid[y][x]:
pygame.draw.rect(screen, self.grid[y][x],
(GAME_AREA_LEFT + x * BLOCK_SIZE, y * BLOCK_SIZE,
BLOCK_SIZE, BLOCK_SIZE))
pygame.draw.rect(screen, WHITE,
(GAME_AREA_LEFT + x * BLOCK_SIZE, y * BLOCK_SIZE,
BLOCK_SIZE, BLOCK_SIZE), 1)
# Рисуем текущую фигуру
if not self.game_over:
piece = self.current_piece
for y, row in enumerate(piece["shape"]):
for x, cell in enumerate(row):
if cell:
pygame.draw.rect(screen, piece["color"],
(GAME_AREA_LEFT + (piece["x"] + x) * BLOCK_SIZE,
(piece["y"] + y) * BLOCK_SIZE,
BLOCK_SIZE, BLOCK_SIZE))
pygame.draw.rect(screen, WHITE,
(GAME_AREA_LEFT + (piece["x"] + x) * BLOCK_SIZE,
(piece["y"] + y) * BLOCK_SIZE,
BLOCK_SIZE, BLOCK_SIZE), 1)
# Рисуем информацию (счет, уровень)
font = pygame.font.SysFont(None, 36)
score_text = font.render(f"Счет: {self.score}", True, WHITE)
level_text = font.render(f"Уровень: {self.level}", True, WHITE)
screen.blit(score_text, (GAME_AREA_LEFT + GRID_WIDTH * BLOCK_SIZE + 10, 30))
screen.blit(level_text, (GAME_AREA_LEFT + GRID_WIDTH * BLOCK_SIZE + 10, 70))
# Если игра окончена, выводим сообщение
if self.game_over:
game_over_font = pygame.font.SysFont(None, 48)
game_over_text = game_over_font.render("Игра Окончена!", True, (255, 0, 0))
screen.blit(game_over_text, (GAME_AREA_LEFT + GRID_WIDTH * BLOCK_SIZE // 2 - 100,
SCREEN_HEIGHT // 2 - 24))
# Создаем экземпляр игры
game = Tetris()
# Основной игровой цикл
running = True
last_time = pygame.time.get_ticks()
while running:
# Управление FPS
current_time = pygame.time.get_ticks()
delta_time = (current_time - last_time) / 1000.0 # Конвертируем в секунды
last_time = current_time
# Обработка событий
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if not game.game_over:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
if game.valid_move(game.current_piece, -1, 0):
game.current_piece["x"] -= 1
elif event.key == pygame.K_RIGHT:
if game.valid_move(game.current_piece, 1, 0):
game.current_piece["x"] += 1
elif event.key == pygame.K_DOWN:
if game.valid_move(game.current_piece, 0, 1):
game.current_piece["y"] += 1
elif event.key == pygame.K_UP:
game.rotate_piece()
elif event.key == pygame.K_SPACE:
# Мгновенное падение
while game.valid_move(game.current_piece, 0, 1):
game.current_piece["y"] += 1
game.lock_piece()
# Обновление игры
game.update(delta_time)
# Отрисовка
game.draw()
pygame.display.flip()
# Ограничиваем FPS
clock.tick(60)
pygame.quit()