井字棋游戏

1. 游戏创建

1.1导包

from tkinter import *
import numpy as np
import math
import tkinter.messagebox

1.2 窗口内容

1.2.1创建一个窗口

root = Tk()  # 窗口名称
root.title("井字棋 from Sun")

1.2.2 创建一个框架,将其放置在窗口中

Frame1 = Frame(root)  # 框架
Frame1.pack()

1.2.3 创建一个用来绘制九宫格的画布w1

w1 = Canvas(Frame1, width=580, height=580, bg="white")  # 创建一个画布(Canvas),设置大小
w1.pack()    # w1:画布

1.3 绘制九宫格

  使用create_line在画布上绘制九宫格。

for i in range(0, 4):

    w1.create_line(i * 180 + 20, 20, i * 180 + 20, 560)  # 绘制竖线

    w1.create_line(20, i * 180 + 20, 560, i * 180 + 20)  # 绘制横线

运行结果:

1.4 定义一个全局变量

# 定义全局变量num

num = 0 # 记录点击的次数,用来决定点击后该画哪种图形

# 定义一个3X3的数组A

A = np.full((3, 3), 0) # 记录每个位置的图形

# 0表示空,1表示叉号,2表示圆圈。

1.5 定义一个鼠标事件

根据鼠标的点击在网格中绘制“X”和“O”

def dawn(event):

    global w1

    global num, A

    for i in range(0, 3):  # 确定被单击的网格单元格的行号。

        for j in range(0, 3):  # 确定被单击的网格单元格的行号。

            if 20 + j * 180 < event.y and event.y <= 20 + (j+1) * 180:

                break

        if 20 + i * 180 <= event.x and event.x <= 20 + (i+1) * 180:

            break

    if num % 2 == 0 and A[i][j] == 0:   # 如果当前玩家是 X并且该单元格为空,则绘制叉号。

         A[i][j] = 1   

1.6 创建图形“×”和“○”

1.6.1 创建“×”

# 使用create_line方法在指定位置绘制叉号。

        w1.create_line(110 + 180 * i - 45 * math.sqrt(2), 110 + 180 * j - 45 * math.sqrt(2),

                       110 + 180 * i + 45 * math.sqrt(2), 110 + 180 * j + 45 * math.sqrt(2), width=5)

        w1.create_line(110 + 180 * i + 45 * math.sqrt(2), 110 + 180 * j - 45 * math.sqrt(2),

                       110 + 180 * i - 45 * math.sqrt(2), 110 + 180 * j + 45 * math.sqrt(2), width=5)

        num += 1  # 增加点击次数。

1.6.2 创建“○”

# 使用create_oval方法在指定位置绘制圆圈。

  w1.create_oval(20 + 180 * i + 10, 20 + 180 * j + 10, 20 + 180 * (i + 1) - 10, 20 + 180 * (j + 1) - 10, width=5)

   num += 1

1.7 对弈结果:①“X”获胜  ②“O获胜”③ 平局

1.7.1 “O”获胜的所有可能性

  • 所有可能性:  ① 横向三个相邻单元格都包含 O。
  •                         ② 纵向三个相邻单元格都包含 O。
  •                         ③ 从左上角到右下角的对角线上的所有单元格都包含 O。
  •                         ④ 从右上角到左下角的对角线上的所有单元格都包含 O。

    

if (A[0][0] == A[0][1] == A[0][2] == 2 or A[1][0] == A[1][1] == A[1][2] == 2 or A[2][0] == A[2][1] == A[2][2] == 2 or A[0][0] == A[1][0] == A[2][0] == 2 or A[0][1] == A[1][1] == A[2][1] == 2 or A[0][2] == A[1][2] ==A[2][2] == 2 or A[0][0] == A[1][1] == A[2][2] == 2 or A[2][0] == A[1][1] == A[0][2] == 2):

     tkinter.messagebox.showinfo('Warning', '恭喜O获胜啦')

1.7.2 “X”获胜的所有可能性

  • 所有可能性:  ① 横向三个相邻单元格都包含 X。
    •                         ② 纵向三个相邻单元格都包含 X。
      •                         ③ 从左上角到右下角的对角线上的所有单元格都包含 X。
        •                         ④ 从右上角到左下角的对角线上的所有单元格都包含 X。
