Bootstrap

[Python/Tkinter]用Tkinter编写一个五子棋程序(附源代码和图片文件)

说是用Tkinter,其实Tkinter只是负责图形建构的噢,先看成品图

先简单说明一下这个界面是怎样建构的再讲逻辑哦~ 

棋盘和背景都是图片,使用PhotoImage导入,然后用画布控件的create_image把图片放上去

棋子是用画布的方法create_oval画出来的

好了那么逻辑如何编写呢?我们首先要有一个明确的思路,把整件事情分为许多小步骤,一点一点完成,也可以说是逐步击破:构建棋盘--->棋盘落子--->胜负判断(PVP)--->编写简单AI(人机模式)。这些都完成后在补充一些诸如步时局时的细节就完成了。

一、构建棋盘

这部分是最简单的,我们只需要加载图片,创建窗口、画布并把图片放上去就行了

二、棋盘落子

一个程序的正确运行的背后是无数个小小的逻辑的支撑哦,要做到精准把控落子的位置需要我们一点一点的调试,第一步我们已经构建了棋盘,然后我们要获取最左上角和最右下角的落子位置的坐标从而计算出每个落子位置的坐标,通过self.game_canvas.bind('<Button-1>', 函数名)绑定鼠标单击事件,在函数内获取点击坐标,换算成棋盘落子位置的坐标,最后把棋子画上去就完成了

三、胜负判断

要做到让程序自己判断游戏是否已经分出胜负,我们首先需要让程序知晓棋盘的状况,也就是记录棋局,做到这一点可以使用二元数组,对不同颜色的棋子分别用不同数字表示。每下一步,就检索一遍数组,探查是否满足胜利条件,并且更新棋盘状态。这里我们需要从落子点出发,分别在竖向,横向,斜向方向判断是否连成五子,如图

 四、编写AI

 通过第三步的胜负判断,我们已经积累了一些经验,想让电脑知道该下哪里也就是让他知道哪里下棋最好,为此我们可以设置一个计分系统,在知道胜负标准的情况才下,通过分析棋盘上的棋子来得到每个落子点的分数,最后选取最高分的落子点下棋,这样就完成啦

废话不多说,直接看代码

五、代码展示

学艺不精,代码实在冗长qwq(ttkbootstrap只是tkinter的美化版本哦!)

import ttkbootstrap as ttk
import random
import pygame


