import pygame
import random
import os
import sys

# --- 1. 初始化与字体设置 ---
pygame.init()

# 自动寻找系统中文字体
def get_font(size):
    font_paths = [
        "C:/Windows/Fonts/msyh.ttc",      # Windows 微软雅黑
        "C:/Windows/Fonts/simhei.ttf",     # Windows 黑体
        "/System/Library/Fonts/PingFang.ttc", # Mac 苹方
        "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc" # Linux
    ]
    for path in font_paths:
        if os.path.exists(path):
            return pygame.font.Font(path, size)
    return pygame.font.Font(None, size)

# --- 2. 游戏配置 ---
SIZE = 4
TILE_SIZE = 100
GAP = 10
BOARD_SIZE = TILE_SIZE * SIZE + GAP * (SIZE + 1)
SCREEN_WIDTH = BOARD_SIZE
SCREEN_HEIGHT = BOARD_SIZE + 60  # 底部留空显示分数

screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Pygame 2048")

# 颜色配置 (背景, 空格, 数字颜色)
BG_COLOR = (187, 173, 160)
EMPTY_COLOR = (205, 193, 180)
TEXT_COLOR_DARK = (119, 110, 101)
TEXT_COLOR_LIGHT = (249, 246, 242)

# 不同数字对应的背景色
TILE_COLORS = {
    2: (238, 228, 218), 4: (237, 224, 200), 8: (242, 177, 121),
    16: (245, 149, 99), 32: (246, 124, 95), 64: (246, 94, 59),
    128: (237, 207, 114), 256: (237, 204, 97), 512: (237, 200, 80),
    1024: (237, 197, 63), 2048: (237, 194, 46)
}

font_large = get_font(40)
font_small = get_font(30)
font_hint = get_font(24)

# --- 3. 核心游戏逻辑 ---
class Game2048:
    def __init__(self):
        self.reset()

    def reset(self):
        self.board = [[0]*SIZE for _ in range(SIZE)]
        self.score = 0
        self.add_random_tile()
        self.add_random_tile()

    def add_random_tile(self):
        empty = [(r, c) for r in range(SIZE) for c in range(SIZE) if self.board[r][c] == 0]
        if empty:
            r, c = random.choice(empty)
            self.board[r][c] = 2 if random.random() < 0.9 else 4

    def move(self, direction):
        # 简单的移动合并逻辑
        def compress(row):
            new_row = [i for i in row if i != 0]
            new_row += [0] * (SIZE - len(new_row))
            return new_row

        def merge(row):
            score = 0
            for i in range(SIZE - 1):
                if row[i] == row[i+1] and row[i] != 0:
                    row[i] *= 2
                    row[i+1] = 0
                    score += row[i]
            return row, score

        old_board = [row[:] for row in self.board]
        move_score = 0

        if direction in ('LEFT', 'RIGHT'):
            for r in range(SIZE):
                row = self.board[r][:]
                if direction == 'RIGHT': row = row[::-1]
                row = compress(row)
                row, sc = merge(row)
                row = compress(row)
                move_score += sc
                if direction == 'RIGHT': row = row[::-1]
                self.board[r] = row
        
        elif direction in ('UP', 'DOWN'):
            for c in range(SIZE):
                col = [self.board[r][c] for r in range(SIZE)]
                if direction == 'DOWN': col = col[::-1]
                col = compress(col)
                col, sc = merge(col)
                col = compress(col)
                move_score += sc
                if direction == 'DOWN': col = col[::-1]
                for r in range(SIZE): self.board[r][c] = col[r]

        if self.board != old_board:
            self.score += move_score
            self.add_random_tile()
            return True
        return False

    def is_game_over(self):
        # 简单判断：还有空格或者相邻有相同数字就没结束
        for r in range(SIZE):
            for c in range(SIZE):
                if self.board[r][c] == 0: return False
                if c < SIZE-1 and self.board[r][c] == self.board[r][c+1]: return False
                if r < SIZE-1 and self.board[r][c] == self.board[r+1][c]: return False
        return True

# --- 4. 绘制界面 ---
def draw_tile(x, y, value):
    color = TILE_COLORS.get(value, (60, 58, 50)) # 超过2048变深色
    rect = pygame.Rect(x, y, TILE_SIZE, TILE_SIZE)
    pygame.draw.rect(screen, color, rect, border_radius=10)
    
    if value != 0:
        text_color = TEXT_COLOR_LIGHT if value >= 8 else TEXT_COLOR_DARK
        font = font_small if value >= 1024 else font_large
        text = font.render(str(value), True, text_color)
        text_rect = text.get_rect(center=rect.center)
        screen.blit(text, text_rect)

def draw_board(game):
    screen.fill(BG_COLOR)
    for r in range(SIZE):
        for c in range(SIZE):
            x = GAP + c * (TILE_SIZE + GAP)
            y = GAP + r * (TILE_SIZE + GAP)
            draw_tile(x, y, game.board[r][c])
    
    # 底部分数
    score_text = font_hint.render(f"Score: {game.score} | R: Restart", True, TEXT_COLOR_LIGHT)
    screen.blit(score_text, (10, BOARD_SIZE + 15))

# --- 5. 主循环 ---
game = Game2048()
clock = pygame.time.Clock()
running = True

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            moved = False
            if event.key in (pygame.K_LEFT, pygame.K_a): moved = game.move('LEFT')
            elif event.key in (pygame.K_RIGHT, pygame.K_d): moved = game.move('RIGHT')
            elif event.key in (pygame.K_UP, pygame.K_w): moved = game.move('UP')
            elif event.key in (pygame.K_DOWN, pygame.K_s): moved = game.move('DOWN')
            elif event.key == pygame.K_r: game.reset()
            
            if moved and game.is_game_over():
                print(f"Game Over! Final Score: {game.score}")

    draw_board(game)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
sys.exit()