python实现扫雷游戏的示例


Posted in Python onOctober 20, 2020

扫雷是一款益智类小游戏,最早于 1992 年由微软在 Windows 上发行,游戏适合于全年龄段,规则简单,即在最短的时间内找出所有非雷格子且在中间过程中不能踩到雷, 踩到雷则失败,需重新开始。

本文我们使用 Python 来实现扫雷游戏,主要用的 Python 库是 pygame。

实现

游戏组成比较简单,主要包括:小方格、计时器、地雷等。

首先,我们初始化一些常量,比如:横竖方块数、地雷数、鼠标点击情况等,如下所示:

BLOCK_WIDTH = 30
BLOCK_HEIGHT = 16
# 块大小
SIZE = 20
# 地雷数
MINE_COUNT = 66
# 未点击
normal = 1
# 已点击
opened = 2
# 地雷
mine = 3
# 标记为地雷
flag = 4
# 标记为问号
ask = 5
# 踩中地雷
bomb = 6
# 被双击的周围
hint = 7
# 正被鼠标左右键双击
double = 8
readied = 1,
started = 2,
over = 3,
win = 4

接着定义一个地雷类,类中定义一些基本属性(如:坐标、状态等)及 get、set 方法,代码实现如下:

class Mine:
 def __init__(self, x, y, value=0):
  self._x = x
  self._y = y
  self._value = 0
  self._around_mine_count = -1
  self._status = normal
  self.set_value(value)
 def __repr__(self):
  return str(self._value)
 def get_x(self):
  return self._x
 def set_x(self, x):
  self._x = x
 x = property(fget=get_x, fset=set_x)
 def get_y(self):
  return self._y
 def set_y(self, y):
  self._y = y
 y = property(fget=get_y, fset=set_y)
 def get_value(self):
  return self._value
 def set_value(self, value):
  if value:
   self._value = 1
  else:
   self._value = 0
 value = property(fget=get_value, fset=set_value, doc='0:非地雷 1:雷')
 def get_around_mine_count(self):
  return self._around_mine_count
 def set_around_mine_count(self, around_mine_count):
  self._around_mine_count = around_mine_count
 around_mine_count = property(fget=get_around_mine_count, fset=set_around_mine_count, doc='四周地雷数量')
 def get_status(self):
  return self._status
 def set_status(self, value):
  self._status = value
 status = property(fget=get_status, fset=set_status, doc='BlockStatus')

再接着定义一个 MineBlock 类,用来处理扫雷的基本逻辑,代码实现如下:

class MineBlock:
 def __init__(self):
  self._block = [[Mine(i, j) for i in range(BLOCK_WIDTH)] for j in range(BLOCK_HEIGHT)]
  # 埋雷
  for i in random.sample(range(BLOCK_WIDTH * BLOCK_HEIGHT), MINE_COUNT):
   self._block[i // BLOCK_WIDTH][i % BLOCK_WIDTH].value = 1
 def get_block(self):
  return self._block
 block = property(fget=get_block)
 def getmine(self, x, y):
  return self._block[y][x]
 def open_mine(self, x, y):
  # 踩到雷了
  if self._block[y][x].value:
   self._block[y][x].status = bomb
   return False
  # 先把状态改为 opened
  self._block[y][x].status = opened
  around = _get_around(x, y)
  _sum = 0
  for i, j in around:
   if self._block[j][i].value:
    _sum += 1
  self._block[y][x].around_mine_count = _sum
  # 如果周围没有雷,那么将周围 8 个未中未点开的递归算一遍
  if _sum == 0:
   for i, j in around:
    if self._block[j][i].around_mine_count == -1:
     self.open_mine(i, j)
  return True
 def double_mouse_button_down(self, x, y):
  if self._block[y][x].around_mine_count == 0:
   return True
  self._block[y][x].status = double
  around = _get_around(x, y)
  # 周围被标记的雷数量
  sumflag = 0
  for i, j in _get_around(x, y):
   if self._block[j][i].status == flag:
    sumflag += 1
  # 周边的雷已经全部被标记
  result = True
  if sumflag == self._block[y][x].around_mine_count:
   for i, j in around:
    if self._block[j][i].status == normal:
     if not self.open_mine(i, j):
      result = False
  else:
   for i, j in around:
    if self._block[j][i].status == normal:
     self._block[j][i].status = hint
  return result
 def double_mouse_button_up(self, x, y):
  self._block[y][x].status = opened
  for i, j in _get_around(x, y):
   if self._block[j][i].status == hint:
    self._block[j][i].status = normal

我们接下来初始化界面,首先生成由小方格组成的面板,主要代码实现如下

for row in block.block:
	for mine in row:
		pos = (mine.x * SIZE, (mine.y + 2) * SIZE)
		if mine.status == opened:
			screen.blit(img_dict[mine.around_mine_count], pos)
			opened_count += 1
		elif mine.status == double:
			screen.blit(img_dict[mine.around_mine_count], pos)
		elif mine.status == bomb:
			screen.blit(img_blood, pos)
		elif mine.status == flag:
			screen.blit(img_flag, pos)
			flag_count += 1
		elif mine.status == ask:
			screen.blit(img_ask, pos)
		elif mine.status == hint:
			screen.blit(img0, pos)
		elif game_status == over and mine.value:
			screen.blit(img_mine, pos)
		elif mine.value == 0 and mine.status == flag:
			screen.blit(img_error, pos)
		elif mine.status == normal:
			screen.blit(img_blank, pos)

看一下效果:

python实现扫雷游戏的示例

再接着添加面板的 head 部分,包括:显示雷数、重新开始按钮(笑脸)、显示耗时,主要代码实现如下:

print_text(screen, font1, 30, (SIZE * 2 - fheight) // 2 - 2, '%02d' % (MINE_COUNT - flag_count), red)
if game_status == started:
	elapsed_time = int(time.time() - start_time)
print_text(screen, font1, SCREEN_WIDTH - fwidth - 30, (SIZE * 2 - fheight) // 2 - 2, '%03d' % elapsed_time, red)
if flag_count + opened_count == BLOCK_WIDTH * BLOCK_HEIGHT:
	game_status = win
if game_status == over:
	screen.blit(img_face_fail, (face_pos_x, face_pos_y))
elif game_status == win:
	screen.blit(img_face_success, (face_pos_x, face_pos_y))
else:
	screen.blit(img_face_normal, (face_pos_x, face_pos_y))

看一下效果:

python实现扫雷游戏的示例

再接着添加各种点击事件,代码实现如下:

for event in pygame.event.get():
	if event.type == QUIT:
		sys.exit()
	elif event.type == MOUSEBUTTONDOWN:
		mouse_x, mouse_y = event.pos
		x = mouse_x // SIZE
		y = mouse_y // SIZE - 2
		b1, b2, b3 = pygame.mouse.get_pressed()
		if game_status == started:
			# 鼠标左右键同时按下,如果已经标记了所有雷,则打开周围一圈;如果还未标记完所有雷,则有一个周围一圈被同时按下的效果
			if b1 and b3:
				mine = block.getmine(x, y)
				if mine.status == opened:
					if not block.double_mouse_button_down(x, y):
						game_status = over
	elif event.type == MOUSEBUTTONUP:
		if y < 0:
			if face_pos_x <= mouse_x <= face_pos_x + face_size \
					and face_pos_y <= mouse_y <= face_pos_y + face_size:
				game_status = readied
				block = MineBlock()
				start_time = time.time()
				elapsed_time = 0
				continue
		if game_status == readied:
			game_status = started
			start_time = time.time()
			elapsed_time = 0
		if game_status == started:
			mine = block.getmine(x, y)
			# 按鼠标左键
			if b1 and not b3:
				if mine.status == normal:
					if not block.open_mine(x, y):
						game_status = over
			# 按鼠标右键
			elif not b1 and b3:
				if mine.status == normal:
					mine.status = flag
				elif mine.status == flag:
					mine.status = ask
				elif mine.status == ask:
					mine.status = normal
			elif b1 and b3:
				if mine.status == double:
					block.double_mouse_button_up(x, y)

我们来看一下最终实现效果:

python实现扫雷游戏的示例

总结

本文我们通过 Python 简单的实现了扫雷游戏,大家有兴趣的话,可以实际操作一下,看看自己能否排除全部的雷。

完整代码

项目地址

以上就是python实现扫雷游戏的示例的详细内容,更多关于python 扫雷的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python实现telnet客户端的方法
Apr 15 Python
在Python的Django框架中编写错误提示页面
Jul 22 Python
Python简单的制作图片验证码实例
May 31 Python
解决python中使用PYQT时中文乱码问题
Jun 17 Python
python wxpython 实现界面跳转功能
Dec 17 Python
Python代码生成视频的缩略图的实例讲解
Dec 22 Python
Python实现FLV视频拼接功能
Jan 21 Python
解决jupyter notebook import error但是命令提示符import正常的问题
Apr 15 Python
python实现自动清理重复文件
Aug 24 Python
Python爬虫如何破解JS加密的Cookie
Nov 19 Python
Python中json.load()和json.loads()有哪些区别
Jun 07 Python
Django+Celery实现定时任务的示例
Jun 23 Python
python3排序的实例方法
Oct 20 #Python
关于python tushare Tkinter构建的简单股票可视化查询系统(Beta v0.13)
Oct 19 #Python
15款Python编辑器的优缺点,别再问我“选什么编辑器”啦
Oct 19 #Python
django使用channels实现通信的示例
Oct 19 #Python
python实现测试工具(二)——简单的ui测试工具
Oct 19 #Python
python实现测试工具(一)——命令行发送get请求
Oct 19 #Python
基于Python制作一副扑克牌过程详解
Oct 19 #Python
You might like
几个有用的php字符串过滤,转换函数代码
2012/05/01 PHP
php正则提取html图片(img)src地址与任意属性的方法
2017/02/08 PHP
使用vs code编辑调试php配置的方法
2019/01/29 PHP
php 输出缓冲 Output Control用法实例详解
2020/03/03 PHP
php设计模式之模板模式实例分析【星际争霸游戏案例】
2020/03/24 PHP
extjs 学习笔记(一) 一些基础知识
2009/10/13 Javascript
js数字输入框(包括最大值最小值限制和四舍五入)
2009/11/24 Javascript
Javascript document.referrer判断访客来源网址
2020/05/15 Javascript
javascript多种数据类型表格排序代码分析
2010/09/11 Javascript
取消选中单选框radio的三种方式示例介绍
2013/12/23 Javascript
js 声明数组和向数组中添加对象变量的简单实例
2016/07/28 Javascript
不间断循环滚动效果的实例代码(必看篇)
2016/10/08 Javascript
jquery.Callbacks的实现详解
2016/11/30 Javascript
node文字生成图片的示例代码
2017/10/26 Javascript
VueJS 组件参数名命名与组件属性转化问题
2018/12/03 Javascript
详解node登录接口之密码错误限制次数(含代码)
2019/10/25 Javascript
vue组件系列之TagsInput详解
2020/05/14 Javascript
详解Python中的循环语句的用法
2015/04/09 Python
win与linux系统中python requests 安装
2016/12/04 Python
关于Python正则表达式 findall函数问题详解
2018/03/22 Python
在Python中定义一个常量的方法
2018/11/10 Python
python自动化工具之pywinauto实例详解
2019/08/26 Python
pytorch中的transforms模块实例详解
2019/12/31 Python
Django 5种类型Session使用方法解析
2020/04/29 Python
Python使用OpenPyXL处理Excel表格
2020/07/02 Python
Python3+Appium安装及Appium模拟微信登录方法详解
2021/02/16 Python
基于HTML5的WebGL实现json和echarts图表展现在同一个界面
2017/10/26 HTML / CSS
存储过程的优点有哪些
2012/09/27 面试题
室内设计实习自我鉴定
2013/09/25 职场文书
文秘专业应届生求职信范文
2013/11/14 职场文书
党员创先争优活动总结
2014/05/04 职场文书
党员承诺书范文
2014/05/19 职场文书
客运企业隐患排查工作方案
2014/06/06 职场文书
六年级上册《闻官军收河南河北》的教学设计
2019/11/15 职场文书
Vue的生命周期一起来看看
2022/02/24 Vue.js
Java 使用类型为Object的变量指向任意类型的对象
2022/04/13 Java/Android