用python实现扫雷游戏

news2024/9/19 10:39:29

前言

本人最近在学习python语言,发现python是一门很有意思的语音。python有大量的库,大量的函数,可以实现非常多的功能。尤其是在可视化方面,可以画图,可以弹出窗口。于是我就想着看能不能用python编写一个扫雷游戏。我看网上很多用python实现的扫雷游戏,都用了很多类(class)的知识。但是由于我对于类的掌握不太好,所以我没有采用类的写法,而是采用在函数中调用全局变量的做法来实现一些功能。

扫雷介绍

《扫雷》是一款大众类的益智小游戏,于1992年发行。游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。其规则简单易上手。

设计与分析

为了实现游戏的功能,首先引入tkinter库。该库可以实现建立窗口、弹窗等功能,很适合用在扫雷游戏上。游戏总体分为两个界面,目录界面和游戏界面。目录界面分为“简单”“中等”“困难”三个按钮,用于玩家选择游戏难度。在游戏界面,用一个个按钮来表示扫雷的格子。初始随机生成雷,埋在这些区域。点到不同类型的格子会有不同的结果。如果点到雷所在的格子,游戏直接结束。如果点到的是周围有雷的格子,就会显示周围的雷数。如果点到周围没有雷的格子,就利用广度优先搜索把这一片区域都显示出来。每点开一个格子,都判断一次剩下的格子数是否等于总雷数,若相等,则判定玩家获胜。然后回到目录界面,重新开始下一局游戏。
为了优化玩家游戏体验,在游戏界面新增了两个按钮“退出”和“重新开始”。退出按钮使得玩家在游戏过程中可以随时退出游戏。“重新开始”按钮可以让玩家在想调整难度或者想重置游戏的时候,回到目录界面,开始下一局游戏。

程序实现

为了帮助大家看懂代码,我在代码中加入了大量注释

from tkinter import * # 导入tkinter库,该库可以实现建立一个窗口等功能,是实现扫雷游戏的基础
from tkinter import messagebox # messagebox功能使得可以建立弹窗
import random # 用来生成初始的雷
def menu(): # 用来生成目录窗口
    mulu.title("目录") # 给窗口取名为目录
    mulu.geometry("400x400") # 设置目录窗口的大小
    anniu1 = Button(width=10, height=3, background="grey", command=lambda: zhuchengxu(10, 10, 10), text="简单")
    anniu2 = Button(width=10, height=3, background="grey", command=lambda: zhuchengxu(16, 16, 40), text="中等")
    anniu3 = Button(width=10, height=3, background="grey", command=lambda: zhuchengxu(30, 16, 99), text="困难")
    # 生成三个按钮,分别代表三种难度
    anniu1.place(x=150, y=100)
    anniu2.place(x=150, y=200)
    anniu3.place(x=150, y=300) #将三个按钮显示出来,并设定三个按钮的所在位置
    mulu.mainloop() #在目录窗口的各个参数设定完毕后,显示目录窗口
def chongqi(): # 重启函数,用于游戏的重新开始,结束游戏,回到目录窗口
    global root,b,d,mulu # 引入全局变量
    root.destroy() # 结束游戏窗口
    for i in range(100):
        for j in range(100):
            d[i][j] = 0
            b[i][j] = 0 # 将游戏中的一些参数重置
    mulu=Tk() # 建立新的目录窗口
    menu() # 重新建立目录窗口
def check(kuan,gao,lei): # check函数用于判断游戏是否获胜
    global d,root
    rest = kuan*gao #所有的格子数共有这么多个
    for i in range(kuan):
        for j in range(gao):
            rest -= d[i][j] # 计算没被点开的方块数
    if rest == lei: # 如果没被点开的方块数等于雷的数量,说明游戏获胜了
        messagebox.showinfo('提示信息', '恭喜你,游戏胜利!') # 弹出提示框,告知游戏获胜
        chongqi() # 游戏获胜,重启游戏