class WuZiQi:
    def __init__(self):
        self.root = ttk.Window()
        self.root.title('五子棋')
        self.root.geometry('463x728+10+50')
        self.chessboard = ttk.Toplevel()
        self.chessboard.title('五子棋')
        """图片加载"""
        self.login_pic = ttk.PhotoImage(file=r'.\\background\\login.png')
        self.start_pic = ttk.PhotoImage(file=r'.\\background\\start.png')
        self.mode_pic = ttk.PhotoImage(file=r'.\\background\\mode.png')
        self.background_pic = ttk.PhotoImage(file=r'.\\background\\background.png')
        self.chess_board_pic = ttk.PhotoImage(file=r'.\\background\\chessboard.png')
        self.player1_pic = ttk.PhotoImage(file=r'.\\background\\player1.png')
        self.player2_pic = ttk.PhotoImage(file=r'.\\background\\player2.png')
        self.computer_pic = ttk.PhotoImage(file=r'.\\background\\computer.png')
        self.win_pic = ttk.PhotoImage(file=r'.\\background\\win.png')
        """画布控件"""
        self.login_canvas = ttk.Canvas(self.root, width=463, height=728)
        self.mode_canvas = ttk.Canvas(self.root, width=463, height=728)
        self.game_canvas = ttk.Canvas(self.chessboard, width=1450, height=880)
        """设置初始化"""
        self.setting_frame = ttk.Frame(self.root)
        self.setting_frame.pack()
        """记录棋盘落子情况的字典"""
        self.dic = {num: {} for num in range(-2, 21)}
        self.prefix = ['爱吃拉面的', '  好奇的', ' 眼睛圆的', '头上有天线的', '糊里糊涂的', '特会下棋的', '绝不放弃的', '沉默寡言的',
                       '爱喝饮料的', '最后王牌的', ' 完全体的', '阿姆斯特朗回旋加\n   速式的', ' 隐藏款的', '变化莫测的', ' ???的']
        self.color = 'black'   # 棋子颜色
        self.count = 1   # 记录总步数
        self.player = 1   # 1 代表黑棋, 2 代表白棋
        self.flag = False   # 游戏结束与否
        self.game_mode = 'pvp'
        self.per_time = ttk.IntVar()
        self.per_time.set(60)   # 步时
        self.all_time = ttk.IntVar()
        self.all_time.set(600)   # 总时间
        self.n1 = ttk.StringVar()
        self.n1.set('头顶果粒橙')
        self.n2 = ttk.StringVar()
        self.n2.set('吃个太空人')
        self.name1, self.name2 = '头顶果粒橙', '吃个太空人'
        self.p1_time1, self.p1_time2 = 60, 600
        self.p2_time1, self.p2_time2 = 60, 600
        self.index = 0
        self.music_list = ['雪国的记忆', '余烬', 'Still Alive', '栗コーダーカルテット - おじいさんの11ヶ月', '轻策昼间',
                           '死在旋转公寓', '骑士王的荣耀']
        """选中时的八条杠"""
        self.a1 = ttk.Label(self.game_canvas, background='#FF4500')
        self.a2 = ttk.Label(self.game_canvas, background='#FF4500')
        self.b1 = ttk.Label(self.game_canvas, background='#FF4500')
        self.b2 = ttk.Label(self.game_canvas, background='#FF4500')
        self.c1 = ttk.Label(self.game_canvas, background='#FF4500')
        self.c2 = ttk.Label(self.game_canvas, background='#FF4500')
        self.d1 = ttk.Label(self.game_canvas, background='#FF4500')
        self.d2 = ttk.Label(self.game_canvas, background='#FF4500')
        """音乐和音效"""
        pygame.mixer.init()
        self.chess_sound = pygame.mixer.Sound(r'.\\音乐\\落子.mp3')
        self.chess_sound.set_volume(1.0)
        pygame.mixer.music.load(r'.\\音乐\\雪国的记忆.ogg')
        pygame.mixer.music.set_volume(1)
        pygame.mixer.music.play(-1)
        self.hit = pygame.mixer.Sound(r'.\\音乐\\点击.wav')
        self.game_end = pygame.mixer.Sound(r'.\\音乐\\游戏结束.mp3')
        self.music = ttk.StringVar()
        self.music.set('ON')
        """游戏结束画面控件"""
        self.win_label = ttk.Label(self.chessboard, background='black', font=('华文新宋', 50), foreground='#40E0D0')
        """防守策略"""
        self.defense = [
                        [0, 0, 1, 1, 1, 1, 2], [1, 0, 1, 1, 1, 1, 2], [1, 0, 1, 1, 1, 2, 2], [1, 0, 1, 1, 1, 2, 0],
                        [2, 0, 1, 1, 1, 1, 2], [2, 0, 1, 1, 1, 1, 0], [1, 0, 1, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1, 0],
                        [2, 1, 1, 3, 1, 1, 2], [1, 1, 1, 3, 1, 1, 1], [0, 1, 1, 3, 1, 1, 0], [0, 1, 1, 3, 1, 1, 1],
                        [1, 1, 1, 3, 1, 1, 2], [1, 1, 1, 3, 1, 1, 0], [1, 1, 1, 3, 1, 2, 0], [1, 1, 1, 3, 1, 2, 1],
                        [1, 1, 1, 3, 1, 2, 2], [2, 1, 1, 3, 1, 1, 1], [1, 1, 1, 3, 1, 0, 2], [2, 0, 1, 3, 1, 1, 1],
                        [1, 1, 1, 3, 1, 0, 1], [1, 0, 1, 3, 1, 1, 1], [1, 2, 1, 3, 1, 1, 1], [1, 0, 1, 1, 1, 2, 1],
                        [0, 1, 1, 3, 1, 1, 2], [2, 1, 1, 3, 1, 1, 0]]

        self.defense1 = [[0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 2], [1, 0, 1, 1, 0, 2, 1], [1, 0, 1, 3, 1, 1, 0],
                         [0, 1, 1, 3, 1, 0, 0], [1, 0, 1, 1, 0, 2, 0], [1, 0, 1, 0, 1, 0, 0], [1, 0, 1, 0, 1, 0, 1],
                         [1, 0, 1, 0, 1, 0, 2], [0, 1, 1, 3, 1, 0, 0], [0, 0, 1, 3, 1, 1, 0], [1, 1, 1, 3, 0, 0, 0],
                         [0, 0, 0, 3, 1, 1, 1], [0, 0, 1, 3, 1, 1, 0]]

        self.defense2 = [[0, 1, 1, 3, 0, 0, 0], [0, 1, 1, 3, 0, 1, 2], [0, 1, 1, 3, 0, 1, 1], [0, 1, 1, 3, 0, 0, 2],
                         [0, 1, 1, 3, 0, 0, 1], [0, 0, 1, 1, 0, 0, 0], [0, 0, 1, 3, 1, 0, 0], [0, 0, 1, 3, 1, 0, 1],
                         [1, 0, 1, 3, 1, 0, 0], [0, 0, 1, 0, 1, 0, 2], [0, 0, 0, 3, 1, 1, 0], [2, 1, 0, 3, 1, 1, 0],
                         [1, 1, 0, 3, 1, 1, 0], [2, 0, 0, 3, 1, 1, 0], [1, 0, 0, 3, 1, 1, 0], [0, 0, 1, 0, 1, 0, 0]]

        self.defense3 = [[0, 0, 1, 3, 0, 0, 0], [0, 0, 1, 3, 0, 2, 1], [0, 0, 1, 3, 0, 2, 2], [0, 0, 1, 3, 0, 1, 1],
                         [0, 0, 1, 3, 0, 1, 2], [0, 0, 1, 3, 0, 0, 2], [0, 0, 1, 3, 0, 0, 1], [0, 0, 1, 0, 0, 0, 0],
                         [0, 0, 0, 3, 1, 0, 0], [1, 2, 0, 3, 1, 0, 0], [2, 2, 0, 3, 1, 0, 0], [0, 0, 1, 3, 0, 1, 1],
                         [2, 1, 0, 3, 1, 0, 0], [2, 0, 0, 3, 1, 0, 0], [1, 0, 0, 3, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0],
                         [1, 0, 0, 0, 0, 0, 0]]

        """进攻策略"""
        self.attack = [[0, 0, 2, 2, 2, 2, 0], [0, 0, 2, 2, 2, 2, 1], [1, 0, 2, 2, 2, 2, 0], [2, 0, 2, 2, 2, 2, 0],
                       [1, 0, 2, 2, 2, 2, 1], [2, 2, 2, 3, 2, 2, 2], [1, 2, 2, 3, 2, 2, 2], [2, 2, 2, 3, 2, 2, 1],
                       [1, 2, 2, 3, 2, 2, 1], [1, 2, 2, 3, 2, 2, 0], [0, 2, 2, 3, 2, 2, 1], [0, 2, 2, 3, 2, 2, 0],
                       [2, 2, 2, 3, 2, 1, 1], [2, 2, 2, 3, 2, 1, 0], [2, 2, 2, 3, 2, 0, 0], [0, 0, 2, 3, 2, 2, 2],
                       [1, 0, 2, 3, 2, 2, 2], [1, 1, 2, 3, 2, 2, 2]]

        self.attack1 = [[0, 0, 2, 2, 2, 0, 1], [0, 0, 2, 2, 2, 0, 0], [0, 0, 2, 3, 2, 2, 0], [0, 2, 2, 3, 2, 0, 0],
                        [0, 0, 2, 3, 2, 0, 2], [2, 0, 2, 3, 2, 0, 0], [1, 0, 2, 3, 2, 2, 0], [0, 2, 2, 3, 2, 0, 1],
                        [0, 2, 0, 3, 2, 2, 0], [0, 2, 2, 3, 0, 2, 0]]

        self.attack1_little = [[1, 0, 2, 3, 2, 0, 0], [0, 0, 2, 3, 2, 0, 1], [0, 2, 2, 3, 0, 0, 0],
                               [0, 0, 2, 3, 2, 0, 0]]

        self.attack2 = [[0, 0, 2, 2, 2, 1, 1], [0, 0, 2, 2, 2, 1, 2], [0, 0, 2, 2, 2, 1, 0], [0, 0, 2, 2, 0, 1, 2],
                        [1, 2, 0, 3, 2, 2, 0], [0, 0, 2, 3, 2, 0, 0], [0, 0, 2, 3, 0, 2, 2], [2, 2, 0, 3, 2, 0, 0],
                        [1, 0, 2, 3, 2, 0, 2], [2, 0, 2, 3, 2, 0, 1], [0, 2, 2, 3, 0, 1, 2], [0, 2, 2, 3, 0, 1, 0],
                        [0, 2, 2, 3, 0, 1, 1], [1, 1, 0, 3, 2, 2, 0], [2, 1, 0, 3, 2, 2, 0], [0, 1, 0, 3, 2, 2, 0],
                        [0, 0, 2, 2, 0, 0, 0], [0, 0, 2, 2, 0, 1, 1], [0, 0, 2, 2, 0, 0, 1], [0, 0, 2, 2, 0, 1, 0]]

        self.attack3 = [[0, 0, 2, 3, 0, 0, 0], [0, 0, 2, 3, 0, 0, 1], [0, 0, 2, 3, 0, 0, 2], [0, 0, 2, 0, 0, 1, 0],
                        [0, 0, 0, 3, 2, 0, 0], [1, 0, 0, 3, 2, 0, 0], [2, 0, 0, 3, 2, 0, 0], [0, 1, 0, 3, 2, 0, 0],
                        [2, 0, 0, 0, 0, 0, 0], [0, 0, 2, 0, 0, 0, 0]]
        """弃子策略"""
        self.leave = [[1, 0, 2, 3, 2, 0, 1], [0, 0, 2, 3, 0, 1, 2], [0, 0, 2, 3, 0, 1, 1], [0, 0, 2, 3, 0, 1, 0],
                      [0, 0, 2, 3, 0, 2, 1], [-1, 0, 0, 3, 2, 2, 2], [-1, 0, 0, 3, 1, 1, 1], [0, 0, 1, 1, 1, 2, 0],
                      [0, 0, 1, 1, 0, 1, 2], [1, 0, 1, 1, 0, 1, 2], [2, 0, 1, 1, 0, 1, 2], [1, 0, 2, 2, 1, 2, 2],
                      [2, 0, 1, 3, 1, 1, 0], [0, 1, 1, 3, 0, 1, 2], [0, 0, 1, 1, 1, 2, 1], [1, 0, 2, 2, 1, 0, 0],
                      [0, 0, 1, 1, 1, 2, 2], [2, 0, 1, 3, 1, 0, 0], [2, 0, 1, 1, 1, 2, 2], [2, 0, 1, 1, 1, 2, 1],
                      [0, 0, 2, 3, 0, 2, 1], [1, 2, 0, 3, 2, 0, 0], [0, 1, 2, 3, 2, 0, 0], [0, 0, 2, 3, 2, 1, 0],
                      [0, 0, 1, 1, 2, 0, 0], [0, 0, 2, 1, 0, 0, 0], [0, 0, 0, 3, 2, 1, 0],
                      [1, 0, 2, 2, 1, 0, 1], [1, 0, 2, 2, 1, 1, 1], [1, 0, 2, 2, 1, 1, 2],
                      [1, 0, 2, 2, 1, 2, 1], [0, 0, 0, 3, 2, 1, 1], [1, 1, 2, 3, 0, 0, 0]]

        self.login()
        self.root.mainloop()

    def login(self):
        for key in self.dic:
            self.dic[key] = {num: 0 for num in range(-2, 21)}

        self.login_canvas.place(x=0, y=0)
        self.login_canvas.create_image(0, 0, image=self.login_pic, anchor='nw')
        ((start_btn := ttk.Label(self.login_canvas, text='开始游戏', image=self.start_pic))
         .place(x=140, y=500, width=195, height=50))
        (ttk.Button(self.login_canvas, text='设置', style='outline-dark', command=lambda: self.set_frame())
         .place(x=140, y=570, width=195, height=50))
        start_btn.bind('<Button-1>', lambda event: self.mode_choice())

    def mode_choice(self):
        self.hit.play()
        self.mode_canvas.place(x=463)
        self.mode_canvas.create_image(0, 0, image=self.mode_pic, anchor='nw')
        (ttk.Button(self.mode_canvas, text='返回', style='outline-dark', command=lambda: self.slide())
         .place(x=140, y=400, width=195, height=50))
        (ttk.Button(self.mode_canvas, text='机机模式', style='outline-dark', command=lambda: self.cvc())
         .place(x=140, y=100, width=195, height=50))
        (ttk.Button(self.mode_canvas, text='人机对弈', style='outline-dark', command=lambda: self.pvc())
         .place(x=140, y=200, width=195, height=50))
        (ttk.Button(self.mode_canvas, text='双人模式', style='outline-dark', command=lambda: self.pvp())
         .place(x=140, y=300, width=195, height=50))
        self.slide()

    def win_frame(self, player):

        def music_stop(ind=0):
            if ind < 15:
                pygame.mixer.music.pause()
                self.root.after(100, music_stop, ind + 1)
            if ind == 15:
                pygame.mixer.music.play(-1)

        self.game_end.play()
        music_stop()
        self.game_canvas.create_image(460, 0, image=self.win_pic, anchor='nw')
        text = player + '\n  赢了!'
        self.win_label.configure(text=text)
        self.win_label.place(x=570, y=100)

    def set_frame(self):

        def com_change():
            cur_music = com.get()
            if cur_music == '雪国的记忆':
                self.index = 0
            elif cur_music == '余烬':
                self.index = 1
            elif cur_music == 'Still Alive':
                self.index = 2
            elif cur_music == '栗コーダーカルテット - おじいさんの11ヶ月':
                self.index = 3
            elif cur_music == '轻策昼间':
                self.index = 4
            elif cur_music == '死在旋转公寓':
                self.index = 5
            elif cur_music == '骑士王的荣耀':
                self.index = 6
            return cur_music

        ttk.Label(self.setting_frame, background='#B0C4DE').place(x=0, y=0, width=463, height=400)
        self.setting_frame.place(x=0, y=728, width=463, height=400)
        ttk.Label(self.setting_frame, text='设置步时', background='#B0C4DE', font=('楷体', 15)).place(x=80, y=20)
        ttk.Entry(self.setting_frame, textvariable=self.per_time).place(x=200, y=20)
        ttk.Label(self.setting_frame, text='设置局时', background='#B0C4DE', font=('楷体', 15)).place(x=80, y=70)
        ttk.Entry(self.setting_frame, textvariable=self.all_time).place(x=200, y=70)
        ttk.Label(self.setting_frame, text='音乐开关', background='#B0C4DE', font=('楷体', 15)).place(x=80, y=120)
        music_btn = ttk.Button(self.setting_frame, textvariable=self.music, style='outline',
                               command=lambda: self.music_switch())
        music_btn.place(x=200, y=120, width=195)
        ttk.Label(self.setting_frame, text='玩家一号名字', background='#B0C4DE', font=('楷体', 15)).place(x=40, y=170)
        ttk.Entry(self.setting_frame, textvariable=self.n1).place(x=200, y=170)
        ttk.Label(self.setting_frame, text='玩家二号名字', background='#B0C4DE', font=('楷体', 15)).place(x=40, y=220)
        ttk.Entry(self.setting_frame, textvariable=self.n2).place(x=200, y=220)
        ttk.Label(self.setting_frame, text='音乐选择', background='#B0C4DE', font=('楷体', 15)).place(x=80, y=270)
        com = ttk.Combobox(self.setting_frame)
        com.bind('<<ComboboxSelected>>', lambda event: com_change())
        com['value'] = ['雪国的记忆', '余烬', 'Still Alive', '栗コーダーカルテット - おじいさんの11ヶ月', '轻策昼间', '死在旋转公寓',
                        '骑士王的荣耀']
        com.current(self.index)
        com.place(x=200, y=270, width=195)
        (ttk.Button(self.setting_frame, text='确认\n更改', style='outline', command=lambda: self.confirm())
         .place(x=400, y=250, width=60, height=60))
        self.slide2()

    def music_switch(self):
        if self.music.get() == 'ON':
            self.hit.play()
            self.music.set('OFF')
            pygame.mixer.music.set_volume(0.0)
        else:
            self.hit.play()
            self.music.set('ON')
            pygame.mixer.music.set_volume(0.5)

    def confirm(self):
        self.hit.play()
        self.setting_frame.place(x=0, y=728, width=463, height=350)
        self.p1_time1 = self.p2_time1 = self.per_time.get()
        self.p2_time2 = self.p2_time2 = self.all_time.get()
        self.per_time.set(self.p1_time1)
        self.all_time.set(self.p2_time2)
        self.name1 = self.n1.get()
        self.name2 = self.n2.get()
        self.n1.set(self.name1)
        self.n2.set(self.name2)

        if self.index == 0:
            pygame.mixer.music.load(r'.\\音乐\\雪国的记忆.ogg')
            pygame.mixer.music.set_volume(1)
            pygame.mixer.music.play(-1)

        elif self.index == 1:
            pygame.mixer.music.load(r'.\\音乐\\余烬.ogg')
            pygame.mixer.music.set_volume(0.3)
            pygame.mixer.music.play(-1)
        elif self.index == 2:
            pygame.mixer.music.load(r'.\\音乐\\StillAlive.ogg')
            pygame.mixer.music.set_volume(1)
            pygame.mixer.music.play(-1)
        elif self.index == 3:
            pygame.mixer.music.load(r'.\\音乐\\栗コーダーカルテット - おじいさんの11ヶ月.ogg')
            pygame.mixer.music.set_volume(0.7)
            pygame.mixer.music.play(-1)
        elif self.index == 4:
            pygame.mixer.music.load(r'.\\音乐\\轻策昼间.ogg')
            pygame.mixer.music.set_volume(0.5)
            pygame.mixer.music.play(-1)
        elif self.index == 5:
            pygame.mixer.music.load(r'.\\音乐\\死在旋转公寓.ogg')
            pygame.mixer.music.set_volume(1)
            pygame.mixer.music.play(-1)
        elif self.index == 6:
            pygame.mixer.music.load(r'.\\音乐\\骑士王的荣耀.ogg')
            pygame.mixer.music.set_volume(1)
            pygame.mixer.music.play(-1)

    def forget(self):
        self.win_label.place_forget()

    def again(self):
        self.hit.play()
        self.forget()

        self.flag = False
        if self.game_mode == 'pvc':
            self.pvc()
        elif self.game_mode == 'pcp':
            self.pvp()
        elif self.game_mode == 'cvc':
            self.cvc()

    def back(self):
        self.hit.play()
        self.forget()
        self.game_canvas.place_forget()

    def slide(self, ind=0):
        move_list = [1, 1, 2, 2, 4, 5, 5, 5, 8, 9, 11, 11, 9, 8, 5, 5, 5, 4, 2, 2]
        self.mode_canvas.place(x=int(self.mode_canvas.place_info()['x']) + -1 * 4.5 * move_list[ind])
        if ind < 19:
            self.root.after(5, self.slide, ind + 1)

    def slide2(self, ind=0):
        move_list = [2, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9, 8, 5, 5, 5, 4, 3, 2]
        self.setting_frame.place(y=int(self.setting_frame.place_info()['y']) + -1 * 3.7 * move_list[ind])
        if ind < 17:
            self.root.after(5, self.slide2, ind + 1)

    def cvc(self):
        self.flag = False
        self.forget()
        self.hit.play()
        self.game_mode = 'cvc'
        self.build()

    def pvc(self):
        self.flag = False
        self.forget()
        self.hit.play()
        self.game_mode = 'pvc'
        self.build()

    def pvp(self):
        self.flag = False
        self.forget()
        self.hit.play()
        self.game_mode = 'pvp'
        self.build()

    def build(self):
        def initialize():
            self.count = 1
            self.color = 'black'
            for key in self.dic:
                self.dic[key] = {num: 0 for num in range(-2, 21)}

        def xy(event):
            if 310 < event.x < 1150 and 20 < event.y < 860 and self.flag is False:
                x_count = round((event.x - 325) / 45)
                y_count = round((event.y - 35) / 45)
                if self.dic[y_count][x_count] == 0:
                    x = 325 + x_count * 45
                    y = 35 + y_count * 45
                    self.a1.place(x=x-18, y=y-14, width=14, height=2)
                    self.a2.place(x=x-4, y=y-27, width=2, height=14)
                    self.b1.place(x=x+10, y=y-14, width=14, height=2)
                    self.b2.place(x=x+10, y=y-27, width=2, height=14)
                    self.c1.place(x=x-18, y=y-1, width=14, height=2)
                    self.c2.place(x=x-4, y=y-1, width=2, height=14)
                    self.d1.place(x=x+10, y=y-1, width=14, height=2)
                    self.d2.place(x=x+10, y=y-1, width=2, height=14)

        def click(event):
            if 310 < event.x < 1150 and 20 < event.y < 860 and self.flag is False:
                x_count = round((event.x - 325) / 45)
                y_count = round((event.y - 35) / 45)
                x = 325 + x_count * 45
                y = 35 + y_count * 45
                radius = 20
                if self.dic[y_count][x_count] == 0:
                    self.color = 'black' if self.count % 2 == 1 else 'white'
                    self.dic[y_count][x_count] = 1 if self.color == 'black' else 2
                    self.game_canvas.create_oval(x - radius, y - radius, x + radius, y + radius, fill=self.color)
                    self.game_canvas.update_idletasks()
                    self.count += 1
                    self.chess_sound.play()
                    win(self.color, (y_count, x_count))
                    self.color = 'black' if self.count % 2 == 1 else 'white'

                def stop(ind=0):
                    if ind < 120:
                        ind += 1

                        self.root.after(10, stop, ind)
                    else:
                        ai_judge()

                if self.game_mode == 'pvc' and self.flag is False:
                    stop()

        def win(player, position: tuple):  # 参数player: 1 : O ; 2 : X
            sign = 1 if player == 'black' else 2
            a, b = position

            def judge_x_y(row, column, value1, value2):
                count = 1
                copy_row = row
                copy_column = column
                for _ in range(4):
                    row += value1
                    column -= value2
                    if self.dic[row][column] == sign:
                        count += 1
                    else:
                        break
                column, row = copy_column, copy_row
                for _ in range(4):
                    row -= value1
                    column += value2
                    if self.dic[row][column] == sign:
                        count += 1
                    else:
                        break
                if count >= 5:
                    self.flag = True
                    return True

            def judge_slash(row, column, value1, value2):
                count = 1
                copy_row, copy_column = row, column
                for _ in range(4):
                    row += value1
                    column -= value2
                    if self.dic[row][column] == sign:
                        count += 1
                    else:
                        break
                row, column = copy_row, copy_column
                for _ in range(4):
                    row -= value1
                    column += value2
                    if self.dic[row][column] == sign:
                        count += 1
                    else:
                        break
                if count >= 5:
                    return True

            if (judge_x_y(a, b, 0, 1) or judge_x_y(a, b, 1, 0)
                    or judge_slash(a, b, 1, value2=-1) or judge_slash(a, b, 1, 1)):
                win_player = '黑棋玩家' if sign == 1 else '白棋玩家'
                self.win_frame(win_player)
                self.flag = True
                self.a1.place_forget()
                self.a2.place_forget()
                self.b1.place_forget()
                self.b2.place_forget()
                self.c1.place_forget()
                self.c2.place_forget()
                self.d1.place_forget()
                self.d2.place_forget()
                return True

        def time_p1(current_time1=self.p1_time1, current_time2=self.p2_time2):
            if not self.flag:
                self.color = 'black' if self.count % 2 == 1 else 'white'
                if self.color == 'black':
                    if current_time1 <= 0 or current_time2 <= 0:
                        self.win_frame('黑棋超时\n白棋玩家')
                        self.flag = True
                    self.game_canvas.itemconfig(player_1_t1, text=current_time1)
                    self.game_canvas.itemconfig(player_1_t2, text=current_time2)
                    self.root.after(1000, time_p1, current_time1 - 1, current_time2 - 1)
                else:
                    self.root.after(10, time_p1, self.p1_time1, current_time2)

        def time_p2(current_time1=self.p2_time1, current_time2=self.p2_time2):
            if not self.flag:
                self.color = 'black' if self.count % 2 == 1 else 'white'
                if self.color == 'white':
                    if current_time1 <= 0 or current_time2 <= 0:
                        self.win_frame('白棋超时\n黑棋玩家')
                        self.flag = True
                    self.game_canvas.itemconfig(player_2_t1, text=current_time1)
                    self.game_canvas.itemconfig(player_2_t2, text=current_time2)
                    self.root.after(1000, time_p2, current_time1-1, current_time2-1)
                else:
                    self.root.after(10, time_p2, self.p2_time1, current_time2)

        def ai_judge():  # 决定AI下在哪里
            value_dic = {}
            for row in range(0, 19):
                for column in range(0, 19):
                    temp_list = []
                    if self.dic[row][column] == 0:
                        temp_list.append(row_value(row, column, 0, 1))  # x轴
                        temp_list.append(row_value(row, column, 1, 0))  # y轴
                        temp_list.append(slash_value(row, column, -1, 1))  # 右斜
                        temp_list.append(slash_value(row, column, 1, 1))  # 左斜

                        value_dic[(row, column)] = max(temp_list)
            arr = list(value_dic.items())
            arr.sort(key=lambda x: x[1], reverse=True)
            if arr:
                ai_round(arr[0][0])

        def ai_round(position):

            x = 325 + position[1] * 45
            y = 35 + position[0] * 45
            radius = 20
            self.color = 'black' if self.count % 2 == 1 else 'white'
            self.dic[position[0]][position[1]] = 1 if self.color == 'black' else 2
            self.count += 1
            self.game_canvas.create_oval(x - radius, y - radius, x + radius, y + radius, fill=self.color)
            self.chess_sound.play()
            win(self.color, (position[0], position[1]))
            self.color = 'black' if self.count % 2 == 1 else 'white'

        def row_value(row, column, value1, value2):
            left_list, right_list = [], []
            copy_row = row
            copy_column = column
            if value1 == 0:
                left_list.append(self.dic[row][column + 1])
                right_list.append(self.dic[row][column - 1])
            else:
                left_list.append(self.dic[row + 1][column])
                right_list.append(self.dic[row - 1][column])
            for _ in range(6):
                if -2 <= row <= 20 and -2 <= column <= 20:
                    right_list.append(self.dic[row][column])
                    row += value1
                    column += value2
            column, row = copy_column, copy_row
            for _ in range(6):
                if -2 <= row <= 20 and -2 <= column <= 20:
                    left_list.append(self.dic[row][column])
                    row -= value1
                    column -= value2
            while len(left_list) < 7:
                left_list.append(-1)
            while len(right_list) < 7:
                right_list.append(-1)
            mix_list = [*left_list[4: 1: -1], 3, *right_list[2: 5]]
            row, column = copy_row, copy_column
            if row == 9 and column == 6:
                print(left_list, right_list, mix_list)
            sum_value = value_judge(left_list) + value_judge(right_list) + value_judge(mix_list)
            return sum_value

        def slash_value(row, column, value1, value2):

            value_list, left_list, right_list = [], [], []
            copy_row, copy_column = row, column
            if value1 == -1:
                left_list.append(self.dic[row + 1][column + 1])
                right_list.append(self.dic[row - 1][column - 1])
            else:
                left_list.append(self.dic[row - 1][column + 1])
                right_list.append(self.dic[row + 1][column - 1])
            for _ in range(6):
                if -2 <= row <= 20 and -2 <= column < 20:
                    right_list.append(self.dic[row][column])
                    row -= value1
                    column += value2
            row, column = copy_row, copy_column
            for _ in range(6):
                if -2 <= row <= 20 and -2 <= column <= 20:
                    left_list.append(self.dic[row][column])
                    row += value1
                    column -= value2
            while len(left_list) < 7:
                left_list.append(-1)
            while len(right_list) < 7:
                right_list.append(-1)
            mix_list = [*left_list[4: 1: -1], 3, *right_list[2: 5]]
            row, column = copy_row, copy_column
            if row == 9 and column == 6:
                print(left_list, right_list, mix_list)
            sum_value = value_judge(left_list) + value_judge(right_list) + value_judge(mix_list)
            return sum_value

        def value_judge(arr):
            value = -1000
            if arr in self.leave:
                value = -50000
                return value
            if arr in self.defense:
                value = 9999999999
            if arr in self.attack:
                value = 100000000000
            if arr in self.defense1:
                value = 5000
            if arr in self.attack1:
                value = 4000
            if arr in self.attack1_little:
                value = 3000
            if arr in self.attack2:
                value = 2000
            if arr in self.defense2:
                value = 1500
            if arr in self.defense3:
                value = 900
            if arr in self.attack3:
                value = 800

            for num in arr[1: 4]:
                if num == 2:
                    value += 50
                elif num == 1:
                    value += 1
            return value

        def cvc():
            if not self.flag and self.game_mode == 'cvc':
                ai_judge()
                self.root.after(100, cvc)

        initialize()
        self.chessboard.geometry('1450x880+463+50')
        self.chessboard.resizable(False, False)
        self.game_canvas.place(x=0, y=0)
        self.game_canvas.create_image(0, 0, image=self.background_pic, anchor='nw')
        self.game_canvas.create_image(300, 10, image=self.chess_board_pic, anchor='nw')
        if self.game_mode != 'cvc':
            self.game_canvas.create_text(65, 320, text='步时:', anchor='nw', font=('楷体', 20))
            player_1_t1 = self.game_canvas.create_text(160, 320, text=self.p1_time1, anchor='nw', font=('楷体', 20))
            self.game_canvas.create_text(65, 380, text='局时:', anchor='nw', font=('楷体', 20))
            player_1_t2 = self.game_canvas.create_text(160, 380, text=self.p1_time2, anchor='nw', font=('楷体', 20))

            self.game_canvas.create_text(1225, 320, text='步时:', anchor='nw', font=('楷体', 20))
            player_2_t1 = self.game_canvas.create_text(1320, 320, text=self.p2_time1, anchor='nw', font=('楷体', 20))
            self.game_canvas.create_text(1225, 380, text='局时:', anchor='nw', font=('楷体', 20))
            player_2_t2 = self.game_canvas.create_text(1320, 380, text=self.p2_time2, anchor='nw', font=('楷体', 20))

        if self.game_mode == 'pvc':
            self.game_canvas.create_image(50, 50, image=self.player1_pic, anchor='nw')
            self.game_canvas.create_text(65, 260, text=self.name1, anchor='nw', font=('楷体', 20))
            self.game_canvas.create_image(1210, 50, image=self.computer_pic, anchor='nw')
            c_name = random.choice(self.prefix) + '电脑'
            self.game_canvas.create_text(1180, 260, text=c_name, anchor='nw', font=('楷体', 20))
        if self.game_mode == 'pvp':
            self.game_canvas.create_image(50, 50, image=self.player1_pic, anchor='nw')
            self.game_canvas.create_text(65, 260, text=self.name1, anchor='nw', font=('楷体', 20))
            self.game_canvas.create_image(1210, 50, image=self.player2_pic, anchor='nw')
            self.game_canvas.create_text(1225, 260, text=self.name2, anchor='nw', font=('楷体', 20))
        if self.game_mode == 'cvc':
            c1_name = random.choice(self.prefix) + '电脑'
            c2_name = random.choice(self.prefix) + '电脑'
            self.game_canvas.create_image(50, 50, image=self.computer_pic, anchor='nw')
            self.game_canvas.create_text(30, 260, text=c1_name, anchor='nw', font=('楷体', 20))
            self.game_canvas.create_image(1210, 50, image=self.computer_pic, anchor='nw')
            self.game_canvas.create_text(1190, 260, text=c2_name, anchor='nw', font=('楷体', 20))
            x1 = 325 + 9 * 45
            y1 = 35 + 9 * 45
            radius1 = 20
            self.game_canvas.create_oval(x1 - radius1, y1 - radius1, x1 + radius1, y1 + radius1, fill=self.color)
            self.count += 1
            cvc()

        if self.game_mode != 'cvc':
            self.game_canvas.bind('<Motion>', xy)
            self.game_canvas.bind('<Button-1>', click)

        if self.game_mode != 'cvc':
            time_p1()
            time_p2()


if __name__ == '__main__':
    WuZiQi()

;