import pygame
import random

# 游戏基础设置
BLOCK_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20
SCREEN_WIDTH = BLOCK_SIZE * (GRID_WIDTH + 6)
SCREEN_HEIGHT = BLOCK_SIZE * GRID_HEIGHT

# 方块形状定义
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
]
COLORS = [
    (0, 255, 255),
    (255, 255, 0),
    (128, 0, 128),
    (255, 165, 0),
    (0, 0, 255),
    (0, 255, 0),
    (255, 0, 0)
]

class Tetromino:
    def __init__(self):
        self.shape_idx = random.randint(0, len(SHAPES)-1)
        self.shape = SHAPES[self.shape_idx]
        self.color = COLORS[self.shape_idx]
        self.x = GRID_WIDTH // 2 - len(self.shape[0]) // 2
        self.y = 0

    def rotate(self):
        # 矩阵旋转
        rotated = list(zip(*self.shape[::-1]))
        self.shape = [list(row) for row in rotated]

class Game:
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("俄罗斯方块")
        self.clock = pygame.time.Clock()
        self.grid = [[(0,0,0) for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
        self.current = Tetromino()
        self.next_piece = Tetromino()
        self.score = 0
        self.fall_time = 0
        self.fall_speed = 500
        # =========【修复重点】=========
        # 替换 SysFont(None,36)，规避Windows字体bug
        self.font = pygame.font.Font(None, 36)

    def check_collision(self, piece, dx=0, dy=0):
        for y, row in enumerate(piece.shape):
            for x, cell in enumerate(row):
                if cell:
                    nx = piece.x + x + dx
                    ny = piece.y + y + dy
                    if nx < 0 or nx >= GRID_WIDTH:
                        return True
                    if ny >= GRID_HEIGHT:
                        return True
                    if ny >= 0 and self.grid[ny][nx] != (0,0,0):
                        return True
        return False

    def lock_piece(self):
        for y, row in enumerate(self.current.shape):
            for x, cell in enumerate(row):
                if cell:
                    self.grid[self.current.y + y][self.current.x + x] = self.current.color
        self.clear_lines()
        self.current = self.next_piece
        self.next_piece = Tetromino()
        if self.check_collision(self.current):
            return False # 游戏结束
        return True

    def clear_lines(self):
        lines = 0
        for y in range(GRID_HEIGHT-1, -1, -1):
            if all(c != (0,0,0) for c in self.grid[y]):
                lines += 1
                for yy in range(y, 0, -1):
                    self.grid[yy] = self.grid[yy-1][:]
                self.grid[0] = [(0,0,0)] * GRID_WIDTH
        self.score += lines * 100

    def draw_grid(self):
        for y in range(GRID_HEIGHT):
            for x in range(GRID_WIDTH):
                color = self.grid[y][x]
                rect = pygame.Rect(x*BLOCK_SIZE, y*BLOCK_SIZE, BLOCK_SIZE-1, BLOCK_SIZE-1)
                pygame.draw.rect(self.screen, color, rect)

    def draw_piece(self, piece, offset_x=0, offset_y=0):
        for y, row in enumerate(piece.shape):
            for x, cell in enumerate(row):
                if cell:
                    rx = (piece.x + x + offset_x) * BLOCK_SIZE
                    ry = (piece.y + y + offset_y) * BLOCK_SIZE
                    r = pygame.Rect(rx, ry, BLOCK_SIZE-1, BLOCK_SIZE-1)
                    pygame.draw.rect(self.screen, piece.color, r)

    def draw_next(self):
        tx = GRID_WIDTH * BLOCK_SIZE + 20
        ty = 80
        text = self.font.render("下一个", True, (255,255,255))
        self.screen.blit(text, (tx, 40))
        for y, row in enumerate(self.next_piece.shape):
            for x, cell in enumerate(row):
                if cell:
                    r = pygame.Rect(tx + x*BLOCK_SIZE, ty + y*BLOCK_SIZE, BLOCK_SIZE-1, BLOCK_SIZE-1)
                    pygame.draw.rect(self.screen, self.next_piece.color, r)

    def run(self):
        game_over = False
        last_drop = pygame.time.get_ticks()
        while not game_over:
            now = pygame.time.get_ticks()
            self.screen.fill((20,20,20))
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    return
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT and not self.check_collision(self.current, dx=-1):
                        self.current.x -= 1
                    if event.key == pygame.K_RIGHT and not self.check_collision(self.current, dx=1):
                        self.current.x += 1
                    if event.key == pygame.K_DOWN and not self.check_collision(self.current, dy=1):
                        self.current.y += 1
                    if event.key == pygame.K_UP:
                        old_shape = self.current.shape.copy()
                        self.current.rotate()
                        if self.check_collision(self.current):
                            self.current.shape = old_shape

            # 自动下落
            if now - last_drop > self.fall_speed:
                if self.check_collision(self.current, dy=1):
                    if not self.lock_piece():
                        game_over = True
                else:
                    self.current.y += 1
                last_drop = now

            self.draw_grid()
            self.draw_piece(self.current)
            self.draw_next()
            score_text = self.font.render(f"分数:{self.score}", True, (255,255,255))
            self.screen.blit(score_text, (GRID_WIDTH*BLOCK_SIZE+10, 220))
            pygame.display.update()
            self.clock.tick(60)

        # 游戏结束画面
        over_text = self.font.render("游戏结束！", True, (255,0,0))
        self.screen.blit(over_text, (40, SCREEN_HEIGHT//2))
        pygame.display.update()
        pygame.time.wait(2000)

if __name__ == "__main__":
    game = Game()
    game.run()