def f(i,j,kuan,gao,lei): # f函数是在玩家点击(i,j)方块后,判断应该给出什么反馈
    global a,b,d
    if b[i][j]==-1: # 表示该方块为雷
        messagebox.showinfo('提示信息', 'Game Over') # 告知玩家游戏结束
        chongqi() # 游戏输了,重启游戏
        return
    if b[i][j]>0: # b[i][j]>0表示该点附近有几个雷
        a[i][j]=Button(width=3,height=1,background="white",text=str(b[i][j])) # 把该方块点开,显示出数字,表示该方块附近有几个雷
        a[i][j].place(x=50 + 30 * i, y=100 + 30 * j) # 新按钮覆盖原按钮
        d[i][j]=1 # 表示该方块已被点击
        check(kuan,gao,lei) # 判断游戏是否获胜
        return
    if b[i][j]==0: # 表示该方块附近没有雷,则需要显示一大片区域
        h=0
        c=[] # 建立广搜的队列
        c.append([i,j]) # 该方块自己先进队
        b[i][j]=-9 # 在一大片区域中,b[i][j]的范围是0~7,于是以b[i][j]-9来识别该点是否入队,若为负数则已入队,若为正数则未入队
        while h<len(c): # 广度优先搜索,把这一片区域都显示出来
            i,j=c[h] # 获取队头的方块位置
            if b[i][j]>-9: # 表示该方块原来的数字大于0,那么该方块为广搜边界,应该停止
                a[i][j] = Button(width=3, height=1, background="white",text=str(b[i][j]+9)) # 把该方块的数字显示出来
                a[i][j].place(x=50 + 30 * i, y=100 + 30 * j)
                d[i][j]=1 # 标记该方块已被点击
                h=h+1
                check(kuan,gao,lei) # 每一步都要判断游戏是否获胜
                continue
            a[i][j] = Button(width=3, height=1, background="white") # 做到这里表示该方块周围没有雷,那么应该继续往8个方向扩展
            a[i][j].place(x=50 + 30 * i, y=100 + 30 * j) # 先把该方块显示出来
            d[i][j]=1
            if i - 1 >= 0 and j - 1 >= 0 and b[i - 1][j - 1] >= 0: # 往8个方向搜索
                c.append([i-1,j-1])
                b[i-1][j-1]-=9
            if i - 1 >= 0 and b[i - 1][j] >= 0:
                c.append([i-1,j])
                b[i-1][j]-=9
            if i - 1 >= 0 and j + 1 < gao and b[i - 1][j + 1] >= 0:
                c.append([i-1,j+1])
                b[i-1][j+1]-=9
            if j - 1 >= 0 and b[i][j - 1] >= 0:
                c.append([i,j-1])
                b[i][j-1]-=9
            if j + 1 < gao and b[i][j + 1] >= 0:
                c.append([i,j+1])
                b[i][j+1]-=9
            if i + 1 < kuan and j - 1 >= 0 and b[i + 1][j - 1] >= 0:
                c.append([i+1,j-1])
                b[i+1][j-1]-=9
            if i + 1 < kuan and b[i + 1][j] >= 0:
                c.append([i+1,j])
                b[i+1][j]-=9
            if i + 1 < kuan and j + 1 < gao and b[i + 1][j + 1] >= 0:
                c.append([i+1,j+1])
                b[i+1][j+1]-=9
            h=h+1
