【Python】利用tkinter开发AI对战井字棋游戏

简介: 【Python】利用tkinter开发AI对战井字棋游戏

1 前言


在学习tkinter时打算开发一款井字棋游戏,之前试过利用pygame开发【利用pygame开发井字棋博客】。但是这个项目没有嵌入AI智能对战,只能由两个玩家操作。正好借此机会利用tkinter开发对战界面,并嵌入AI对战。

游戏界面如下:



为了读者对游戏由更好的了解,这里放操作视频:

image.png

20220813_105943

为方便游玩,我利用pyinstaller打包了代码至exe文件可以让所有用户安装游玩!exe下载地址:软件下载

若仅仅想获取代码,本文的代码就是全部代码,可放心使用!


2 代码分模块介绍


2.1 导入需要的库


分别是tkinter 、random

from tkinter import *
import tkinter.messagebox as msq
import random


2.2 定义全局变量


这里定义了窗体大小,窗体标题以及九个可落子位置的序号和变量值。

def __init__(self, master=None):
        self.root = master  # 定义内部变量root
        self.root.title("井字棋")
        self.root.geometry('%dx%d' % (600, 400))  # 设置窗口大小
        self.panels = ["panel"]*10
        self.count = 0
        self.digits = [1, 2, 3, 4, 5, 6, 7, 8, 9]
        self.mark = ""
        self.btn_text1 = StringVar()
        self.btn_text2 = StringVar()
        self.btn_text3 = StringVar()
        self.btn_text4 = StringVar()
        self.btn_text5 = StringVar()
        self.btn_text6 = StringVar()
        self.btn_text7 = StringVar()
        self.btn_text8 = StringVar()
        self.btn_text9 = StringVar()
        self.computerLetter = "O"
        self.createPage()


2.3 定义玩家类


def read_name(self):
        return [0,"玩家"]
    def read_choose(self):
        return "X"


2.4 定义页面类


利用gird对页面进行合理的分布,下子的方框实则是button,利用command对button进行动态改变

def createPage(self):
        self.page = Frame(self.root)  # 创建Frame
        self.page.pack()
        Label(self.page, text="{0},您选择的棋子是{1},您为先手".format(self.read_name()[1], self.read_choose())).grid(row=0, stick=W, pady=10)
        button1 = Button(self.page, textvariable=self.btn_text1, width=10, font=('Times 16 bold'), height=3, command=lambda:self.update_btn_text(1))
        button1.grid(row=1, column=1)
        button2 = Button(self.page, textvariable=self.btn_text2, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(2))
        button2.grid(row=1, column=2)
        button3 = Button(self.page, textvariable=self.btn_text3, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(3))
        button3.grid(row=1, column=3)
        button4 = Button(self.page, textvariable=self.btn_text4, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(4))
        button4.grid(row=2, column=1)
        button5 = Button(self.page, textvariable=self.btn_text5, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(5))
        button5.grid(row=2, column=2)
        button6 = Button(self.page, textvariable=self.btn_text6, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(6))
        button6.grid(row=2, column=3)
        button7 = Button(self.page, textvariable=self.btn_text7, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(7))
        button7.grid(row=3, column=1)
        button8 = Button(self.page, textvariable=self.btn_text8, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(8))
        button8.grid(row=3, column=2)
        button9 = Button(self.page, textvariable=self.btn_text9, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(9))
        button9.grid(row=3, column=3)


2.5 定义页面变化类以及玩家与AI轮流转换下子权限


def update_btn_text(self, digit):
        playerLetter = self.read_choose()
        if playerLetter == "X":
            self.computerLetter == "O"
        else:
            self.computerLetter = "X"
        if digit == 1 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text1.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 2 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text2.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 3 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text3.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 4 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text4.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 5 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text5.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 6 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text6.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 7 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text7.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 8 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text8.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 9 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text9.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if (len(self.digits) == 1 and self.win(self.panels, 'X') == False and self.win(self.panels, 'O') == False):
            self.page.destroy()
            msq.showinfo("RESULT", "平局")


2.6 定义判断胜负类