elif (A[0][0] == A[0][1] == A[0][2] == 1 or A[1][0] == A[1][1] == A[1][2] == 1 or A[2][0] == A[2][1] == A[2][2] == 1 or A[0][0] == A[1][0] == A[2][0] == 1 or A[0][1] == A[1][1] == A[2][1] == 1 or A[0][2] == A[1][2] ==A[2][2] == 1 or  [0][0] == A[1][1] == A[2][2] == 1 or A[2][0] == A[1][1] == A[0][2] == 1):

    tkinter.messagebox.showinfo('Warning', '恭喜X获胜啦')

1.7.3 平局的所有可能性

          每个棋子最多能走5步,当X走了5步时,则O只走了4步,所以XO加一起只能走9步,所以当没有棋子连在一起的时候,就该考虑是否已经走了9次,如果走了就此还没达到获胜条件时,那么这时候就是平局

    elif num == 9 and not (

        A[0][0] == A[0][1] == A[0][2] == 2 or A[1][0] == A[1][1] == A[1][2] == 2 or A[2][0] == A[2][1] == A[2][2] == 2 or A[0][0] == A[1][0] == A[2][0] == 2 or A[0][1] == A[1][1] == A[2][1] == 2 or A[0][2] == A[1][2] ==A[2][2] == 2 or A[0][0] == A[1][1] == A[2][2] == 2 or A[2][0] == A[1][1] == A[0][2] == 2 orA[0][0] == A[0][1] == A[0][2] == 1 or A[1][0] == A[1][1] == A[1][2] == 1 or A[2][0] == A[2][1] == A[2][2] == 1 or A[0][0] == A[1][0] == A[2][0] == 1 or A[0][1] == A[1][1] == A[2][1] == 1 or A[0][2] == A[1][2] == A[2][2] == 1 orA[0][0] == A[1][1] == A[2][2] == 1 or A[2][0] == A[1][1] == A[0][2] ==1):

     tkinter.messagebox.showinfo('Warning', 'woo平局啦!')

1.8 “退出”

1.8.1 退出的函数

def quit():

    root.quit()

1.8.2 退出的按钮

# 退出按钮

button1 = Button(root, text="退出", font=('微软雅黑', 15), command=quit)

button1.pack()

1.9 “重新开始”

1.9.1 重新开始的函数

def restart():

    global w1, num, A

    w1.delete("all")  # 清除画布上所有的东西

    for i in range(0, 4):

        w1.create_line(i * 180 + 20, 20, i * 180 + 20, 560)

        w1.create_line(20, i * 180 + 20, 560, i * 180 + 20)

    num = 0

    A = np.full((3, 3), 0)



w1.bind("<Button -1>", dawn)

1.9.1 从新开始的按钮

# 重新开始按钮

button2 = Button(root, text="重新开始", font=('微软雅黑', 15), command=restart)

button2.pack()

2. 完整代码

from tkinter import *
import numpy as np
import math
import tkinter.messagebox

root = Tk()  # 窗口名称
root.title("井字棋 from Sun")
# root.geometry("600x600")
Frame1 = Frame(root)  # 框架
Frame1.pack()
w1 = Canvas(Frame1, width=580, height=580, bg="white")  # 创建一个画布(Canvas),设置大小
w1.pack()    # w1:画布

for i in range(0, 4):
    w1.create_line(i * 180 + 20, 20, i * 180 + 20, 560)  # 绘制竖线
    w1.create_line(20, i * 180 + 20, 560, i * 180 + 20)  # 绘制横线

# 定义全局变量num
num = 0							# 记录点击的次数,用来决定点击后该画哪种图形
# 定义一个3X3的数组A
A = np.full((3, 3), 0)			# 记录每个位置的图形
# 0表示空,1表示叉号,2表示圆圈。