def zhuchengxu(kuan,gao,lei): # 这个函数是该程序最主要的程序,kuan和gao表示扫雷区域的宽和高,lei表示总雷数
    global root,mulu
    mulu.destroy() # 先把目录窗口关闭
    root=Tk() # 再建立新的游戏窗口
    root.title("扫雷") # 给游戏窗口命名为扫雷
    x=40*kuan
    y=40*gao
    root.geometry(str(x)+"x"+str(y)) # 根据扫雷区域的大小计算窗口大小
    i=1
    while i<=lei: # 埋雷
        x=random.randrange(kuan*gao)
        if b[x//gao][x%gao]==-1: # b[i][j]=-1表示这个点是雷
            continue
        b[x // gao][x %gao] = -1
        i=i+1
    for i in range(kuan): # 计算每个方块周围有几个雷,用b[i][j]来标记
        for j in range(gao):
            if b[i][j]==-1:
                continue
            x=0
            if i-1>=0 and j-1>=0 and b[i-1][j-1]==-1:
                x=x+1
            if i-1>=0 and b[i-1][j]==-1:
                x=x+1
            if i-1>=0 and j+1<gao and b[i-1][j+1]==-1:
                x=x+1
            if j-1>=0 and b[i][j-1]==-1:
                x=x+1
            if j+1<gao and b[i][j+1]==-1:
                x=x+1
            if i+1<kuan and j-1>=0 and b[i+1][j-1]==-1:
                x=x+1
            if i+1<kuan and b[i+1][j]==-1:
                x=x+1
            if i+1<kuan and j+1<gao and b[i+1][j+1]==-1:
                x=x+1
            b[i][j]=x
    for i in range(kuan): # 生成方块
        for j in range(gao):
            x=3
            y=1
            a[i][j]= Button(width=x,height=y,background="grey",command=lambda x1=i,y1=j:f(x1,y1,kuan,gao,lei))
            a[i][j].place(x=50+30*i, y=100+30*j) # 用按钮表示方块,把按钮紧密排列,就变成了一片扫雷阵
    Button(text='退出', command=lambda:root.destroy()).pack(anchor='ne') # 建立一个退出按钮,不想玩了可以直接退出游戏
    Button(text='重新开始', command=lambda: chongqi()).pack(anchor='ne') # 建立一个重新开始按钮,可以回到目录窗口重新选择难度
    root.mainloop() # 生成扫雷阵之后,显示出来
a = [[0 for j in range(100)] for i in range(100)] # 这里开始才是主程序,定义了一些全局变量,方便后续的使用
b = [[0 for j in range(100)] for i in range(100)]
d = [[0 for j in range(100)] for i in range(100)]
root=0 # root表示游戏窗口
mulu=Tk() # 新建一个窗口
menu() # 先出现目录,再开始游戏

结果展示

以下是游戏的一些界面展示:
目录
简单
游戏获胜
中等
困难

总结

这个扫雷是一个比较粗糙的实现。在一般的扫雷中,还有一些其它功能,如右键标记雷;单击已点开的数字格子,周边的格子会闪一下,若其周边的雷都被正确标记,则会自动显示出其周边不是雷的区域。由于tkinter中的按钮无法区分左键点击和右键点击,故该功能暂时无法实现。该程序仅仅提供了一个制作游戏的思路,毕竟谁会真的拿我的代码来玩扫雷呢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/715444.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5. 创建声卡

代码位置 sound/soc/generic/simple-card.c static int asoc_simple_card_probe(struct platform_device *pdev) {...ret devm_snd_soc_register_card(dev, card);... } asoc_simple_card_probe -> devm_snd_soc_register_card -> snd_soc_register_card int snd_soc_r…

MS1825 SDK 移植指南

1. 概述 MS1825 SDK 支持以下 Macrosilicon 芯片&#xff0c;按照芯片功能组合的不同&#xff0c; SDK 中相关 API 和类型的定义有所 不同&#xff0c;请在该文档 API 和类型说明时特别关注&#xff1a; MS1825 SDK 的作用是帮助用户建立基于 MS1825 的视频输入输…

力扣 17. 电话号码的字母组合

题目来源&#xff1a;https://leetcode.cn/problems/letter-combinations-of-a-phone-number/description/ C题解&#xff1a; 递归法。 确定回溯函数参数&#xff1a;首先需要一个字符串s来收集叶子节点的结果&#xff0c;一个字符串数组result保存起来&#xff0c;定义为全局…

78-基于stm32单片机电压电流检测LCD1602显示(程序+原理图+元件清单全套资料)...

资料编号&#xff1a;078 功能介绍&#xff1a;采用stm32单片机作为主控CPU&#xff0c;采用精密电阻分压将高电压分压后接入STM32单片机ADC接口&#xff0c;采用ADC可以采集出当前的电压值&#xff0c;通过功率电阻来测量电路中的电流&#xff0c;通过串联电路电流相同的原理&…

正则表达式 教程与简介 | 一看就懂!!!(一)

目录 一、正则表达式 - 教程 二、 正则表达式的模式 &#xff08;一&#xff09;字面值字符 &#xff08;二&#xff09;特殊字符 &#xff08;三&#xff09;字符类 &#xff08;四&#xff09;元字符 &#xff08;五&#xff09;量词 &#xff08;六&#xff09;边界…

如何进行小红书笔记关键词布局,热词分析!

坐拥2.6亿活跃用户&#xff0c;小红书已经成为品牌宣推、种草的重要平台之一。那么品牌进入平台&#xff0c;如何进行小红书笔记关键词布局&#xff0c;热词分析&#xff01; 一、 如何确定关键词 想要做好小红书关键词布局&#xff0c;首先要明确如何确定关键词。 1、当我们要…

shell判断程序是否运行,守护进程

一、需求 服务部署在linux上&#xff0c;要求服务器上的服务可以一直保持正常运行 二、问题 在linux上部署的微服务&#xff0c;不知道什么原因过一段时间就自己停掉了&#xff0c;无法启动。 三、解决办法 添加angle守护进程&#xff0c;通过定时执行脚本来判断程序是否运行…

为什么对ChatGPT、ChatGLM这样的大语言模型说“你是某某领域专家”,它的回答会有效得多?(一)...

“ 太长不看总结版&#xff1a;LLM大模型的本质在于计算某个词汇后面应该跟着哪些词汇的概率。当问题给定了特定的限定范围后&#xff0c;它能够找到一条相对明确的计算路径&#xff0c;从一系列概率分布中挑选出所需的答案。否则&#xff0c;它会根据最常见且最高概率的组合方…

浑元太极马老师和小薇-UMLChina建模知识竞赛第4赛季第7轮[更新]

DDD领域驱动设计批评文集 欢迎加入“软件方法建模师”群 《软件方法》各章合集 参考潘加宇在《软件方法》和UMLChina公众号文章中发表的内容作答。在本文下留言回答。 第7轮一直无人得分&#xff0c;再次更换题目。 因有的题目之前已经出过&#xff0c;本轮需要最先答对全…

聊天室(二)__ unipush 推送如何实现?

你想搞个自己的聊天室 app 吗&#xff1f;好多前端同学会好奇聊天室app的推送是怎么搞的&#xff1f;今天就以前端同学使用最多的 uniapp 开发的 app 推送为例&#xff0c;悄悄告诉大家推送是如何实现的&#xff01; 项目技术栈&#xff1a; 项目基于 vue3 的 uniapp 推送基于…

从小白到大神之路之学习运维第51天---第三阶段----redis高可用集群数据库的安装部署

第三阶段基础 时 间&#xff1a;2023年7月3日 参加人&#xff1a;全班人员 内 容&#xff1a; 生产级redis cluster部署 目录 一、环境配置&#xff1a;【两台服务器】 二、redis多实例配置&#xff1a; 三、构建redis cluster集群 四、生产集群部署 五、集群故障切…

Makefile:1: *** 遗漏分隔符 (null)。 停止。解决方法

在使用ubuntu时&#xff0c;make命令后&#xff0c;直接弹出了个错误。。。。。。 Makefile: n n表示出问题的行数&#xff0c;仔细检查代码的内容&#xff0c;主要问题可能是该有的空格是否添加或者使用$引入的参数是否存在等 我的问题是这个 ifneq 后面的空格没有加 耐心查…

论文浅尝 | 大语言模型综述

笔记整理&#xff1a;刘康为、方润楠&#xff0c;浙江大学硕士&#xff0c;研究方向为自然语言处理 链接&#xff1a;https://arxiv.org/abs/2303.18223 一、介绍 在当前机遇和挑战的背景下&#xff0c;对大语言模型的研究和开发需要更多的关注。为了让读者对大语言模型有一个基…

C++实现打包工具代码框架(附源码)

C++常用功能源码系列 文章目录 C++常用功能源码系列前言一、打包工具二、packtool框架前言 本文是C/C++常用功能代码封装专栏的导航贴。部分来源于实战项目中的部分功能提炼,希望能够达到你在自己的项目中拿来就用的效果,这样更好的服务于工作实践。 专栏介绍:专栏讲本人近…

windows10安装wsl2,centos内核

windows10安装wsl2&#xff0c;centos内核 检查系统环境 必须运行 Windows 10 版本 2004 及更高版本&#xff08;内部版本 19041 及更高版本&#xff09;或 Windows 11 才能使用以下命令。 一、开启WSL2特性 【控制面板】>>【程序】>>【程序和功能】>>【启…

apple pencil平替笔哪个好用?适用于绘画的电容笔推荐

由于ipad的版本一直在升级&#xff0c;其功能也在增加&#xff0c;其功能已经达到了与手提电脑相媲美的程度。而且随着科技的发展&#xff0c;ipad也不仅仅是一个娱乐的工具&#xff0c;更是一个可以用来学习、画画、工作的强大工具。想要提高生产力&#xff0c;那么电容笔就是…

mysql 8.0版本更换用户密码

1、首先 cmd 进入命令行 mysql -uroot -p 2、查询版本号 select version(); 3、看一下数据库 show databases; 4、使用mysql即可 5、进行查询 user、host select user,host from user; 6、修改root的密码 alter user root% identified by 1234; 7、刷新权限 flush privi…

Kubernetes 服务发布方式(蓝绿发布、灰度发布和滚动发布)

目录 一、三种常用的项目发布方式1.1 蓝绿发布1.2 灰度发布&#xff08;金丝雀发布&#xff09;1.3 滚动发布 二、金丝雀的方式升级发布实验三、总结 一、三种常用的项目发布方式 应用程序升级面临最大挑战是新旧业务切换&#xff0c;将软件从测试的最后阶段带到生产环境&…

Windows服务器——部署WSUS服务与综合测试

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​ 目录 前言 本章结构&#xff1a; 一.WSUS概述 1.WSUS概述 2.WSUS的特点 3.WSUS常见部署…

fastboot连接@设备识别问题

文章目录 fastboot模式(MIUI)界面变换fastboot链接电脑设备识别问题连接部件的兼容性 fastboot模式(MIUI)界面变换 老设备新设备 fastboot链接电脑设备识别问题 通常一根普通的数据线和PC就能够识别处于fastboot(bootloader)模式下的android设备 扫描已连接的bootloader模式…