Загрузка данных
import pygame
import random
# Инициализация Pygame
pygame.init()
# --- Настройки ---
WINDOW_WIDTH = 300
WINDOW_HEIGHT = 600
BLOCK_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20
PLAY_WIDTH = BLOCK_SIZE * GRID_WIDTH
PLAY_HEIGHT = BLOCK_SIZE * GRID_HEIGHT
TOP_LEFT_X = (WINDOW_WIDTH - PLAY_WIDTH) // 2
TOP_LEFT_Y = WINDOW_HEIGHT - PLAY_HEIGHT - 20
# Цвета (RGB)
BLACK = (0, 0, 0)
WHITE = (200, 200, 200)
GRAY = (128, 128, 128)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
CYAN = (0, 255, 255)
MAGENTA = (255, 0, 255)
YELLOW = (255, 255, 0)
ORANGE = (255, 165, 0)
# Фигуры и их вращения
S = [['.....',
'.....',
'..00.',
'.00..',
'.....'],
['.....',
'..0..',
'..00.',
'...0.',
'.....']]
Z = [['.....',
'.....',
'.00..',
'..00.',
'.....'],
['.....',
'..0..',
'.00..',
'.0...',
'.....']]
I = [['..0..',
'..0..',
'..0..',
'..0..',
'.....'],
['.....',
'0000.',
'.....',
'.....',
'.....']]
O = [['.....',
'.....',
'.00..',
'.00..',
'.....']]
J = [['.....',
'.0...',
'.000.',
'.....',
'.....'],
['.....',
'..00.',
'..0..',
'..0..',
'.....'],
['.....',
'.....',
'.000.',
'...0.',
'.....'],
['.....',
'..0..',
'..0..',
'.00..',
'.....']]
L = [['.....',
'...0.',
'.000.',
'.....',
'.....'],
['.....',
'..0..',
'..0..',
'..00.',
'.....'],
['.....',
'.....',
'.000.',
'.0...',
'.....'],
['.....',
'.00..',
'..0..',
'..0..',
'.....']]
T = [['.....',
'..0..',
'.000.',
'.....',
'.....'],
['.....',
'..0..',
'..00.',
'..0..',
'.....'],
['.....',
'.....',
'.000.',
'..0..',
'.....'],
['.....',
'..0..',
'.00..',
'..0..',
'.....']]
SHAPES = [S, Z, I, O, J, L, T]
SHAPE_COLORS = [GREEN, RED, CYAN, YELLOW, BLUE, ORANGE, MAGENTA]
# --- Класс фигуры ---
class Piece:
def __init__(self, x, y, shape):
self.x = x
self.y = y
self.shape = shape
self.color = SHAPE_COLORS[SHAPES.index(shape)]
self.rotation = 0 # текущий поворот (0,1,2,3 в зависимости от фигуры)
# --- Функции ---
def create_grid(locked_positions={}):
grid = [[BLACK for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
for y in range(GRID_HEIGHT):
for x in range(GRID_WIDTH):
if (x, y) in locked_positions:
grid[y][x] = locked_positions[(x, y)]
return grid
def convert_shape_format(piece):
positions = []
format = piece.shape[piece.rotation % len(piece.shape)]
for i, line in enumerate(format):
for j, column in enumerate(line):
if column == '0':
positions.append((piece.x + j, piece.y + i))
return positions
def valid_space(piece, grid):
accepted_pos = [[(j, i) for j in range(GRID_WIDTH) if grid[i][j] == BLACK] for i in range(GRID_HEIGHT)]
accepted_pos = [pos for sublist in accepted_pos for pos in sublist]
formatted = convert_shape_format(piece)
for pos in formatted:
if pos not in accepted_pos and pos[1] > -1:
return False
return True
def check_lost(positions):
for pos in positions:
x, y = pos
if y < 1:
return True
return False
def get_shape():
return Piece(5, 0, random.choice(SHAPES))
def draw_grid(surface, grid):
for y in range(GRID_HEIGHT):
for x in range(GRID_WIDTH):
pygame.draw.rect(surface, grid[y][x],
(TOP_LEFT_X + x * BLOCK_SIZE, TOP_LEFT_Y + y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE), 0)
# Сетка
for y in range(GRID_HEIGHT):
pygame.draw.line(surface, GRAY, (TOP_LEFT_X, TOP_LEFT_Y + y * BLOCK_SIZE),
(TOP_LEFT_X + PLAY_WIDTH, TOP_LEFT_Y + y * BLOCK_SIZE))
for x in range(GRID_WIDTH):
pygame.draw.line(surface, GRAY, (TOP_LEFT_X + x * BLOCK_SIZE, TOP_LEFT_Y),
(TOP_LEFT_X + x * BLOCK_SIZE, TOP_LEFT_Y + PLAY_HEIGHT))
# Рамка
pygame.draw.rect(surface, WHITE, (TOP_LEFT_X, TOP_LEFT_Y, PLAY_WIDTH, PLAY_HEIGHT), 4)
def draw_window(surface, grid, score=0):
surface.fill(BLACK)
font = pygame.font.SysFont('comicsans', 40)
label = font.render('ТЕТРИС', 1, WHITE)
surface.blit(label, (TOP_LEFT_X + PLAY_WIDTH / 2 - label.get_width() / 2, 20))
font = pygame.font.SysFont('comicsans', 25)
label = font.render(f'Счёт: {score}', 1, WHITE)
surface.blit(label, (TOP_LEFT_X + PLAY_WIDTH / 2 - label.get_width() / 2, TOP_LEFT_Y + PLAY_HEIGHT + 20))
draw_grid(surface, grid)
def clear_rows(grid, locked):
new_locked = {}
rows_cleared = 0
for y in range(GRID_HEIGHT - 1, -1, -1):
row = grid[y]
if BLACK not in row:
rows_cleared += 1
for x in range(GRID_WIDTH):
try:
del locked[(x, y)]
except:
pass
# Сдвиг строк вниз
for key in sorted(list(locked), key=lambda k: k[1]):
x, locked_y = key
if locked_y < y:
new_locked[(x, locked_y + 1)] = locked[key]
else:
new_locked[(x, locked_y)] = locked[key]
locked = new_locked.copy()
new_locked.clear()
return locked, rows_cleared
def draw_next_shape(piece, surface):
font = pygame.font.SysFont('comicsans', 25)
label = font.render('Следующая', 1, WHITE)
sx = TOP_LEFT_X + PLAY_WIDTH + 30
sy = TOP_LEFT_Y + 100
surface.blit(label, (sx, sy))
format = piece.shape[piece.rotation % len(piece.shape)]
for i, line in enumerate(format):
for j, column in enumerate(line):
if column == '0':
pygame.draw.rect(surface, piece.color,
(sx + j * BLOCK_SIZE//2, sy + 30 + i * BLOCK_SIZE//2, BLOCK_SIZE//2, BLOCK_SIZE//2), 0)
def main():
screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption('Тетрис')
clock = pygame.time.Clock()
grid = create_grid()
change_piece = False
run = True
current_piece = get_shape()
next_piece = get_shape()
locked_positions = {}
fall_time = 0
fall_speed = 0.5 # секунд
score = 0
while run:
grid = create_grid(locked_positions)
fall_time += clock.get_rawtime()
clock.tick()
if fall_time / 1000 > fall_speed:
fall_time = 0
current_piece.y += 1
if not valid_space(current_piece, grid) and current_piece.y > 0:
current_piece.y -= 1
change_piece = True
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.display.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
current_piece.x -= 1
if not valid_space(current_piece, grid):
current_piece.x += 1
if event.key == pygame.K_RIGHT:
current_piece.x += 1
if not valid_space(current_piece, grid):
current_piece.x -= 1
if event.key == pygame.K_DOWN:
current_piece.y += 1
if not valid_space(current_piece, grid):
current_piece.y -= 1
if event.key == pygame.K_UP:
current_piece.rotation += 1
if not valid_space(current_piece, grid):
current_piece.rotation -= 1
if event.key == pygame.K_SPACE:
while valid_space(current_piece, grid):
current_piece.y += 1
current_piece.y -= 1
change_piece = True
# Фиксация фигуры
if change_piece:
for pos in convert_shape_format(current_piece):
p = (pos[0], pos[1])
locked_positions[p] = current_piece.color
current_piece = next_piece
next_piece = get_shape()
change_piece = False
locked_positions, cleared = clear_rows(grid, locked_positions)
score += cleared * 10
draw_window(screen, grid, score)
draw_next_shape(next_piece, screen)
pygame.display.update()
if check_lost(locked_positions):
font = pygame.font.SysFont('comicsans', 40)
label = font.render('Игра окончена!', 1, RED)
screen.blit(label, (WINDOW_WIDTH//2 - label.get_width()//2, WINDOW_HEIGHT//2 - label.get_height()//2))
pygame.display.update()
pygame.time.delay(2000)
run = False
pygame.quit()
if __name__ == '__main__':
main()