• Python-井字棋


    1.设计登录界面

    1.1导入需要的工具包

    import tkinter as tk
    from PIL import Image, ImageTk
    import pickle
    from tkinter import messagebox
    import subprocess
    

    1.2窗口显示

    window = tk.Tk()
    window.title("Welcome")
    window.geometry('500x600')
    

    1.3登录界面图片显示

    image = Image.open("welcome.gif")
    photo = ImageTk.PhotoImage(image)
    

    函数解析 ImageTk.PhotoImage 是 Python 中用于处理图像的模块,通常与 PIL(Python Imaging
    Library)一起使用。它允许你在 Tkinter 程序中加载和显示图像。
    1.5 用户名设置默认值

    value = "GaoYue"
    entry_var = tk.StringVar(window)
    entry_var.set(value)
    

    解释:
    创建了一个StringVar对象entry_var,用于绑定到一个Entry控件,以便可以在用户输入时更新该控件的值。然后,给entry_var设置了一个初始值value,这样在Entry控件中显示的文本就是value的值,并设置初始值为@qq.com,这样在Entry控件中显示的文本就是。

    1.6标签按钮输入框显示

    label1_image = tk.Label(window,image=photo)
    label1_image.place(x=10,y=10)
    label2 = tk.Label(window,text='User name',width=10,height=5)
    label2.place(x=40,y=130)
    label3 = tk.Label(window,text='password',width=10,height=5)
    label3.place(x=40,y=180)
    label4 = tk.Entry(window,width=30,bd=5)
    label4.place(x=140,y=210)
    label5 = tk.Entry(window,textvariable=entry_var,width=30,bd=5)
    label5.place(x=140,y=160)
    
    button1 = tk.Button(window,text='Loign',width=10,command=usr_login)
    button1.place(x=140,y=280)
    button2 = tk.Button(window,text='Sign up',width=10,command=usr_sign_up)
    button2.place(x=250,y=280)
    

    2.登录功能实现

    2.1用户数据存储

    def usr_login():
        usr_name = label5.get()
        usr_pwd=label4.get()
        print(usr_name)
        try:
            with open("usrs_info.pickle",'rb') as usr_file:
                print("1")
                usrs_info = pickle.load(usr_file)
                print(usrs_info)
        except FileNotFoundError:
            with open("usrs_info.pickle",'wb') as usr_file:
                print("2")
                usrs_info = {'admin':'admin'}
                pickle.dump(usrs_info,usr_file)
    

    解释:

    两个输入框(label5,label4)使用get()函数,获取用户输入的数据,接下来使用使用了Python中的异常处理机制。在try使用with语句打开"usrs_info.pickle"文件,设置为只读二进制模式,将”usrs_info.pickle”二进制文件加载到内存里面,转换到usrs_info变量中,输出出来。当读取的文件不存在报错时,跳转到except代码块中执行相应的异常处理,使用with语句打开二进制写入模式打开文件,文件不存在时创建相对应文件,用一个变量(usrs_info)接收一个字典(
    {‘admin’:‘admin’})用来存储用户信息或者账户信息,用于验证用户身份,将字典序列化为字节流(二进制数据)并写入usr_file文件中永久保存。

    2.2登录和注册

    2.2.1登录功能实现

    print("ok")
    print("usr_name:",usr_name)
    if usr_name in usrs_info:
        print("3")
        if usr_pwd  == usrs_info[usr_name]:
            tk.messagebox.showinfo(title="Welcome",message="How are you"+usr_name)
            tk.messagebox.showinfo(title="Game Start", message="Let's start the game!")
            subprocess.run(["python", "飞机大战.py"])
        else:
            tk.messagebox.showerror(message="Error,your password is wrong,try again.")
    else:
        print("4")
        is_sign_up = tk.messagebox.askyesno(title="Welcome",message="You have not sign up yet.sign up today?")
    

    解释:
    If语句如果用户名在字典中执行下一个if语句用户密码是否等于usrs_info中键usr_name的值,如果等于弹出消息框((title=“Welcome”,message=“How
    are you”+usr_name),(title=“Game Start”, message=“Let’s start the
    game!”),使用subprocess.run函数以python解释器,执行井字棋.py文件,如果不等于弹出消息框(message=“Error,your
    password is wrong,try
    again.”),如果第一个if语句没有达到条件,弹出一个对话框,内容是title=“Welcome”,message=“You have
    not sign up yet.sign up today?”。

    2.2.2注册功能实现

    def sign_up():
        nn = entry9.get()
        np = entry10.get()
        npf = entry11.get()
        with open('usrs_info.pickle','rb') as usr_file:
            exist_usr_info = pickle.load(usr_file)
        if np != npf:
            tk.messagebox.showerror("Error","The user has already signed up!")
        elif nn in exist_usr_info:
            print("已经注册过了")
            tk.messagebox.showerror("Error","The user has already signed up!")
        else:
            exist_usr_info[nn] = np
            with open("usrs_info.pickle","wb") as usr_file:
                pickle.dump(exist_usr_info,usr_file)
            tk.messagebox.showinfo("Welcome","You have successfully signed up!")
            window.destroy()
    button3 = tk.Button(window, text='Sign up', width=10,command=sign_up)
    button3.place(x=140, y=150)
    print("开始注册")
    

    解释:
    三个输入框获取用户输入的用户名,注册密码,重复密码,打开二进制文件,将二进制文件数据转换为python对象,用一个变量exist_usr_info保存,然后if判断注册密码是否与重复密码相等,如果不相等就弹出消息框(“Error”,“The
    user has already signed
    up!”),反之文件中的用户名中的密码等于注册密码,将变量exist_usr_info中的数据通过with语句和pickle函数保存在二进制文件中,然后弹出消息框(“Welcome”,“You
    have successfully signed up!”),窗口销毁,将函数sign_up与按钮进行连接,最后输入开始注册。

    3.井字棋游戏

    3.1 导入需要的工具包

    import tkinter as tk
    from tkinter import messagebox
    

    3.2 窗口显示

    window = tk.Tk()
    window.geometry("600x500")
    window.title("Welcome")
    

    3.2 按钮标签显示

    label2 = tk.Label(text="请输入要落下棋子的位置(1-9):", width=30, height=2)
    label2.pack()
    label2.place(x=190, y=310)
    entry2 = tk.Entry(width=20)
    entry2.pack()
    entry2.place(x=220, y=350)
    button11 = tk.Button(text="落下棋子", width=10, height=2,command=message2)
    button11.pack()
    button11.place(x=250, y=380)
    button22 = tk.Button(text="重新开始", width=10, height=2)
    button22.pack()
    button22.place(x=250, y=430)
    

    解释: 设置标签和按钮,按钮与函数相连接

    3.3 棋盘设置初始状态

    gameover = False
    board = ['']*9
    step = 0
    

    解释: 设置游戏初始化为结束,设置棋盘状态为九个空字符串的列表,step为初始化棋盘步数为0

    3.4 游戏设计

    3.4.1创建白布

    canvas = tk.Canvas(window, width=300, height=300, bg="white")
    canvas.pack()
    

    函数解析: tk.Canvas 是 Tkinter
    中用于绘制图形的组件,你可以在其中绘制直线、矩形、椭圆等形状,也可以放置文本、图像等元素。

    3.4.2 画出九宫格

    def draw_nume(canvas,width,height,line_color='black'):
        cell_width = width / 3
        cell_height = height / 3
    
        for i in range(3):
            x = i * cell_width
            canvas.create_line(x, 0, x, height, fill=line_color)  # 垂直线
        for i in range(3):
            y = i * cell_height
            canvas.create_line(0, y, width, y, fill=line_color)  # 水平线
    

    解释:
    定义一个draw_nume函数传入形参(canvas,width,height,line_color=‘black’),’line_color='black’表示线条颜色,width,height,cell_width
    = width / 3和cell_height = height / 3计算了每个单元格的宽度和高度,第一个for循环是画垂直线(起点坐标,终点坐标) fill=line_color填充方式为线条,计算当前列的
    x 坐标为 i * cell_width。第二个for循环是画水平线,计算当前行的 y坐标为 i *
    cell_height,canvas.create_line()画水平线。

    在每个格子中心绘制数字或 “X”

    for i in range(3):
        for j in range(3):
            x = i * cell_width + cell_width / 2
            y = j * cell_height + cell_height / 2
            index = i * 3 + j
            if board[index] == 'X':
                canvas.create_text(y, x, text="X", font=("Helvetica", 20))
            else:
                canvas.create_text(y, x, text=str(index + 1), font=("Helvetica", 20))
    

    解释: 第一个for循环为行的中心位置,第二个for循环为列的中心位置,在x,y找到中心位置 index = i * 3 +
    j是在九宫格上写上数字的索引,如果board[index] == ‘X’:,就在x,y的中心位置画X,如果不是在index索引加一。
    3.5设置输入限制

    def message():
        Iemet = entry2.get()
        if not Iemet.isdigit():
            tk.messagebox.showinfo("输入错误", "请输入一个数字。")
        elif int(Iemet) > 9:
            tk.messagebox.showinfo("输入错误", "输入的数字不能大于 9。")
    

    解释: 如果判断不是数字,弹出消息框(“输入错误”, “请输入一个数字。”),接着判断输入的是大于9 的弹出消息框(“输入错误”,
    “输入的数字不能大于 9。”)

    3.6设置输赢条件

    def iswins():
        global gameover
        wins = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]]
        for w in wins:
            if (board[w[0]]!=" " and board[w[0]]==board[w[1]]==board[w[2]]):
                gameover = True
                tk.messagebox.showinfo(title="你别挣了",message="我赢了")
                return
        if step>=5:
            gameover =True
            return tk.messagebox.showinfo(title="你别挣了",message="都没有赢了")
        return
    

    解释:
    定义全局变量gameover,列出所有的用户赢的可能,for循环用与循环遍历wins列表,if条件使用索引board[w[0]],w的第一个数不能为空,判断board[w[0]]的第一个数和第二个数和第三个数是否相等,如果相等就是wins列表中的一个赢的可能,弹出消息框(title=“你别挣了”,message=“我赢了”),返回,第二个if条件如果我方步数大于等于5返回消息框(title=“你别挣了”,message=“都没有赢了”),返回。

    3.7 进一步处理用户输入

    def message2():
        global board
        global step
        Iemet = entry2.get()
        if Iemet.isdigit():
            number = int(Iemet)
            if 1 <= number <= 9:
                index = number - 1
                board[index] = 'X'
                draw_nume(canvas, 300, 300)
        is_Win()
        step +=1
    

    解释:
    定义两个全局变量,获取输入框文本,if语句检查用户输入的文本是否为数字,接着if语句判断是否在1到9之间(包括1-9),井字棋游戏板上的索引位置标记为
    ‘X’,表示用户的棋子,这是一个函数调用,用来在画布上绘制新的游戏板,调用一个函数is_Win(),用来检查是否获胜,这一行代码增加游戏的步数,以便在每一步后进行检查。将函数放置在按钮上。

    3.8设置AI步数

    index = ai.AI().decide("AI","高越",board)
    r = 20
    canvas.create_oval()
    board[index] = "AI"
    iswins()
    

    解释: 调用了 ai.AI().decide(“AI”,“高越”,board),圆的半径为20,设置棋盘数据为”AI”。

    3.9 清空棋盘状态

    def reset():
        global canvas
        canvas.delete('A')
    

    使用canvas.delete函数清空棋盘状态

    效果图

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    6、Linux-服务管理、权限管理和授权(sudo权限)
    基于Vue+SpringBoot的厦门旅游电子商务预订系统 开源项目
    去掉限制+让赢家保持局面不变:P4101
    代码随想录二刷day28
    电脑开机为什么老是要两次?
    python3:print()打印. 2023-11-18
    【shell 常用脚本30例】
    web前端期末大作业——贵州山地旅游介绍网页1页 HTML旅游网站设计与实现
    jdk7新增时间类Date,SimpleDateFormat,Calendar
    客户端架构
  • 原文地址:https://blog.csdn.net/2302_76950070/article/details/139937410