1 前言
在学习tkinter时打算开发一款井字棋游戏,之前试过利用pygame开发【利用pygame开发井字棋博客】。但是这个项目没有嵌入AI智能对战,只能由两个玩家操作。正好借此机会利用tkinter开发对战界面,并嵌入AI对战。
游戏界面如下:
为了读者对游戏由更好的了解,这里放操作视频:
0813_105943
为方便游玩,我利用pyinstaller打包了代码至exe文件可以让所有用户安装游玩!exe下载地址:软件下载
若仅仅想获取代码,本文的代码就是全部代码,可放心使用!
2 代码分模块介绍
2.1 导入需要的库
分别是tkinter 、random
from tkinter import *import tkinter.messagebox as msqimport random
2.2 定义全局变量
这里定义了窗体大小,窗体标题以及九个可落子位置的序号和变量值。
def __init__(self, master=None):self.root = master # 定义内部变量rootself.root.title("井字棋")self.root.geometry('%dx%d' % (600, 400)) # 设置窗口大小self.panels = ["panel"]*10self.count = 0self.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()puterLetter = "O"self.createPage()
2.2 定义玩家类
def read_name(self):return [0,"玩家"]def read_choose(self):return "X"
2.3 定义页面类
利用gird对页面进行合理的分布,下子的方框实则是button,利用command对button进行动态改变
def createPage(self):self.page = Frame(self.root) # 创建Frameself.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.4 定义页面变化类以及玩家与AI轮流转换下子权限
def update_btn_text(self, digit):playerLetter = self.read_choose()if playerLetter == "X":puterLetter == "O"else:puterLetter = "X"if digit == 1 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text1.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 2 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text2.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 3 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text3.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 4 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text4.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 5 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text5.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 6 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text6.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 7 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text7.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 8 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text8.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 9 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text9.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, 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.5 定义判断胜负类
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.6 定义智能AI下子类
def computer_move(self, panels, digits, computerLetter ,playerLetter):panelscopy = panels.copy()next_step1 = 0for i in digits:panelscopy[i] = computerLetterif (self.win(panelscopy, computerLetter)):next_step1 = ibreakpanelscopy = panels.copy()panelscopy = panels.copy()for i in digits:panelscopy[i] = playerLetterif (self.win(panelscopy, playerLetter)):next_step2 = ibreakelse:next_step2 = random.choice(digits)panelscopy = panels.copy()if next_step1 == 0:next_step = next_step2elif next_step1 != 0:next_step = next_step1digits.remove(next_step)panels[next_step] = computerLetterif 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 msqimport randomclass fupage2_play(object):def __init__(self, master=None):self.root = master # 定义内部变量rootself.root.title("井字棋")self.root.geometry('%dx%d' % (600, 400)) # 设置窗口大小self.panels = ["panel"]*10self.count = 0self.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()puterLetter = "O"self.createPage()def read_name(self):return [0,"玩家"]def read_choose(self):return "X"def createPage(self):self.page = Frame(self.root) # 创建Frameself.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":puterLetter == "O"else:puterLetter = "X"if digit == 1 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text1.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 2 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text2.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 3 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text3.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 4 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text4.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 5 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text5.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 6 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text6.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 7 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text7.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 8 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text8.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, playerLetter)if digit == 9 and digit in self.digits:self.digits.remove(digit)self.panels[digit] = playerLetterself.btn_text9.set(playerLetter)if (self.win(self.panels, playerLetter)):self.page.destroy()msq.showinfo("RESULT", "{},你获胜!".format(self.read_name()[1]))else:puter_move(self.panels, self.digits, puterLetter, 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 = 0for i in digits:panelscopy[i] = computerLetterif (self.win(panelscopy, computerLetter)):next_step1 = ibreakpanelscopy = panels.copy()panelscopy = panels.copy()for i in digits:panelscopy[i] = playerLetterif (self.win(panelscopy, playerLetter)):next_step2 = ibreakelse:next_step2 = random.choice(digits)panelscopy = panels.copy()if next_step1 == 0:next_step = next_step2elif next_step1 != 0:next_step = next_step1digits.remove(next_step)panels[next_step] = computerLetterif 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()
最后展现界面: