前言

1992年扫雷被加入到windows3.1,成为早期windows的经典游戏。近来接触python的GUI(图形化)编程,于是通过编写扫雷来实践学习。有关程序的问题和想法欢迎大家指出。

一、基本思路

(1)程序的核心数据是二维列表control_list[16][16],值-1代表雷,0和其他数字代表四周雷的数目。函数randomization()随机40个雷的 位置
(2)生成16x16个按钮控件,根据control_list列表确定点击相应的按钮时执行的代码。如按照游戏规则:点击对应control_list列表值为0的按钮时,递归执行函数re()来扫雷,当点击对应的control_list列表值为-1时直接结束游戏,对应大于0的值则只需隐藏当前的按钮控件。
其他:本程序用到的GUI编程库为tkinter, 控件的布局统一采用place()方法

二、源代码

1.运行效果

运行效果如下(示例):

2.上源码

"""
Created on Tuesday, April 5,2022
@author:I
"""
from tkinter import *
from tkinter import messagebox
import random

#定义五个二维数组,充当整个程序的数据
control_list=[[0 for i in range(16)] for j in range(16)]#二维列表,呈现雷和数字的分布。
show_list=[[0 for i in range(16)] for j in range(16)]#二维列表,控制遮住或显示雷和数字。(0--遮住,1--显示)
button_list=[[0 for i in range(16)] for j in range(16)]#二维的按钮列表(显示在上层)
label_list=[[0 for i in range(16)] for j in range(16)]#二维的标签列表(显示在下层)
mark_list=[[0 for i in range(16)] for j in range(16)]#二维标记列表
num_mine=40#控制游戏结束
counter=0#计时
T ,t= 1,0#游戏结束的判断
def randomization(c_list):#随机初始化雷的分布即初始化列表control_list
    num=0
    while num<40:
        x=random.randint(0,15)
        y=random.randint(0,15)
        if(c_list[x][y]==0):
            num =1
            c_list[x][y]=-1
    for i in range(16):
        for j in range(16):
            if(c_list[i][j]>-1):
                if (i>0 and c_list[i-1][j]==-1):
                    c_list[i][j] =1
                if (i<15 and c_list[i 1][j]==-1):
                    c_list[i][j] =1
                if (j>0 and c_list[i][j-1]==-1):
                    c_list[i][j] =1
                if (j<15 and c_list[i][j 1]==-1):
                    c_list[i][j] =1
                if (i>0 and j>0 and c_list[i-1][j-1]==-1):
                    c_list[i][j] =1
                if (i<15 and j<15 and c_list[i 1][j 1]==-1):
                    c_list[i][j] =1
                if (i>0 and j<15 and c_list[i-1][j 1]==-1):
                    c_list[i][j] =1
                if (i<15 and j>0 and c_list[i 1][j-1]==-1):
                    c_list[i][j] =1
