1.基础设置
1.1导入所需的库
tkinter 和messagebox包
1.2创建窗口
import tkinter as tk
from tkinter import messagebox
w = tk.Tk()
w.title("棋")
w.geometry("500x600")
1.3创建画布
使用tk库下的Canvas方法来创建画布,参数有:引用窗口w,背景颜色,画布的宽高度等参数
hb = tk.Canvas(w, bg='white', height=420, width=420)
hb.pack()
1.4设置输入框,标签等控件
设置标签
y10 = tk.Label(w, text="请输入要落子的位置(1-9):", font=9)
设置输入框
y11 = tk.Entry(w, width=25)
2.在画布上定义九宫格的位置(每个格子的大小以及距画布的边缘,坐标)
# 方格大小
fg = 125 # 棋盘缩放
# 距画布边缘距离
bj = 20 # 棋盘偏移
# 画出九宫格 得到九宫格的位置
x0, y0, x1, y1 = bj, bj, bj + fg * 3, bj + fg * 3
3.定义交叉点坐标
3.1定义列表,存储每个交差点的坐标
points = [] #存储每个交叉点的坐标
3.2生成一个3x3的网格坐标点集合,存储在points中,用for遍历3行3列,生成9个不同的坐标点
for row in range(3):
for col in range(3):
points.append((x0 + fg * 0.5 + col * fg, y0 + fg * 0.5 + row * fg))
3.3定义游戏的初始化状态
board = [] # 棋盘数据
step = 0 # 游戏进度
gameover = False # 游戏是否结束
4.定义函数,名字:init
4.1使用for循环遍历(0,8),执行9次,使用tk包下的Label方法创建标签,标签显示的文本为 i 的值加1,因此标签显示的数字是1到9
for i in range(9):
tk.Label(hb, text=i + 1).place(x=points[i][0], y=points[i][1], anchor='center')
4.2同样使用for循环的方法绘制棋盘网格,使用tk包下的create_line方法绘制线条,循环会执行4次,所以绘制4条垂直线,每条线之间相差一个“fg(方格大小)”
# 绘制棋盘网格
for i in range(4):
hb.create_line(x0 + i * fg, y0, x0 + i * fg, y1)
hb.create_line(x0, y0 + i * fg, x1, y0 + i * fg)
4.3声明全局变量board
global board
board = ['' for i in range(9)]
声明全局变量gameover,step并设置初始值
global gameover
gameover = False
global step
step = 0
5.画棋子函数
5.1在这里声明全局变量step,设置棋子半径大小为20
def draw(index):
global step
r = 20 # 圆形半径
5.2使用create_oval方法绘制棋子的位置,points[index][0] - r, points[index][1] - r:确定了棋子的左上角的 x 和 y 坐标,棋子填充的颜色为蓝色
hb.create_oval(points[index][0] - r, points[index][1] - r, points[index][0] + r, points[index][1] + r,fill='blue')
5.3在棋盘上放置一个圆形的标记,并且更新游戏的步数
board[index] = '圆形'
# 步数+1
step += 1
6.定义点击函数,当点击按钮时,调用以下内容
6.1将输入框中的内容转换为整数。如果输入的不是数字,它会弹出一个警告消息框,同样如果输入的数字超出范围,也会弹出警告框。try :用于尝试执行其中的代码,如果代码执行过程中出现异常,程序会跳转到相应的 except 板块
def click():
global step
try:
num = int(y11.get()) #获取输入框的内容,将其转换为整型
except ValueError: #输入的不是数字时,会弹出下面的警告框
tk.messagebox.showwarning('警告', '此处不为空,不能落子!')
运行结果1
if num not in range(1, 10): #超出9范围的数字,也会弹出错误框
tk.messagebox.showwarning(title="警告", message="输入必须在(1-9)范围内")
运行结果2
6.2正常我们习惯从1输入,但是计算机的索引从0开始,所以我们要-1才可以对应其正确位置
index = num - 1
draw(index)
7.定义是否胜负的函数
7.1在这里声明变量gameover,把所有可能获胜的组合列举出来存储在win中
def isWin():
global gameover
# 所有可能获胜的组合
win = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [0, 4, 8], [1, 4, 7], [2, 5, 8], [2, 4, 6]]
7.2使用for遍历win,当索引0,1,2在win中一一对应的时候,此时玩家“圆形”获胜,并且索引0的位置不能为空值!!!
for i in win:
if board[i[0]] == board[i[1]] == board[i[2]] and board[i[0]] != '':
gameover = True
tk.messagebox.showinfo(title="输出结果", message='赢家是'+ board[i[0]])
return
7.3当步数大于五步时,没有获胜组合的话,会弹出提示框“无人获胜”
8.清空棋盘
这里我在init函数中,使用画布“hb”调用delete方法实现了清空棋盘
hb.delete('all')
点击后>>
9.设置按钮
9.1使用command分别连接函数
b = tk.Button(w, text="按下落子", width=15, height=2, command=click)
b.place(x=80, y=520)
b1 = tk.Button(w, text="重新开始", width=15, height=2,command=init)
b1.place(x=230, y=520)
10.AI落棋子
10.1定义ai函数,调用AI类的decide()方法,参数为玩家名称:'AI',形状:'圆形'和当前棋盘的状态
def ai_move():
index = ai.AI().decide('AI','圆形',board)
10.2设置AI棋子的半径大小,然后画布上创建矩形,其坐标根据AI返回的索引计算得出
r=20
hb.create_rectangle(points[index][0]-r,points[index][1]-r,points[index][0]+r,points[index][1]+r,fill='pink')
board[index]='AI' #更新游戏棋盘