完整项目下载:下载链接
1 前言
在数字的世界里,古老的棋盘游戏焕发出崭新的活力,因为它们不再只属于人类玩家。本文将带您进入一个充满策略和智慧的领域,通过Python的神奇力量,将经典的井字棋游戏推向了新的高度。
这不再是单纯的人机对战,而是一场与AI智慧的较量。我们将使用tkinter库创建一个令人赞叹的游戏界面,其美观和交互性将让您身临其境。更令人兴奋的是,在这个看似简单的游戏中,隐藏着一个精心设计的AI算法,它将成为您的对手,挑战您的智力极限。
从界面的绘制到用户与AI的交互,再到AI算法的实现,本文将为您逐一揭示这些奥秘。您将亲手编写代码,让AI学会最佳的棋局选择,让游戏不再是孤独的战斗,而是与AI智慧共舞的快乐时光。
准备好迎接这个引人入胜的冒险了吗?让我们一起踏上这个富有挑战性和创造性的Python之旅,探索AI与人类之间的智力角逐!
为了读者对游戏有更好的了解,这里放操作视频:操作视频
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.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) # 创建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.4 定义页面变化类以及玩家与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.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 = 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()
最后展现界面:
4 结语
通过本文的指引,您已经走过了一段关于使用tkinter和Python的旅程,进入了井字棋游戏的精彩世界。从代码模块的分析到实现细节的解释,您已经了解了如何创造一个兼具娱乐和挑战性的AI对战游戏。
在这个过程中,您不仅学习了如何使用Python的库来构建界面和逻辑,还深入探索了AI算法的实现。玩家类、页面类、胜负判断和智能AI下子等模块的设计和互动,为您呈现了一个完整的游戏体验。
希望您通过本文的学习,不仅掌握了更多关于Python编程和界面设计的技能,还能深刻体会AI算法在游戏中的应用。不论是探索代码的乐趣还是与AI对战的挑战,都将让您在编程的世界中获得新的启发和成就感。
愿您在未来的创作中能够运用所学,创造出更多有趣、有用的项目,不断挖掘Python的无限可能性。继续探索,不断前行,让编程之路变得更加精彩!