import pygame
import random

pygame.init()

# ===================== 基础配置 =====================
BLOCK_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20
SIDEBAR_WIDTH = 160
WIDTH = BLOCK_SIZE * GRID_WIDTH + SIDEBAR_WIDTH
HEIGHT = BLOCK_SIZE * GRID_HEIGHT
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("俄罗斯方块")
clock = pygame.time.Clock()
FPS = 60

# 颜色定义
BLACK = (15, 15, 25)
WHITE = (255, 255, 255)
GRAY = (60, 60, 80)
BORDER_COLOR = (100, 140, 220)

COLORS = [
    (0, 0, 0),
    (0, 220, 220),
    (220, 220, 0),
    (120, 0, 220),
    (0, 0, 220),
    (220, 140, 0),
    (0, 220, 0),
    (220, 0, 0)
]

# 七种方块形状 (I, O, T, L, J, S, Z)
SHAPES = [
    [[0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0]],
    [[2, 2], [2, 2]],
    [[0, 3, 0], [3, 3, 3], [0, 0, 0]],
    [[0, 0, 4], [4, 4, 4], [0, 0, 0]],
    [[5, 0, 0], [5, 5, 5], [0, 0, 0]],
    [[0, 6, 6], [6, 6, 0], [0, 0, 0]],
    [[7, 7, 0], [0, 7, 7], [0, 0, 0]]
]

# 字体（中文兼容）
try:
    font = pygame.font.Font("simhei.ttf", 24)
    font_small = pygame.font.Font("simhei.ttf", 18)
except:
    font = pygame.font.SysFont("SimHei", 24)
    font_small = pygame.font.SysFont("SimHei", 18)


class Piece:
    def __init__(self):
        self.shape = random.choice(SHAPES)
        self.x = GRID_WIDTH // 2 - len(self.shape[0]) // 2
        self.y = 0

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


def create_grid(locked={}):
    grid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
    for (x, y), color_id in locked.items():
        if 0 <= y < GRID_HEIGHT:
            grid[y][x] = color_id
    return grid


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


def draw_game(surface, grid, current_piece, next_piece, score):
    # 背景
    surface.fill(BLACK)
    # 绘制游戏网格
    for y in range(GRID_HEIGHT):
        for x in range(GRID_WIDTH):
            color = COLORS[grid[y][x]]
            rect = pygame.Rect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE - 1, BLOCK_SIZE - 1)
            pygame.draw.rect(surface, color, rect)

    # 绘制当前下落方块
    shape = current_piece.shape
    px, py = current_piece.x, current_piece.y
    for dy, row in enumerate(shape):
        for dx, cell in enumerate(row):
            if cell:
                x_pos = px + dx
                y_pos = py + dy
                if y_pos >= 0:
                    r = pygame.Rect(x_pos * BLOCK_SIZE, y_pos * BLOCK_SIZE, BLOCK_SIZE - 1, BLOCK_SIZE - 1)
                    pygame.draw.rect(surface, COLORS[cell], r)

    # 游戏区域边框
    pygame.draw.rect(surface, BORDER_COLOR, (0, 0, GRID_WIDTH * BLOCK_SIZE, GRID_HEIGHT * BLOCK_SIZE), 3)

    # 侧边栏文字
    sx = GRID_WIDTH * BLOCK_SIZE + 20
    text_score = font.render(f"分数: {score}", True, WHITE)
    surface.blit(text_score, (sx, 40))
    text_next = font.render("下一个", True, WHITE)
    surface.blit(text_next, (sx, 100))

    # 预览下一个方块
    next_shape = next_piece.shape
    off_x = sx + 20
    off_y = 140
    for dy, row in enumerate(next_shape):
        for dx, cell in enumerate(row):
            if cell:
                r = pygame.Rect(off_x + dx * BLOCK_SIZE, off_y + dy * BLOCK_SIZE, BLOCK_SIZE - 1, BLOCK_SIZE - 1)
                pygame.draw.rect(surface, COLORS[cell], r)

    # 操作提示
    tip1 = font_small.render("← → 移动", True, (180, 180, 180))
    tip2 = font_small.render("↑ 旋转", True, (180, 180, 180))
    tip3 = font_small.render("↓ 下移", True, (180, 180, 180))
    tip4 = font_small.render("空格 直接落地", True, (180, 180, 180))
    surface.blit(tip1, (sx, 260))
    surface.blit(tip2, (sx, 290))
    surface.blit(tip3, (sx, 320))
    surface.blit(tip4, (sx, 350))


def main():
    locked_blocks = {}
    grid = create_grid(locked_blocks)
    current = Piece()
    next_piece = Piece()
    score = 0
    fall_time = 0
    fall_speed = 450  # 毫秒
    game_over = False

    while True:
        now = pygame.time.get_ticks()
        delta = clock.tick(FPS)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return
            if game_over:
                continue
            if event.type == pygame.KEYDOWN:
                # 左右移动
                if event.key == pygame.K_LEFT:
                    if not check_collision(current.shape, current.x - 1, current.y, grid):
                        current.x -= 1
                if event.key == pygame.K_RIGHT:
                    if not check_collision(current.shape, current.x + 1, current.y, grid):
                        current.x += 1
                # 下移
                if event.key == pygame.K_DOWN:
                    if not check_collision(current.shape, current.x, current.y + 1, grid):
                        current.y += 1
                # 旋转
                if event.key == pygame.K_UP:
                    new_shape = current.rotate()
                    if not check_collision(new_shape, current.x, current.y, grid):
                        current.shape = new_shape
                # 空格快速落底
                if event.key == pygame.K_SPACE:
                    while not check_collision(current.shape, current.x, current.y + 1, grid):
                        current.y += 1

        # 自动下落
        if now - fall_time > fall_speed:
            if not check_collision(current.shape, current.x, current.y + 1, grid):
                current.y += 1
            else:
                # 碰撞，锁定方块
                shape = current.shape
                px, py = current.x, current.y
                for dy, row in enumerate(shape):
                    for dx, cell in enumerate(row):
                        if cell:
                            locked_blocks[(px + dx, py + dy)] = cell
                # 消行判断
                full_lines = []
                for y in range(GRID_HEIGHT):
                    if all((x, y) in locked_blocks for x in range(GRID_WIDTH)):
                        full_lines.append(y)
                # 消除行
                if full_lines:
                    score += len(full_lines) * 100
                    for line in sorted(full_lines):
                        for x in range(GRID_WIDTH):
                            del locked_blocks[(x, line)]
                        # 上方所有行下落
                        for y in range(line, 0, -1):
                            for x in range(GRID_WIDTH):
                                if (x, y - 1) in locked_blocks:
                                    locked_blocks[(x, y)] = locked_blocks.pop((x, y - 1))
                # 生成新方块
                current = next_piece
                next_piece = Piece()
                # 游戏结束判定
                if check_collision(current.shape, current.x, current.y, grid):
                    game_over = True
                grid = create_grid(locked_blocks)
            fall_time = now

        draw_game(screen, grid, current, next_piece, score)
        if game_over:
            over_text = font.render("游戏结束!", True, (255, 60, 60))
            screen.blit(over_text, (GRID_WIDTH * BLOCK_SIZE//2 - 30, HEIGHT//2))
        pygame.display.update()


if __name__ == "__main__":
    main()