def game_core():
    randomization(control_list)
    for row in range(16):
        for col in range(16):
            if(control_list[row][col]==-1):
                label_list[row][col]=Label(root,text="☠",font=('arial', 15, 'bold'),fg="black",bg="#AAAAAA",relief=RIDGE)
                label_list[row][col].place(x=17 col*20,y=46 row*20,height=20,width=20)
            elif(control_list[row][col]==0):
                label_list[row][col]=Label(root,text="",bg="#AAAAAA",relief=RIDGE)
                label_list[row][col].place(x=17 col*20,y=46 row*20,height=20,width=20)
            elif(control_list[row][col]==1):
                label_list[row][col]=Label(root,text="1",font=('arial', 15, 'bold'),fg="red",bg="#AAAAAA",relief=RIDGE)
                label_list[row][col].place(x=17 col*20,y=46 row*20,height=20,width=20)
            elif(control_list[row][col]==2):
                label_list[row][col]=Label(root,text="2",font=('arial', 15, 'bold'),fg="blue",bg="#AAAAAA",relief=RIDGE)
                label_list[row][col].place(x=17 col*20,y=46 row*20,height=20,width=20)
            elif(control_list[row][col]==3):
                label_list[row][col]=Label(root,text="3",font=('arial', 15, 'bold'),fg="green",bg="#AAAAAA",relief=RIDGE)
                label_list[row][col].place(x=17 col*20,y=46 row*20,height=20,width=20)
            elif(control_list[row][col]==4):
                label_list[row][col]=Label(root,text="4",font=('arial', 15, 'bold'),fg="white",bg="#AAAAAA",relief=RIDGE)
                label_list[row][col].place(x=17 col*20,y=46 row*20,height=20,width=20)
            elif(control_list[row][col]==5):
                label_list[row][col]=Label(root,text="5",font=('arial', 15, 'bold'),fg="red",bg="#AAAAAA",relief=RIDGE)
                label_list[row][col].place(x=17 col*20,y=46 row*20,height=20,width=20)
            elif(control_list[row][col]==6):
                label_list[row][col]=Label(root,text="6",font=('arial', 15, 'bold'),fg="blue",bg="#AAAAAA",relief=RIDGE)
                label_list[row][col].place(x=17 col*20,y=46 row*20,height=20,width=20)
            elif(control_list[row][col]==7):
                label_list[row][col]=Label(root,text="7",font=('arial', 15, 'bold'),fg="green",bg="#AAAAAA",relief=RIDGE)
                label_list[row][col].place(x=17 col*20,y=46 row*20,height=20,width=20)
            elif(control_list[row][col]==8):
                label_list[row][col]=Label(root,text="8",font=('arial', 15, 'bold'),fg="white",bg="#AAAAAA",relief=RIDGE)
                label_list[row][col].place(x=17 col*20,y=46 row*20,height=20,width=20)
    for r in range(16):
        for c in range(16):
            s = str((r)*16 c)
            button_list[r][c]=Button(root,text=s,activeforeground="#AAAAAA",bg="#AAAAAA",fg="#AAAAAA")
            button_list[r][c].place(x=17 c*20,y=46 r*20,height=20,width=20)
            button_list[r][c].bind("<Button-1>",button_control_l)#鼠标左击绑定函数
            button_list[r][c].bind("<Button-3>",button_control_r)
def button_control_l(event):#扫雷控制函数.(开始函数直接用参数r和c,但是会产生问题)
    r = int(event.widget["text"])//16
    c = int(event.widget["text"])
    global t
    global T
    if(control_list[r][c]>=1):
        button_list[r][c].place_forget()
        show_list[r][c]=1
        t =1
    elif(control_list[r][c]==0):
        rec(r,c)
    elif(control_list[r][c]==-1 and T):
        button_list[r][c].place_forget()
        show_list[r][c]=1
        T=0
        for i in range(16):
            for j in range(16):
                if(control_list[i][j]==-1):
                    button_list[i][j].place_forget()
                    show_list[r][c]=1
        button_restart["text"]="☹"
        messagebox.showwarning("失败","你已经被炸死了!")
    if t==216:
            T=0
            messagebox.showwarning("成功","恭喜你扫雷完成!")
def button_control_r(event):
    r = int(event.widget["text"])//16
    c = int(event.widget["text"])
    mark_list[r][c]=Button(root,text="?",font=('楷体', 14),activeforeground="#AAAAAA",bg="#AAAAAA",fg="yellow")
    mark_list[r][c].place(x=17 c*20,y=46 r*20,height=20,width=20)
    mark_list[r][c].bind("<Button-3>",button_control_r_change)
def button_control_r_change(event):
    global num_mine
    if (event.widget["text"]=="?" and num_mine>0):
        num_mine-=1
        event.widget["text"]="▲"
        cout_label["text"]=str(num_mine)
    elif(event.widget["text"]=="▲"):
        num_mine =1
        cout_label["text"]=str(num_mine)
        event.widget.place_forget()
    elif (event.widget["text"]=="?" and num_mine==0):
        event.widget.place_forget()
