import tkinter as tk

from tkinter import messagebox

class Gobang:

    def __init__(self):

        self.window = tk.Tk()

        self.window.title("五子棋")

        

        # 棋盘大小

        self.board_size = 15

        self.cell_size = 40

        self.board_margin = 80

        

        # 创建画布

        canvas_size = self.board_size * self.cell_size + self.board_margin + 30

        self.canvas = tk.Canvas(self.window, width=canvas_size, height=canvas_size)

        self.canvas.pack(padx=10, pady=10)

        

        try:

            # 加载背景图片

            self.bg_image = tk.PhotoImage(file="./background.png")

            # 显示背景图片

            self.canvas.create_image(canvas_size//2, canvas_size//2,

                                   image=self.bg_image)

        except Exception as e:

            print("背景图片加载失败:", e)

            # 如果加载图片失败,使用纯色背景

            self.canvas.create_rectangle(0, 0, canvas_size, canvas_size,

                                      fill='#CDBA96', outline='#CDBA96')

        

        # 初始化棋盘数据

        self.board = [[0] * self.board_size for _ in range(self.board_size)]

        self.current_player = 1

        

        # 绘制棋盘

        self.draw_board()

        

        # 绑定鼠标点击事件

        self.canvas.bind('<Button-1>', self.handle_click)

        

    def draw_board(self):

        # 显示当前执子角色

        current_player_text = "当前执子:黑方" if self.current_player == 1 else "当前执子:白方"

        self.canvas.create_text(self.board_margin + (self.board_size-1) * self.cell_size / 2,

                              self.board_margin - 40,

                              text=current_player_text,

                              font=('Arial', 14, 'bold'),

                              fill='#000000')

        

        # 绘制横线和坐标

        for i in range(self.board_size):

            y = self.board_margin + i * self.cell_size

            # 绘制横线

            self.canvas.create_line(self.board_margin, y,

                                  self.board_margin + (self.board_size-1) * self.cell_size, y,

                                  width=2.0, fill='#000000')  # 加粗线条

            # 添加纵坐标标记(A-O)

            self.canvas.create_text(self.board_margin - 20, y,

                                  text=chr(65 + i), font=('Arial', 11))

        

        # 绘制竖线和坐标

        for i in range(self.board_size):

            x = self.board_margin + i * self.cell_size

            # 绘制竖线

            self.canvas.create_line(x, self.board_margin,

                                  x, self.board_margin + (self.board_size-1) * self.cell_size,

                                  width=2.0, fill='#000000')  # 加粗线条

            # 添加横坐标标记(1-15)

            self.canvas.create_text(x, self.board_margin - 20,

                                  text=str(i + 1), font=('Arial', 11))

    def place_piece(self, x, y):

        # 在棋盘数据中记录

        self.board[y][x] = self.current_player

        

        piece_x = self.board_margin + x * self.cell_size

        piece_y = self.board_margin + y * self.cell_size

        

        # 绘制阴影

        shadow_offset = 2

        self.canvas.create_oval(piece_x-15+shadow_offset, piece_y-15+shadow_offset,

                              piece_x+15+shadow_offset, piece_y+15+shadow_offset,

                              fill='#666666', outline='#666666')

        

        # 设置棋子基本属性

        piece_color = 'black' if self.current_player == 1 else '#FFFFFF'

        gradient_color = '#444444' if self.current_player == 1 else '#e0e0e0'

        outline_color = 'black'

        

        # 主棋子

        self.canvas.create_oval(piece_x-15, piece_y-15,

                              piece_x+15, piece_y+15,

                              fill=piece_color, outline=outline_color)

        

        # 渐变效果

        self.canvas.create_oval(piece_x-12, piece_y-12,

                              piece_x+8, piece_y+8,

                              fill=gradient_color, stipple='gray50')

        

        # 高光效果

        self.canvas.create_oval(piece_x-10, piece_y-10,

                              piece_x-4, piece_y-4,

                              fill='white', stipple='gray75')

        

        # 添加渐变效果

        if self.current_player == 1:  # 黑棋

            gradient_color = '#444444'

            gradient_pos = 8  # 渐变位置

        else:  # 白棋

            gradient_color = '#e0e0e0'

            gradient_pos = 8  # 调整白棋渐变位置

            

        self.canvas.create_oval(piece_x-12, piece_y-12,

                              piece_x+gradient_pos, piece_y+gradient_pos,

                              fill=gradient_color, stipple='gray50')

        

        # 添加高光效果

        if self.current_player == 1:  # 黑棋

            shine_size = 6

            shine_pos = -10

        else:  # 白棋

            shine_size = 6

            shine_pos = -10

            

        self.canvas.create_oval(piece_x+shine_pos, piece_y+shine_pos,

                              piece_x+shine_pos+shine_size, piece_y+shine_pos+shine_size,

                              fill='white', stipple='gray75')

    

    def redraw_all_pieces(self):

        # 重新绘制所有已放置的棋子

        for y in range(self.board_size):

            for x in range(self.board_size):

                if self.board[y][x] != 0:

                    # 临时保存当前玩家

                    original_player = self.current_player

                    # 设置为对应的玩家

                    self.current_player = self.board[y][x]

                    # 绘制棋子

                    self.place_piece(x, y)

                    # 恢复当前玩家

                    self.current_player = original_player

    def handle_click(self, event):

        # 将点击位置转换为棋盘坐标

        x = round((event.x - self.board_margin) / self.cell_size)

        y = round((event.y - self.board_margin) / self.cell_size)

        

        # 检查是否在有效范围内

        if 0 <= x < self.board_size and 0 <= y < self.board_size:

            if self.board[y][x] == 0:  # 如果该位置没有棋子

                self.place_piece(x, y)

                if self.check_win(x, y):

                    self.window.update()

                    winner = "黑方" if self.current_player == 1 else "白方"

                    messagebox.showinfo("游戏结束", f"{winner}获胜!")

                    self.reset_game()

                self.current_player = 3 - self.current_player

                # 重绘棋盘以更新当前执子显示

                self.canvas.delete("all")

                canvas_size = self.board_size * self.cell_size + self.board_margin + 30

                try:

                    self.canvas.create_image(canvas_size//2, canvas_size//2,

                                           image=self.bg_image)

                except:

                    self.canvas.create_rectangle(0, 0, canvas_size, canvas_size,

                                              fill='#CDBA96', outline='#CDBA96')

                self.draw_board()

                # 重新绘制所有棋子

                self.redraw_all_pieces()

    

    def check_win(self, x, y):

        directions = [(1,0), (0,1), (1,1), (1,-1)]  # 横、竖、右斜、左斜

        for dx, dy in directions:

            count = 1

            winning_pieces = [(x, y)]  # 记录获胜棋子的位置

            

            # 正向检查

            temp_x, temp_y = x + dx, y + dy

            while 0 <= temp_x < self.board_size and 0 <= temp_y < self.board_size:

                if self.board[temp_y][temp_x] == self.current_player:

                    count += 1

                    winning_pieces.append((temp_x, temp_y))

                    temp_x += dx

                    temp_y += dy

                else:

                    break

            

            # 反向检查

            temp_x, temp_y = x - dx, y - dy

            while 0 <= temp_x < self.board_size and 0 <= temp_y < self.board_size:

                if self.board[temp_y][temp_x] == self.current_player:

                    count += 1

                    winning_pieces.append((temp_x, temp_y))

                    temp_x -= dx

                    temp_y -= dy

                else:

                    break

            

            if count >= 5:

                self.highlight_winning_pieces(winning_pieces)

                return True

        return False

    def highlight_winning_pieces(self, positions):

        for x, y in positions:

            piece_x = self.board_margin + x * self.cell_size

            piece_y = self.board_margin + y * self.cell_size

            

            # 绘制高亮边框

            self.canvas.create_oval(piece_x-16, piece_y-16,

                                  piece_x+16, piece_y+16,

                                  outline='red',

                                  width=2)

    

    def reset_game(self):

        # 清空棋盘数据

        self.board = [[0] * self.board_size for _ in range(self.board_size)]

        # 清空画布

        self.canvas.delete("all")

        

        # 重新绘制背景

        canvas_size = self.board_size * self.cell_size + self.board_margin + 30

        try:

            # 重新显示背景图片

            self.canvas.create_image(canvas_size//2, canvas_size//2,

                                   image=self.bg_image)

        except:

            # 如果加载图片失败,使用纯色背景

            self.canvas.create_rectangle(0, 0, canvas_size, canvas_size,

                                      fill='#CDBA96', outline='#CDBA96')

        

        # 重新绘制棋盘

        self.draw_board()

        # 重置当前玩家

        self.current_player = 1

    

    def run(self):

        self.window.mainloop()

if __name__ == "__main__":

    game = Gobang()

    game.run()