代码已更新

  • 添加了颜色表示数字
  • 画了方格线

一、运行环境

我的环境:

  1. python 3.6.8
  2. pygame 1.9.6
  3. windows 10

二、游戏规则

介绍

游戏开始,你将会看到一个个整齐排列的小方块,在这些小方块中,埋藏的有若干随机分布的炸弹。每当你点击一个方块,如果不是地雷埋藏点你将会得到一个数字,该数字表示以你点击的方块为中心的九宫格内一共有的炸弹数量,或者它周围一圈的炸弹数量如图:


灰色部分表示未点击的方块,X表示你所得到的数字,最小为0,最大为8,表示周围这些灰色方块中藏有的炸弹数。特别的当你点击的方块在界面的边界处时,如下图红色线所在的方块中,
仍然是以你点击的方块为九宫格中心,只不过边界外的方块炸弹数都认为是零。当你点击的方块为零时,该方块周围的方块都会自动被打开。 如果它周围的方块也出现了一个炸弹为零的方块,该方块周围的方块也会被自动打开。如下图所示:
我们点击箭头所示处,数字为零的格子周围一圈的格子都会自动打开。

游戏失败

扫雷游戏中当你点击的格子是埋藏地雷的位点,游戏便失败。

游戏胜利

当你给所有埋藏地雷的点插上红旗即游戏胜利。

三、代码思路

界面

根据游戏规则,我们需要如下主要界面:

界面 描述
主界面 包含游戏开始退出等选项的菜单界面
游戏开始界面 游戏执行界面,绘制游戏所需图形元素,接收鼠标消息
游戏胜利界面 游戏胜利后执行的界面,包含两个简单的选项,重新开始或退出
游戏失败界面 游戏失败后执行的界面,包含两个简单的选项,重新开始或退出

图形元素

  1. 扫雷方块,RGB(112, 128, 144);

  2. 0-9数字;

  3. 炸弹;

  4. 红旗;

  5. 主界面背景图;

游戏执行流程

在整个流程中比较重要的部分是游戏开始,该流程中我们需要绘制扫雷区域,根据用户的行为执行各种游戏判定,包括绘制相应的图形元素,以及这些图形元素背后变量的逻辑变化等。

核心思想

GRID&GRID2数组

我们可以构建两个10x10的二元数组,GRIDGRID2 前者中以10-19 10个数字表示该点周围的炸弹数量0-9,以数字4表示炸弹。后者填充数字 0120表示该方块未被点击,1表示被点击,2表示该位置被插上了红旗。

Draw()函数

代码块中的 Draw() 函数通过读取 GRIDGRID2 中的数字在游戏开始界面上相应位置上绘制对应的图形元素。其中我们规定,只有 GRID2 上数字不为零时,我们才可以在相应位置上绘制炸弹数量和炸弹,其中若为2则表示该位置已经插上红旗,不能点击。

Start()函数

该函数表示游戏的主函数,包括接收鼠标消息判断点击位置并在 GRID&GRID2 对应的索引处更新数字。

鼠标 描述
左键 点击动作,将GRID2相应索引处修改值为1
右键 插旗动作,将GRID2相应索引处修改值为2