def dawn(event):
    global w1
    global num, A
    for i in range(0, 3):  # 确定被单击的网格单元格的行号。
        for j in range(0, 3):  # 确定被单击的网格单元格的行号。
            if 20 + j * 180 < event.y and event.y <= 20 + (j+1) * 180:
                break
        if 20 + i * 180 <= event.x and event.x <= 20 + (i+1) * 180:
            break
    if num % 2 == 0 and A[i][j] == 0:   # 如果当前玩家是 X并且该单元格为空,则绘制叉号。
        # 网格中的行 i 和列 j
        A[i][j] = 1   # 二维数组:A[i][j]
        # 使用create_line方法在指定位置绘制叉号。
        w1.create_line(110 + 180 * i - 45 * math.sqrt(2), 110 + 180 * j - 45 * math.sqrt(2),
                       110 + 180 * i + 45 * math.sqrt(2), 110 + 180 * j + 45 * math.sqrt(2), width=5)
        w1.create_line(110 + 180 * i + 45 * math.sqrt(2), 110 + 180 * j - 45 * math.sqrt(2),
                       110 + 180 * i - 45 * math.sqrt(2), 110 + 180 * j + 45 * math.sqrt(2), width=5)
        num += 1  # 增加点击次数。
    if num % 2 != 0 and A[i][j] == 0:   # 如果当前玩家是 O 并且该单元格为空,则绘制圆圈。
        A[i][j] = 2
        # 使用create_oval方法在指定位置绘制圆圈。
        w1.create_oval(20 + 180 * i + 10, 20 + 180 * j + 10, 20 + 180 * (i + 1) - 10, 20 + 180 * (j + 1) - 10, width=5)
        num += 1
# 0表示空,1表示叉号,2表示圆圈  # \ :换行
    if (A[0][0] == A[0][1] == A[0][2] == 2 or A[1][0] == A[1][1] == A[1][2] == 2 or A[2][0] == A[2][1] == A[2][
        2] == 2 or A[0][0] == A[1][0] == A[2][0] == 2 or A[0][1] == A[1][1] == A[2][1] == 2 or A[0][2] == A[1][2] ==
            A[2][2] == 2 or A[0][0] == A[1][1] == A[2][2] == 2 or A[2][0] == A[1][1] == A[0][2] == 2):
            # 从左上角到右下角的对角线上的所有单元格都包含 O or 从右上角到左下角的对角线上的所有单元格都包含 O
        tkinter.messagebox.showinfo('Warning', '恭喜O获胜啦')

    elif (A[0][0] == A[0][1] == A[0][2] == 1 or A[1][0] == A[1][1] == A[1][2] == 1 or A[2][0] == A[2][1] == A[2][
        2] == 1 or A[0][0] == A[1][0] == A[2][0] == 1 or A[0][1] == A[1][1] == A[2][1] == 1 or A[0][2] == A[1][2] ==
          A[2][2] == 1 or
            A[0][0] == A[1][1] == A[2][2] == 1 or A[2][0] == A[1][1] == A[0][2] == 1):
        tkinter.messagebox.showinfo('Warning', '恭喜X获胜啦')

    elif num == 9 and not (
        A[0][0] == A[0][1] == A[0][2] == 2 or A[1][0] == A[1][1] == A[1][2] == 2 or A[2][0] == A[2][1] == A[2][
        2] == 2 or A[0][0] == A[1][0] == A[2][0] == 2 or A[0][1] == A[1][1] == A[2][1] == 2 or A[0][2] == A[1][2] ==
        A[2][2] == 2 or A[0][0] == A[1][1] == A[2][2] == 2 or A[2][0] == A[1][1] == A[0][2] == 2 or
        A[0][0] == A[0][1] == A[0][2] == 1 or A[1][0] == A[1][1] == A[1][2] == 1 or A[2][0] == A[2][1] == A[2][2] == 1 or
        A[0][0] == A[1][0] == A[2][0] == 1 or A[0][1] == A[1][1] == A[2][1] == 1 or A[0][2] == A[1][2] == A[2][2] == 1 or
        A[0][0] == A[1][1] == A[2][2] == 1 or A[2][0] == A[1][1] == A[0][2] == 1
    ):
        tkinter.messagebox.showinfo('Warning', 'woo平局啦!')

def restart():
    global w1, num, A
    w1.delete("all")  # 清除画布上所有的东西
    for i in range(0, 4):
        w1.create_line(i * 180 + 20, 20, i * 180 + 20, 560)
        w1.create_line(20, i * 180 + 20, 560, i * 180 + 20)
    num = 0
    A = np.full((3, 3), 0)

w1.bind("<Button -1>", dawn)
def quit():
    root.quit()
# 退出按钮
button1 = Button(root, text="退出", font=('微软雅黑', 15), command=quit)
button1.pack()
# 重新开始按钮
button2 = Button(root, text="重新开始", font=('微软雅黑', 15), command=restart)
button2.pack()

root.mainloop()

3. 运行结果

  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值