编辑代码

import pygame
import random

# 初始化Pygame
pygame.init()

# 游戏常量
BLOCK_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20
GAP_LEFT = 30
GAP_TOP = 30
SCREEN_WIDTH = GAP_LEFT + GRID_WIDTH * BLOCK_SIZE + 200
SCREEN_HEIGHT = GAP_TOP + GRID_HEIGHT * BLOCK_SIZE + 50

# 颜色定义
COLORS = [
    (0, 0, 0),         # 0: 背景黑
    (0, 255, 255),     # 1: I型
    (255, 255, 0),     # 2: O型
    (128, 0, 128),     # 3: T型
    (255, 165, 0),     # 4: L型
    (0, 0, 255),       # 5: J型
    (255, 0, 0),       # 6: S型
    (0, 255, 0)        # 7: Z型
]

# 方块形状定义
SHAPES = [
    # I型
    [[(-1, 0), (0, 0), (1, 0), (2, 0)], 
     [(0, -1), (0, 0), (0, 1), (0, 2)]],
    # O型
    [[(0, 0), (1, 0), (0, 1), (1, 1)]],
    # T型
    [[(-1, 0), (0, 0), (1, 0), (0, 1)],
     [(0, -1), (0, 0), (0, 1), (-1, 0)],
     [(-1, 0), (0, 0), (1, 0), (0, -1)],
     [(0, -1), (0, 0), (0, 1), (1, 0)]],
    # L型
    [[(-1, 0), (0, 0), (1, 0), (1, 1)],
     [(0, -1), (0, 0), (0, 1), (-1, 1)],
     [(-1, -1), (-1, 0), (0, 0), (1, 0)],
     [(0, -1), (0, 0), (0, 1), (1, -1)]],
    # J型
    [[(-1, 0), (0, 0), (1, 0), (-1, 1)],
     [(0, -1), (0, 0), (0, 1), (-1, -1)],
     [(-1, 0), (0, 0), (1, 0), (1, -1)],
     [(0, -1), (0, 0), (0, 1), (1, 1)]],
    # S型
    [[(-1, 0), (0, 0), (0, 1), (1, 1)],
     [(0, -1), (0, 0), (-1, 0), (-1, 1)]],
    # Z型
    [[(-1, 1), (0, 1), (0, 0), (1, 0)],
     [(1, -1), (1, 0), (0, 0), (0, 1)]]
]

SHAPE_ROTATIONS = [2, 1, 4, 4, 4, 2, 2]  # 每个形状的旋转状态数量

class Piece:
    def __init__(self, shape_type):
        self.shape_type = shape_type
        self.rotation = 0
        self.x = GRID_WIDTH // 2
        self.y = 0

    def get_blocks(self):
        shape_group = SHAPES[self.shape_type]
        rotation = self.rotation % SHAPE_ROTATIONS[self.shape_type]
        return [(self.x + dx, self.y + dy) for (dx, dy) in shape_group[rotation]]

def is_collision(grid, piece):
    for (x, y) in piece.get_blocks():
        if x < 0 or x >= GRID_WIDTH:
            return True
        if y >= GRID_HEIGHT:
            return True
        if y >= 0 and grid[y][x]:
            return True
    return False

def merge_piece(grid, piece):
    for (x, y) in piece.get_blocks():
        if 0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT:
            grid[y][x] = piece.shape_type + 1

def clear_lines(grid):
    lines_cleared = 0
    y = GRID_HEIGHT - 1
    while y >= 0:
        if all(grid[y]):
            del grid[y]
            grid.insert(0, [0]*GRID_WIDTH)
            lines_cleared += 1
        else:
            y -= 1
    return lines_cleared

def draw_piece(screen, piece):
    color = COLORS[piece.shape_type + 1]
    for (x, y) in piece.get_blocks():
        if y >= 0:
            pygame.draw.rect(screen, color, 
                           (GAP_LEFT + x*BLOCK_SIZE, 
                            GAP_TOP + y*BLOCK_SIZE,
                            BLOCK_SIZE-1, BLOCK_SIZE-1))

def draw_grid(screen, grid):
    for y in range(GRID_HEIGHT):
        for x in range(GRID_WIDTH):
            color_idx = grid[y][x]
            if color_idx:
                pygame.draw.rect(screen, COLORS[color_idx], 
                               (GAP_LEFT + x*BLOCK_SIZE,
                                GAP_TOP + y*BLOCK_SIZE,
                                BLOCK_SIZE-1, BLOCK_SIZE-1))

def main():
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption("俄罗斯方块")
    clock = pygame.time.Clock()
    grid = [[0]*GRID_WIDTH for _ in range(GRID_HEIGHT)]
    current_piece = Piece(random.randint(0, 6))
    next_piece = Piece(random.randint(0, 6))
    fall_time = 0
    fall_speed = 500
    running = True
    game_over = False

    while running:
        screen.fill((255, 255, 255))
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                if game_over:
                    continue
                if event.key == pygame.K_LEFT:
                    current_piece.x -= 1
                    if is_collision(grid, current_piece):
                        current_piece.x += 1
                elif event.key == pygame.K_RIGHT:
                    current_piece.x += 1
                    if is_collision(grid, current_piece):
                        current_piece.x -= 1
                elif event.key == pygame.K_DOWN:
                    current_piece.y += 1
                    if is_collision(grid, current_piece):
                        current_piece.y -= 1
                        merge_piece(grid, current_piece)
                        clear_lines(grid)
                        current_piece = next_piece
                        next_piece = Piece(random.randint(0, 6))
                        if is_collision(grid, current_piece):
                            game_over = True
                elif event.key == pygame.K_UP:
                    original_rotation = current_piece.rotation
                    current_piece.rotation += 1
                    if is_collision(grid, current_piece):
                        current_piece.rotation = original_rotation

        if not game_over:
            fall_time += clock.get_rawtime()
            if fall_time >= fall_speed:
                fall_time = 0
                current_piece.y += 1
                if is_collision(grid, current_piece):
                    current_piece.y -= 1
                    merge_piece(grid, current_piece)
                    clear_lines(grid)
                    current_piece = next_piece
                    next_piece = Piece(random.randint(0, 6))
                    if is_collision(grid, current_piece):
                        game_over = True

        draw_grid(screen, grid)
        if not game_over:
            draw_piece(screen, current_piece)
        if game_over:
            font = pygame.font.SysFont('arial', 48)
            text = font.render('Game Over', True, (255, 0, 0))
            screen.blit(text, (SCREEN_WIDTH//2 - text.get_width()//2, 
                             SCREEN_HEIGHT//2 - text.get_height()//2))
        pygame.display.update()
        clock.tick(60)

    pygame.quit()

if __name__ == "__main__":
    main()