import pygame
import random
import sys

pygame.init()
WIDTH, HEIGHT = 560, 620
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("吃豆人 Pacman")
clock = pygame.time.Clock()
FPS = 60

# 颜色
BLACK = (0, 0, 0)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)

# 修复迷宫！中间幽灵房间上方打通通道，不再封闭
map_data = [
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
    [1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1],
    [1,0,1,1,1,0,1,1,0,1,0,1,1,0,1,1,1,0,1],
    [1,0,1,1,1,0,1,1,0,0,0,1,1,0,1,1,1,0,1],
    [1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1],
    [1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1,0,1],
    [1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1],  # 改动：中间打通
    [1,1,1,1,1,0,1,1,0,1,0,1,1,0,1,1,1,1,1],
    [1,1,1,1,1,0,1,0,0,0,0,0,1,0,1,1,1,1,1],
    [1,1,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1,1,1],
    [0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0],
    [1,1,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1,1,1],
    [1,1,1,1,1,0,1,0,0,0,0,0,1,0,1,1,1,1,1],
    [1,1,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1,1,1],
    [1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1],
    [1,0,1,1,1,0,1,1,0,1,0,1,1,0,1,1,1,0,1],
    [1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1],
    [1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,1,1],
    [1,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,1],
    [1,0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
]
CELL_SIZE = 28
MAP_W = len(map_data[0])
MAP_H = len(map_data)

class Pacman:
    def __init__(self):
        # 吃豆人出生移到隔间外面，不再困在幽灵房！
        start_cx = 9
        start_cy = 6
        self.x = start_cx * CELL_SIZE + CELL_SIZE / 2
        self.y = start_cy * CELL_SIZE + CELL_SIZE / 2
        self.dx = 0
        self.dy = 0
        self.speed = 2.2
        self.radius = CELL_SIZE//2 - 2

    def is_wall_cell(self, cx, cy):
        if 0 <= cx < MAP_W and 0 <= cy < MAP_H:
            return map_data[cy][cx] == 1
        return True

    def can_move_pos(self, px, py):
        cx = int(px // CELL_SIZE)
        cy = int(py // CELL_SIZE)
        return not self.is_wall_cell(cx, cy)

    def update(self):
        target_x = self.x + self.dx * self.speed
        target_y = self.y + self.dy * self.speed

        # X Y 轴独立碰撞，防止穿墙卡墙
        if self.can_move_pos(target_x, self.y):
            self.x = target_x
        if self.can_move_pos(self.x, target_y):
            self.y = target_y

        # 左右隧道传送
        if self.x < 0:
            self.x = CELL_SIZE * MAP_W
        if self.x > CELL_SIZE * MAP_W:
            self.x = 0

    def draw(self):
        pygame.draw.circle(screen, YELLOW, (int(self.x), int(self.y)), self.radius)


class Ghost:
    def __init__(self):
        # 幽灵依旧在中间房间
        cx = 9
        cy = 9
        self.x = cx * CELL_SIZE + CELL_SIZE / 2
        self.y = cy * CELL_SIZE + CELL_SIZE / 2
        self.speed = 1.1

    def update(self, tx, ty):
        dirs = []
        if self.x < tx:
            dirs.append((self.speed, 0))
        if self.x > tx:
            dirs.append((-self.speed, 0))
        if self.y < ty:
            dirs.append((0, self.speed))
        if self.y > ty:
            dirs.append((0, -self.speed))
        random.shuffle(dirs)

        moved = False
        for ddx, ddy in dirs:
            nx = self.x + ddx
            ny = self.y + ddy
            c_x = int(nx // CELL_SIZE)
            c_y = int(ny // CELL_SIZE)
            if 0 <= c_x < MAP_W and 0 <= c_y < MAP_H and map_data[c_y][c_x] != 1:
                self.x = nx
                self.y = ny
                moved = True
                break
        if not moved:
            all_dir = [(self.speed,0),(-self.speed,0),(0,self.speed),(0,-self.speed)]
            random.shuffle(all_dir)
            for ddx, ddy in all_dir:
                nx = self.x + ddx
                ny = self.y + ddy
                c_x = int(nx // CELL_SIZE)
                c_y = int(ny // CELL_SIZE)
                if 0 <= c_x < MAP_W and 0 <= c_y < MAP_H and map_data[c_y][c_x] != 1:
                    self.x = nx
                    self.y = ny
                    break

    def draw(self):
        pygame.draw.circle(screen, RED, (int(self.x), int(self.y)), CELL_SIZE//2 -3)


def main():
    pac = Pacman()
    ghost = Ghost()
    score = 0
    font = pygame.font.Font(None, 32)

    dots = []
    for y, row in enumerate(map_data):
        for x, v in enumerate(row):
            if v == 0:
                dots.append((x*CELL_SIZE + CELL_SIZE//2, y*CELL_SIZE + CELL_SIZE//2))

    running = True
    while running:
        screen.fill(BLACK)
        keys = pygame.key.get_pressed()

        # 按键控制
        if keys[pygame.K_a] or keys[pygame.K_LEFT]:
            pac.dx, pac.dy = -1, 0
        elif keys[pygame.K_d] or keys[pygame.K_RIGHT]:
            pac.dx, pac.dy = 1, 0
        elif keys[pygame.K_w] or keys[pygame.K_UP]:
            pac.dx, pac.dy = 0, -1
        elif keys[pygame.K_s] or keys[pygame.K_DOWN]:
            pac.dx, pac.dy = 0, 1
        else:
            pac.dx, pac.dy = 0, 0

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        # 绘制墙
        for y, row in enumerate(map_data):
            for x, v in enumerate(row):
                if v == 1:
                    pygame.draw.rect(screen, BLUE, (x*CELL_SIZE,y*CELL_SIZE,CELL_SIZE-1,CELL_SIZE-1))

        # 豆子绘制与拾取
        for pos in dots[:]:
            dis_sq = (pac.x-pos[0])**2 + (pac.y-pos[1])**2
            if dis_sq < 130:
                dots.remove(pos)
                score += 10
            pygame.draw.circle(screen, WHITE, pos, 3)

        pac.update()
        pac.draw()
        ghost.update(pac.x, pac.y)
        ghost.draw()

        # 碰撞判定
        if (pac.x-ghost.x)**2 + (pac.y-ghost.y)**2 < 400:
            print(f"游戏结束！得分:{score}")
            running = False

        if len(dots) == 0:
            print(f"通关！得分:{score}")
            running = False

        text = font.render(f"Score: {score}", True, WHITE)
        screen.blit(text, (10, HEIGHT-30))

        pygame.display.flip()
        clock.tick(FPS)

    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()