def rec(r,c):#递归探测
    global t
    if control_list[r][c]>0 and show_list[r][c]==0:
        button_list[r][c].place_forget()
        show_list[r][c]=1
        t =1
        return 0
    elif control_list[r][c] ==0 and show_list[r][c]==0:
        button_list[r][c].place_forget()
        show_list[r][c]=1
        t =1
        if r>0 and c>0:
            rec(r-1,c-1)
        if r>0:
            rec(r-1,c)
        if r>0 and c<15:
            rec(r-1,c 1)
        if c<15:
            rec(r,c 1)
        if r<15 and c<15:
            rec(r 1,c 1)
        if r<15:
            rec(r 1,c)
        if r<15 and c>0:
            rec(r 1,c-1)
        if c>0:
            rec(r,c-1)
def time_counter(la):  # la是标签,计时函数
    def counting():
        global counter
        if T:
            counter  = 1
        la["text"]=str(counter)
        la.after(1000,counting)  # 在1000毫秒后执行counting()函数,即循环执行counting
    counting()
def restart():#重新开始函数
    button_restart["text"]="☺"
    cout_label["text"]="40"
    #数据重置
    for i in range(16):
        for j in range(16):
            control_list[i][j]=0
            show_list[i][j]=0
            button_list[i][j].place_forget()
            button_list[i][j]=0
            label_list[i][j].place_forget()
            label_list[i][j]=0
            if (mark_list[i][j]!=0):
                mark_list[i][j].place_forget()
            mark_list[i][j]=0
    global num_mine
    global counter
    global T ,t
    num_mine=40
    counter=0
    T ,t= 1,0
    game_core()
if __name__ =="__main__":
    
    root = Tk()#根窗体
    root.title("扫雷小游戏")
    root.geometry("360x410")#根窗体大小
    cv1 = Canvas(root,bd=15,bg="#FFFFFF",relief=RIDGE,cursor="cross",width=321,height=350)
    cv1.create_line(15,45,337,45)
    cv1.place(x=0,y=0)
    w=Label(root,text="你所作的选择,决定你的命运!",font=("楷体",12))
    w.place(x=60,y=385)
    button_restart=Button(root,text="☺",font=('楷体', 15),bg="#AAAAAA",fg="yellow",command=restart)
    button_restart.place(x=150,y=17,height=27,width=27)
    time_label = Label(root,bg="black",fg="red",text=str(counter),font=("LcdD",15))#计时标签
    time_label.place(x=285,y=17,height=27,width=50)
    cout_label = Label(root,bg="black",fg="red",text="40",font=("LcdD",20))#计数标签
    cout_label.place(x=18,y=17,height=27,width=27)
    game_core()
    time_counter(time_label)
    root.mainloop()#监控组件,组件发生变化或触发事件时,更新窗口

总结

扫雷的思路简单,但编写这个程序仍然花费了我比较长的时间,究其原因:初次接触python的GUI编程,对各个控件的方法等不熟悉,且没有能够充分的查找资料,在面对问题时处理思路局限。编程世界,道路漫长遥远。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持Devmax。