def win(self, panels, sign):
        return ((panels[1] == panels[2] == panels[3] == sign)
                or (panels[1] == panels[4] == panels[7] == sign)
                or (panels[1] == panels[5] == panels[9] == sign)
                or (panels[2] == panels[5] == panels[8] == sign)
                or (panels[3] == panels[6] == panels[9] == sign)
                or (panels[3] == panels[5] == panels[7] == sign)
                or (panels[4] == panels[5] == panels[6] == sign)
                or (panels[7] == panels[8] == panels[9] == sign))


2.7 定义智能AI下子类

def computer_move(self, panels, digits, computerLetter ,playerLetter):
        panelscopy = panels.copy()
        next_step1 = 0
        for i in digits:
            panelscopy[i] = computerLetter
            if (self.win(panelscopy, computerLetter)):
                next_step1 = i
                break
            panelscopy = panels.copy()
        panelscopy = panels.copy()
        for i in digits:
            panelscopy[i] = playerLetter
            if (self.win(panelscopy, playerLetter)):
                next_step2 = i
                break
            else:
                next_step2 = random.choice(digits)
            panelscopy = panels.copy()
        if next_step1 == 0:
            next_step = next_step2
        elif next_step1 != 0:
            next_step = next_step1
        digits.remove(next_step)
        panels[next_step] = computerLetter
        if next_step == 1:
            self.btn_text1.set(computerLetter)
        elif next_step == 2:
            self.btn_text2.set(computerLetter)
        elif next_step == 3:
            self.btn_text3.set(computerLetter)
        elif next_step == 4:
            self.btn_text4.set(computerLetter)
        elif next_step == 5:
            self.btn_text5.set(computerLetter)
        elif next_step == 6:
            self.btn_text6.set(computerLetter)
        elif next_step == 7:
            self.btn_text7.set(computerLetter)
        elif next_step == 8:
            self.btn_text8.set(computerLetter)
        elif next_step == 9:
            self.btn_text9.set(computerLetter)
        if (self.win(panels, computerLetter)):
            self.page.destroy()
            msq.showinfo("RESULT", "AI获胜")


3 整体代码展示(可直接使用!)