那么如何根据鼠标点击的位置来判断GRID&GRID2的索引值?
我们可以假设,方块的大小为60x60 ,那么游戏开始界面中方块的横纵坐标 (x,y) 便等于数组的列索引 i ,行索引 j (ix60,jx60),相应的,当游戏界面接收到一个鼠标点击消息后,获取鼠标在界面上的点击位点 (X,Y)(X//60,Y//60) 便是数组对应位置的索引。“//”表示取整。

四、完整代码展示

#python3
#author:LEIWEI
#Date:11/11/2020
#update:12/24/2020
import pygame as pg
import random
import time#------------------------------
#set key vars
SIZE=20
HEIGHT=30
WIDTH=30
BOMBS=15
BLOCKSIZE=60
NDraft=18
GRIDx,GRIDy=0,0
HaveLocate=[]
FLAGLOCATE=[]
USERBOMBS=0
ACTIVE=1
Bounder=[[i+2.5,i+600] for i in range(0,660,60)]#color vars
SlateGrey=(112, 128, 144)
white=(255,255,255)
red=(255,0,0)
green=(0,255,0)
yellow=(255,255,0)
blue=(0,0,255)
black=(0,0,0)
ColorDict={"0":white,"1":blue,"2":green,"3":yellow,"4":red,"5":red,"6":red,"7":red,"8":red,}#Image
BOMBIMAGE=pg.image.load(r"bomb.png")
FLAGIMAGE=pg.image.load(r"flag2.jpg")
BACKIMAGE=pg.image.load(r"backimage.jpg")
BOMBIMAGE=pg.transform.scale(BOMBIMAGE,(55,55))
FLAGIMAGE=pg.transform.scale(FLAGIMAGE,(55,55))
BACKIMAGE=pg.transform.scale(BACKIMAGE,(600,600))#pygame object init
pg.init()
window=pg.display.set_mode((WIDTH*SIZE+10,HEIGHT*SIZE+10),0,32)#font drawing the number of bomb in your click pos
N="?"#the speed of update
normal=30
clock=pg.time.Clock()#ground
#0->unopen
#1->open:N->the number of bomb in your click pos
#2->flag
#3->?
#4->bomb
GRID=[[0 for x in range(10)]for y in range(10)]  #remain
GRID2=[[0 for x in range(10)]for y in range(10)] #open and not open flag 0&1&2def GameInit():global BOMBI,GRID,HaveLocate,FLAGLOCATE,ACTIVE,GRID2,USERBOMBS,BOMBSHaveLocate=[]FLAGLOCATE=[]USERBOMBS=0ACTIVE=1GRID=[[0 for x in range(10)]for y in range(10)]  GRID2=[[0 for x in range(10)]for y in range(10)] #--------------------#the mine posBOMBI=0while BOMBI<BOMBS:bombx,bomby=random.randrange(10),random.randrange(10)if GRID[bomby][bombx]!=4:GRID[bomby][bombx]=4BOMBI+=1#--------------------#cal bomb num in aroundfor y in range(10):for x in range(10):bombNums=0if GRID[y][x]!=4:x0,y0=x-1,y-1for i in range(3):for j in range(3):if x0+j>=0 and y0+i>=0 and x0+j<10 and y0+i<10 :#print("x0=%d\ty0=%d"%(x0+j,y0+i))if GRID[y0+i][x0+j]==4:bombNums+=1GRID[y][x]=10+bombNumsdef Draw():global GRID2,window,pg,ACTIVE,BounderH,BounderVwindow.fill(white)for y in range(10):for x in range(10):#unopen<->if GRID2[y][x]==0:pg.draw.rect(window,SlateGrey,(x*BLOCKSIZE+5,y*BLOCKSIZE+5,BLOCKSIZE-5,BLOCKSIZE-5))#unopen - flagelif GRID2[y][x]==2:window.blit(FLAGIMAGE,(x*BLOCKSIZE+5,y*BLOCKSIZE+5,BLOCKSIZE-5,BLOCKSIZE-5))#openelif GRID2[y][x]==1:if GRID[y][x]>=10:N=str(GRID[y][x]-10)Nfont=pg.font.SysFont(None,75)Ntext=Nfont.render(N,True,ColorDict[N],white)pg.draw.rect(window,white,(x*BLOCKSIZE+5,y*BLOCKSIZE+5,BLOCKSIZE-5,BLOCKSIZE-5))window.blit(Ntext,(x*BLOCKSIZE+NDraft,y*BLOCKSIZE+5))elif GRID[y][x]==4:window.blit(BOMBIMAGE,(x*BLOCKSIZE+5,y*BLOCKSIZE+5,BLOCKSIZE-5,BLOCKSIZE-5))for H in Bounder:pg.draw.line(window,black,(H[0],5),(H[0],H[1]))pg.draw.line(window,black,(5,H[0]),(H[1],H[0]))pg.display.update()if ACTIVE==0:GameOver()pg.display.update()#--------------------------------------
#This function will be target,while you click pos that its number
#   >=10,if you get the number zero you will open a lager aera centre
#   you have clicked pos
def OpenAera(x,y,bombs):global GRID2,GRID,HaveLocateHaveLocate.append([x,y])GRID2[y][x]=1x0,y0=x-1,y-1if bombs==10:for i in range(3):for j in range(3):if x0+j>=0 and y0+i>=0 and x0+j<10 and y0+i<10:if GRID2[y0+i][x0+j]!=2:GRID2[y0+i][x0+j]=1if GRID[y0+i][x0+j]==10 and [x0+j,y0+i] not in HaveLocate:OpenAera(x0+j,y0+i,GRID[y0+i][x0+j])#----------------------------------------
#This function will be target,while you click a bombs.
#   The pos of all bombs in var GRID will turn into 1 in
#   var GRID2,and draw in Draw Func
def AllBomb():global GRID2,GRIDfor y in range(10):for x in range(10):if GRID[y][x]==4:GRID2[y][x]=1def GameOver():global pg,fontPoint2=0GameOverText=["是","否"]pg.draw.rect(window,white,(200,200,300,200))restarttext=font.render("失败!!重新开始?",False,blue,white)window.blit(restarttext,(250,215))GameOverAct=[Main,exit]while True:for i in range(2):if Point2==i:text=font.render(GameOverText[i],False,blue,red)else:text=font.render(GameOverText[i],False,blue,white)window.blit(text,(285+(i*50),350))for event in pg.event.get():if event.type==12:pg.quit()exit()if event.type==2:if event.key==275:Point2+=1if Point2==2:Point2=0elif event.key==276:Point2-=1if Point2==-1:Point2=1elif event.key==13:GameOverAct[Point2]()pg.display.update()def GameWin():global GRID,GRID2,USERBOMBS,BOMBS,pg,fontif USERBOMBS==BOMBS:Point2=0GameOverText=["是","否"]pg.draw.rect(window,white,(200,200,300,200))restarttext=font.render("胜利!!重新开始?",False,blue,white)window.blit(restarttext,(250,215))GameOverAct=[Main,exit]while True:for i in range(2):if Point2==i:text=font.render(GameOverText[i],False,blue,red)else:text=font.render(GameOverText[i],False,blue,white)window.blit(text,(285+(i*50),350))for event in pg.event.get():if event.type==12:pg.quit()exit()if event.type==2:if event.key==275:Point2+=1if Point2==2:Point2=0elif event.key==276:Point2-=1if Point2==-1:Point2=1elif event.key==13:GameOverAct[Point2]()pg.display.update()#----------------------------
#Game main Func
def Start():global GRIDx,GRIDy,GRID,GRID2,ACTIVE,FLAGLOCATE,USERBOMBSwhile True:Draw()GameWin()for event in pg.event.get():#get destroy message,shutdown windowif event.type==12:pg.quit()exit()#get mouse press messageif event.type==5:#get the pos of clickingclickpos=event.posGRIDx,GRIDy=clickpos[0]//BLOCKSIZE,clickpos[1]//BLOCKSIZE#get left button,turn GRID2 corresponding pos into openif event.button==1:#bomb,you get bomb!!! bomb!!! bomb!!!if GRID[GRIDy][GRIDx]==4 and GRID2[GRIDy][GRIDx]!=2:ACTIVE=0AllBomb()#click flagelif GRID2[GRIDy][GRIDx]==2:pass#openedelif GRID2[GRIDy][GRIDx]==1:pass#click safe aera elif GRID[GRIDy][GRIDx]>=10:ACTIVE=1OpenAera(GRIDx,GRIDy,GRID[GRIDy][GRIDx])#get right buttonelif event.button==3:if GRID[GRIDy][GRIDx]==4 and [GRIDx,GRIDy] not in FLAGLOCATE:USERBOMBS+=1FLAGLOCATE.append([GRIDx,GRIDy])if GRID2[GRIDy][GRIDx]==0:GRID2[GRIDy][GRIDx]=2elif GRID2[GRIDy][GRIDx]==2:GRID2[GRIDy][GRIDx]=0elif GRID2[GRIDy][GRIDx]==1:passclock.tick(normal)#---------------------------
#Restart game Func
def Main():GameInit()Start()#---------------------------
#Game main menu Func
def Home():global Pointwhile True:window.fill(white)window.blit(BACKIMAGE,(5,5,600,600))for textI in range(3):if Point==textI:text=font.render(HomeItemText[textI],True,blue,red)else:text=font.render(HomeItemText[textI],True,blue,white)window.blit(text,(280,400+(textI*50),25,25))pg.display.update()for event in pg.event.get():if event.type==12:pg.quit()exit()if event.type==2:if event.key==274:Point+=1if Point==3:Point=0elif event.key==273:Point-=1if Point==-1:Point=2elif event.key==13:HomeAct[Point]()if __name__=="__main__":font=pg.font.SysFont("华文楷体",24,bold=True,italic=True)HomeItemText=["开始","关于","退出"]HomeAct=[Main,None,exit]Point=1textL=[]Home()

五、游戏演示

主界面

游戏界面

游戏说明

键盘操作 描述
向上移动
向下移动
向左移动
向右移动
Enter 确定
鼠标左键 打开方块
鼠标右键 插上红旗,再点击取消红旗

谢谢各位!!!

pyhon扫雷演示与讲解相关推荐

  1. MyBatis的一级缓存、二级缓存演示以及讲解,序列化异常的处理

    MyBatis的一级缓存.二级缓存演示以及讲解,序列化异常的处理 参考文章: (1)MyBatis的一级缓存.二级缓存演示以及讲解,序列化异常的处理 (2)https://www.cnblogs.co ...

  2. layer php弹出层,layer官方演示与讲解(jQuery弹出层插件)

    特别说明:事件需自己绑定,以下只展现调用代码. //初体验 layer.alert('内容') //第三方扩展皮肤 layer.alert('内容', { icon: 1, skin: 'layer- ...

  3. C语言实现扫雷完整代码讲解

    扫雷是一款初学者能用C语言实现的益智小游戏,只需要用二维数组操作雷区即可. 算法详讲 : 游戏思路如下:点击雷区中的任一格子,如果该格子有雷,则游戏结束:如果该格子周围9个格子都不是雷,那么直接展开其 ...

  4. 转】PPT带备注演示(只有讲解者看到备注)[转载]

    --带备注演示,讲解者可以看到备注,观众看不到. 想实现PPT带备注的演示吗?这种方式只有讲解者自己能够看到备注内容,而观 看PPT演示的人看不见,如下 图所示: 要实现这种放映方式只需要简单的两步: ...

  5. 扫雷计算机教案,《扫雷游戏》教学设计

    一. 导入 纸牌游戏我们已经玩的很熟悉了,今天又有一个新游戏向我们挑战--扫雷 还记得进入纸牌游戏的方法吗?扫雷游戏的进入方法和它一样. 学生操作进入"扫雷"游戏. 二.讲授与讨论 ...

  6. Python小项目——学生信息管理系统(详细讲解)

    目录 一.需求分析 1.学生管理系统应具备的功能 二.系统设计 1.系统功能结构 2.系统业务流程 三.系统开发必备工具 1.系统开发环境 2.项目目录结构 四.主函数设计 1.系统主界面运行效果图 ...

  7. jbox ajax,JBox演示30种不同的调用方法

    jBox 是一款基于 jQuery 的多功能对话框插件,有alert警告框.confirm确认框和prompt输入对话框等,并且兼容 IE6+.Firefox.Chrome.Safari.Opera ...

  8. C语言实现简单扫雷游戏

    前言: 相信大家对于扫雷都不陌生,但如果用C语言该如何实现呢? 原理介绍: 首先我们得了解扫雷游戏的原理,在一个格子数长宽相同的大正方形中随机布置雷,当我们点开一个小方格时如果此小格不是雷将显示以此方 ...

  9. 网站策划方案写作、演示标准

    一份成功的网站策划方案是赢得订单的重要砝码,如何写一份令客户心动的网站策划方案则需要下苦功夫.<网站策划方案写作.演示标准>主要分为7个部分,希望对您有帮助: 1. 网站策划方案的价值-- ...

最新文章

  1. 【转】Linux世界驰骋——文件系统和设备管理
  2. 高效排序算法(快排序)
  3. 论坛答疑SQL(二)
  4. 《系统集成项目管理工程师》必背100个知识点-77配置审计的功能
  5. OpenAI 挑战《索尼克》,阿里南大队如何一举夺魁?
  6. js如何判断一个对象是不是Array
  7. 在删除一个指针之后,一定将该指针设置成空指针(即在delete *p之后一定要加上: p=NULL)...
  8. 剑指offer之求二叉树中两个节点的最低共同父节点
  9. 嵌入式Jetty和Apache CXF:借助Spring Security来保护REST服务
  10. UVA 11557 - Code Theft (KMP + HASH)
  11. python邮件图片加密软件_用Python发一封图文并茂的邮件
  12. 使用decode函数
  13. SpringBoot日记——日志框架篇
  14. UE4之cmd调用函数
  15. 〖Linux〗VirtualBox修改虚拟电脑硬盘(vdi)空间大小
  16. 洛谷3067 BZOJ 2679题解(折半搜索)
  17. Linux 如何生成文件的MD5值(md5sum)?
  18. 网络应用程序的架构:C/S架构、B/S架构的区别与优缺点
  19. Windows驱动认证
  20. 14、UI_02拨号盘动画

热门文章

  1. matlab模拟短波天波,短波的天波传播衰减预测模型
  2. safari下载文件后缀多添加了.exe的解决方法
  3. 51单片机的银行排队呼叫系统设计
  4. VS2017 winform开发知识点汇总
  5. 人工智能相关思维导图
  6. 计算机组成与系统结构——期末复习
  7. 【华为 OJ】密码验证合格程序
  8. 传统bios安装linux分区,传统BIOS传统MBR分区,Clover硬盘安装基础教程
  9. HTML5期末大作业:生鲜超市网站设计——生鲜超市网站设计(5页)HTML+CSS+JavaScript 学生DW网页设计作业成品 美食站
  10. vscode 样式字体粗细颜色自定义