python GUI编程实现扫雷游戏的更多相关文章

  1. XCode 3.2 Ruby和Python模板

    在xcode3.2下,我的ObjectiveCPython/Ruby项目仍然可以打开更新和编译,但是你无法创建新项目.鉴于xcode3.2中缺少ruby和python的所有痕迹(即创建项目并添加新的ruby/python文件),是否有一种简单的方法可以再次安装模板?我发现了一些关于将它们复制到某个文件夹的信息,但我似乎无法让它工作,我怀疑文件夹的位置已经改变为3.2.解决方法3.2中的应用程序模板

  2. ios – 在Spritekit游戏中限制GUI元素的比例

    如果我使用375×667尺寸的场景,那么一切都正确定位并具有良好的比例,但质量受损解决方法统一的GUI和游戏据我所知,处理统一GUI和游戏的最佳方法是设置场景大小,让SpriteKit从那里扩展.这是iPhone6的分数.因为SpriteKit在点上工作但设备以像素显示,对于@2x设备,场景大小将为750pxx1354px像素,对于iPhone6,场景大小将为1125pxx2031px.这如何与资产一起使用?对于Apple来说,这是一个更好的问题.显然,SpriteKit不支持纹理图集中的@3x图像.SO

  3. 如何在Xcode 4中自动生成Core Data GUI?

    我正在通过基于Xcode3编写的Mac上的LearnCocoa工作,我正在使用v4.到目前为止,我已经能够相当容易地找到解决差异的方法,但现在我正在介绍CoreData的一章,还有一部分关于能够通过Option从实体拖动到IB中的窗口来自动生成GUI,但我似乎无法在Xcode4中做到这一点.它仍然可能,或者那个能力是否与v3一起死亡?

  4. Swift基本使用-函数和闭包(三)

    声明函数和其他脚本语言有相似的地方,比较明显的地方是声明函数的关键字swift也出现了Python中的组元,可以通过一个组元返回多个值。传递可变参数,函数以数组的形式获取参数swift中函数可以嵌套,被嵌套的函数可以访问外部函数的变量。可以通过函数的潜逃来重构过长或者太复杂的函数。

  5. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  6. Swift、Go、Julia与R能否挑战 Python 的王者地位

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  7. 红薯因 Swift 重写开源中国失败,貌似欲改用 Python

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  8. 你没看错:Swift可以直接调用Python函数库

    上周Perfect又推出了新一轮服务器端Swift增强函数库:Perfect-Python。对,你没看错,在服务器端Swift其实可以轻松从其他语种的函数库中直接拿来调用,不需要修改任何内容。以如下python脚本为例:Perfect-Python可以用下列方法封装并调用以上函数,您所需要注意的仅仅是其函数名称以及参数。

  9. Swift中的列表解析

    在Swift中完成这个的最简单的方法是什么?我在寻找类似的东西:从Swift2.x开始,有一些与你的Python样式列表解析相当的东西。(在这个意义上,它更像是Python的xrange。如果你想保持集合懒惰一路通过,只是这样说:与Python中的列表解析语法不同,Swift中的这些操作遵循与其他操作相同的语法。

  10. swift抛出终端的python错误

    每当我尝试启动与python相关的swift时,我都会收到错误.我该如何解决?

随机推荐

  1. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  2. python数学建模之三大模型与十大常用算法详情

    这篇文章主要介绍了python数学建模之三大模型与十大常用算法详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感想取得小伙伴可以参考一下

  3. Python爬取奶茶店数据分析哪家最好喝以及性价比

    这篇文章主要介绍了用Python告诉你奶茶哪家最好喝性价比最高,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

  4. 使用pyinstaller打包.exe文件的详细教程

    PyInstaller是一个跨平台的Python应用打包工具,能够把 Python 脚本及其所在的 Python 解释器打包成可执行文件,下面这篇文章主要给大家介绍了关于使用pyinstaller打包.exe文件的相关资料,需要的朋友可以参考下

  5. 基于Python实现射击小游戏的制作

    这篇文章主要介绍了如何利用Python制作一个自己专属的第一人称射击小游戏,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起动手试一试

  6. Python list append方法之给列表追加元素

    这篇文章主要介绍了Python list append方法如何给列表追加元素,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  7. Pytest+Request+Allure+Jenkins实现接口自动化

    这篇文章介绍了Pytest+Request+Allure+Jenkins实现接口自动化的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. 利用python实现简单的情感分析实例教程

    商品评论挖掘、电影推荐、股市预测……情感分析大有用武之地,下面这篇文章主要给大家介绍了关于利用python实现简单的情感分析的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

  9. 利用Python上传日志并监控告警的方法详解

    这篇文章将详细为大家介绍如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务,感兴趣的小伙伴可以了解一下

  10. Pycharm中运行程序在Python console中执行,不是直接Run问题

    这篇文章主要介绍了Pycharm中运行程序在Python console中执行,不是直接Run问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

返回
顶部