# -*- coding: utf-8 -*-
from tkinter import *
import tkinter.messagebox as msq
import random
class fupage2_play(object):
    def __init__(self, master=None):
        self.root = master  # 定义内部变量root
        self.root.title("井字棋")
        self.root.geometry('%dx%d' % (600, 400))  # 设置窗口大小
        self.panels = ["panel"]*10
        self.count = 0
        self.digits = [1, 2, 3, 4, 5, 6, 7, 8, 9]
        self.mark = ""
        self.btn_text1 = StringVar()
        self.btn_text2 = StringVar()
        self.btn_text3 = StringVar()
        self.btn_text4 = StringVar()
        self.btn_text5 = StringVar()
        self.btn_text6 = StringVar()
        self.btn_text7 = StringVar()
        self.btn_text8 = StringVar()
        self.btn_text9 = StringVar()
        self.computerLetter = "O"
        self.createPage()
    def read_name(self):
        return [0,"玩家"]
    def read_choose(self):
        return "X"
    def createPage(self):
        self.page = Frame(self.root)  # 创建Frame
        self.page.pack()
        Label(self.page, text="{0},您选择的棋子是{1},您为先手".format(self.read_name()[1], self.read_choose())).grid(row=0, stick=W, pady=10)
        button1 = Button(self.page, textvariable=self.btn_text1, width=10, font=('Times 16 bold'), height=3, command=lambda:self.update_btn_text(1))
        button1.grid(row=1, column=1)
        button2 = Button(self.page, textvariable=self.btn_text2, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(2))
        button2.grid(row=1, column=2)
        button3 = Button(self.page, textvariable=self.btn_text3, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(3))
        button3.grid(row=1, column=3)
        button4 = Button(self.page, textvariable=self.btn_text4, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(4))
        button4.grid(row=2, column=1)
        button5 = Button(self.page, textvariable=self.btn_text5, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(5))
        button5.grid(row=2, column=2)
        button6 = Button(self.page, textvariable=self.btn_text6, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(6))
        button6.grid(row=2, column=3)
        button7 = Button(self.page, textvariable=self.btn_text7, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(7))
        button7.grid(row=3, column=1)
        button8 = Button(self.page, textvariable=self.btn_text8, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(8))
        button8.grid(row=3, column=2)
        button9 = Button(self.page, textvariable=self.btn_text9, width=10, height=3, font=('Times 16 bold'), command=lambda:self.update_btn_text(9))
        button9.grid(row=3, column=3)
    def update_btn_text(self, digit):
        playerLetter = self.read_choose()
        if playerLetter == "X":
            self.computerLetter == "O"
        else:
            self.computerLetter = "X"
        if digit == 1 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text1.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 2 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text2.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 3 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text3.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 4 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text4.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 5 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text5.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 6 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text6.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 7 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text7.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 8 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text8.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if digit == 9 and digit in self.digits:
            self.digits.remove(digit)
            self.panels[digit] = playerLetter
            self.btn_text9.set(playerLetter)
            if (self.win(self.panels, playerLetter)):
                self.page.destroy()
                msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))
            else:
                self.computer_move(self.panels, self.digits, self.computerLetter, playerLetter)
        if (len(self.digits) == 1 and self.win(self.panels, 'X') == False and self.win(self.panels, 'O') == False):
            self.page.destroy()
            msq.showinfo("RESULT", "平局")
    def win(self, panels, sign):
        return ((panels[1] == panels[2] == panels[3] == sign)
                or (panels[1] == panels[4] == panels[7] == sign)
                or (panels[1] == panels[5] == panels[9] == sign)
                or (panels[2] == panels[5] == panels[8] == sign)
                or (panels[3] == panels[6] == panels[9] == sign)
                or (panels[3] == panels[5] == panels[7] == sign)
                or (panels[4] == panels[5] == panels[6] == sign)
                or (panels[7] == panels[8] == panels[9] == sign))
    def computer_move(self, panels, digits, computerLetter ,playerLetter):
        panelscopy = panels.copy()
        next_step1 = 0
        for i in digits:
            panelscopy[i] = computerLetter
            if (self.win(panelscopy, computerLetter)):
                next_step1 = i
                break
            panelscopy = panels.copy()
        panelscopy = panels.copy()
        for i in digits:
            panelscopy[i] = playerLetter
            if (self.win(panelscopy, playerLetter)):
                next_step2 = i
                break
            else:
                next_step2 = random.choice(digits)
            panelscopy = panels.copy()
        if next_step1 == 0:
            next_step = next_step2
        elif next_step1 != 0:
            next_step = next_step1
        digits.remove(next_step)
        panels[next_step] = computerLetter
        if next_step == 1:
            self.btn_text1.set(computerLetter)
        elif next_step == 2:
            self.btn_text2.set(computerLetter)
        elif next_step == 3:
            self.btn_text3.set(computerLetter)
        elif next_step == 4:
            self.btn_text4.set(computerLetter)
        elif next_step == 5:
            self.btn_text5.set(computerLetter)
        elif next_step == 6:
            self.btn_text6.set(computerLetter)
        elif next_step == 7:
            self.btn_text7.set(computerLetter)
        elif next_step == 8:
            self.btn_text8.set(computerLetter)
        elif next_step == 9:
            self.btn_text9.set(computerLetter)
        if (self.win(panels, computerLetter)):
            self.page.destroy()
            msq.showinfo("RESULT", "AI获胜")
if __name__ == "__main__":
    root = Tk()
    root.title('井字棋')
    fupage2_play(root)
    root.mainloop()

最后展现界面:

相关文章
|
22天前
|
人工智能 小程序
一步步开发AI运动小程序】二、引入插件
随着人工智能技术的发展,阿里体育等公司推出的“乐动力”、“天天跳绳”等AI运动APP广受欢迎。本文将引导您从零开始开发一个AI运动小程序,使用“云智AI运动识别小程序插件”。内容包括新建uni-app项目、配置插件、部署模型、安装依赖包、全局初始化和调用插件对象。
|
2天前
|
人工智能 安全 测试技术
探索AI在软件开发中的应用:提升开发效率与质量
【10月更文挑战第31天】在快速发展的科技时代,人工智能(AI)已成为软件开发领域的重要组成部分。本文探讨了AI在代码生成、缺陷预测、自动化测试、性能优化和CI/CD中的应用,以及这些应用如何提升开发效率和产品质量。同时,文章也讨论了数据隐私、模型可解释性和技术更新等挑战。
|
8天前
|
数据可视化 开发者 Python
Python GUI开发:Tkinter与PyQt的实战应用与对比分析
【10月更文挑战第26天】本文介绍了Python中两种常用的GUI工具包——Tkinter和PyQt。Tkinter内置于Python标准库,适合初学者快速上手,提供基本的GUI组件和方法。PyQt基于Qt库,功能强大且灵活,适用于创建复杂的GUI应用程序。通过实战示例和对比分析,帮助开发者选择合适的工具包以满足项目需求。
40 7
|
7天前
|
人工智能 C语言 Python
AI师傅+通义灵码=零基础小白上手python真·不是梦
作为一名不懂编程的设计师,我一直渴望掌握AI辅助设计。在快刀青衣的推荐下,我尝试了AI师傅和通义灵码,成功写出了第一个Python程序,并理解了编程的基本概念。通过AI师傅的引导和通义灵码的帮助,我顺利完成了Coursera上的Python课程,获得了两张证书。这种学习方式让编程变得不再遥不可及,为我的未来学习打开了新大门。
|
8天前
|
人工智能 小程序
【一步步开发AI运动小程序】五、帧图像人体识别
随着AI技术的发展,阿里体育等公司推出的AI运动APP,如“乐动力”和“天天跳绳”,使云上运动会、线上健身等概念广受欢迎。本文将引导您从零开始开发一个AI运动小程序,使用“云智AI运动识别小程序插件”。文章分为四部分:初始化人体识别功能、调用人体识别功能、人体识别结果处理以及识别结果旋转矫正。下篇将继续介绍人体骨骼图绘制。
|
8天前
|
人工智能 小程序 vr&ar
AI运动小程序开发常见问题集锦二
截至当前,我们的AI运动识别小程序插件已迭代至第23个版本,广泛应用于健身、体育、体测、AR互动等场景。本文针对近期用户咨询,汇总了常见问题,帮助用户减少开发成本,提高效率。主要涵盖计时与计数模式的区别、综合排行榜生成方法、全屏模式适配及无开发能力用户的解决方案。
|
19天前
|
人工智能 编解码 小程序
【一步步开发AI运动小程序】四、小程序如何抽帧
随着AI技术的发展,阿里体育等公司推出的“乐动力”、“天天跳绳”等APP使云上运动会、线上健身等概念备受关注。本文将引导您从零开始开发一个AI运动小程序,利用“云智AI运动识别小程序插件”。文中详细介绍了微信小程序抽帧的相关API、设置及注意事项,帮助开发者更好地实现AI运动功能。下篇将介绍人体识别技术,敬请期待。
|
21天前
|
机器学习/深度学习 人工智能 监控
利用AI进行代码审查:提升代码质量和开发效率
【10月更文挑战第12天】本文探讨了AI在代码审查中的应用及其优势,介绍了AI辅助代码审查工具如何通过自动化和持续学习提升代码质量和开发效率。文章还提供了实施AI辅助代码审查的具体步骤和实战技巧,帮助团队更好地利用这些工具。
|
21天前
|
人工智能
添加一个Stable Difussion图像生成应用,通过向AI助手简单的提问,即可快速搭建Stable Diffusion应用至自己的网站中,大幅提升开发效率。
添加一个Stable Difussion图像生成应用,通过向AI助手简单的提问,即可快速搭建Stable Diffusion应用至自己的网站中,大幅提升开发效率。
|
21天前
|
存储 人工智能 NoSQL
使用 MongoDB 构建 AI:Gradient Accelerator Block 如何在几秒钟内让您从零开发 AI
借助 MongoDB,开发者可以存储任何结构的数据,然后使用单一查询 API 和驱动程序将这些数据用于 OLTP、文本搜索和向量搜索处理。