本文代码基于 python3.6 和 pygame1.9.4。
这次,我们来模仿做一个 XP 上的扫雷,感觉 XP 上的样式比 win7 上的好看多了。

原谅我手残,扫雷基本就没赢过,测试的时候我是偷偷的把雷的数量从99改到50才赢了。。。
下面将一下我的实现逻辑。
首先,如何表示雷和非雷,一开始想的是,建立一个二维数组表示整个区域,0表示非地雷,1表示地雷。后来一想不对,还有标记为地雷,标记为问号,还有表示周边雷数的数字,好多状态,干脆就做个类吧
class BlockStatus(Enum): normal = 1 # 未点击 opened = 2 # 已点击 mine = 3 # 地雷 flag = 4 # 标记为地雷 ask = 5 # 标记为问号 bomb = 6 # 踩中地雷 hint = 7 # 被双击的周围 double = 8 # 正被鼠标左右键双击 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 = BlockStatus.normal self.set_value(value) def __repr__(self): return str(self._value) # return f'({self._x},{self._y})={self._value}, status={self.status}' 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') 复制代码
布雷就很简单了,随机取99个数,从上往下顺序排就是了。
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 复制代码
我们点击一个格子的时候,只要根据点击的坐标,找到对应的 Mine,看它的值是多少,就知道有没有踩中雷了。
如果没踩中雷的话,要计算周边8个位置中有几个雷,以便显示对应的数字。
如果周边有雷,那么显示数字,这个简单,可是如果周边没有雷,那就要显示一片区域,直到有雷出现,如下图,我只点了当中一下,就出现了那么大一片区域

这个计算其实也容易,只要用递归就可以了,如果计算出周围的雷数为0,则递归计算周边8个位置的四周雷数,直到雷数不为0。
class MineBlock: def open_mine(self, x, y): # 踩到雷了 if self._block[y][x].value: self._block[y][x].status = BlockStatus.bomb return False # 先把状态改为 opened self._block[y][x].status = BlockStatus.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 _get_around(x, y): """返回(x, y)周围的点的坐标""" # 这里注意,range 末尾是开区间,所以要加 1 return [(i, j) for i in range(max(0, x - 1), min(BLOCK_WIDTH - 1, x + 1) + 1) for j in range(max(0, y - 1), min(BLOCK_HEIGHT - 1, y + 1) + 1) if i != x or j != y] 复制代码
接下来还有一个麻烦的地方,我们经常鼠标左右键同时按下,如果雷被全部标记,则会一下子打开周围所有的格子,如果其中有标记错的,那么不好意思,GAME OVER。
如果没有全标记完,会有一个效果显示周围一圈未被打开和标记的格子
class MineBlock: def double_mouse_button_down(self, x, y): if self._block[y][x].around_mine_count == 0: return True self._block[y][x].status = BlockStatus.double around = _get_around(x, y) sumflag = 0 # 周围被标记的雷数量 for i, j in _get_around(x, y): if self._block[j][i].status == BlockStatus.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 == BlockStatus.normal: if not self.open_mine(i, j): result = False else: for i, j in around: if self._block[j][i].status == BlockStatus.normal: self._block[j][i].status = BlockStatus.hint return result def double_mouse_button_up(self, x, y): self._block[y][x].status = BlockStatus.opened for i, j in _get_around(x, y): if self._block[j][i].status == BlockStatus.hint: self._block[j][i].status = BlockStatus.normal 复制代码
扫雷的主要逻辑就这么多,剩下来的就是一些杂七杂八的事件了。

扫雷打开的初始区域递归_Python:游戏:写一个和 XP 上一模一样的“扫雷”!相关推荐

  1. java递归怎么写_什么是递归?用Java写一个简单的递归程序

    什么是递归?用Java写一个简单的递归程序 递归的定义 递归(recursion):以此类推是递归的基本思想,将规模大的问题转化为规模小的问题来解决. 递归的要素 自定义递归函数,并确定函数的基本功能 ...

  2. 下面属于python内置对象的有哪些_python练习题-写一个函数,打印所有包含copy方法的内置对象...

    代码: #encoding=utf-8 for i in dir(__builtins__): #print "i:",i try: #这里的i是个字符串,并不能直接用dir(i) ...

  3. 递归学习:写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和;递归实现n的k次方

    写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和. 例如,调用DigitSum(1729),则应该返回1+7+2+9,它的和是19 输入:1729,输出:19 #inclu ...

  4. 用迭代和递归方式分别写一个兔子生育的python程序(斐波那契数列)

    问题: 有一对兔子出生,从第三月起,每个月生一对兔子,出生的兔子也是第三月起每个月生一对兔子,请问n年后,共有多少只兔子? 月份 1 2 3 4 5 6 7 8 9 10 - n 数量(对) 1 1 ...

  5. python拼写检查_Python 怎样写一个拼写检查器

    例子import re, collections    def words(text): return re.findall('[a-z]+', text.lower())     def train ...

  6. python怎么设置回文数_python如何写一个函数判断回文数?

    python如何写一个函数判断回文数? python写一个函数判断回文数的方法: 设n是一任意自然数.若将n的各位数字反向排列所得自然数n1与n相等,则称n为一回文数.例如,若n=1234321,则称 ...

  7. python回文数判定_python如何写一个函数判断回文数?

    python如何写一个函数判断回文数? python写一个函数判断回文数的方法: 设n是一任意自然数.若将n的各位数字反向排列所得自然数n1与n相等,则称n为一回文数.例如,若n=1234321,则称 ...

  8. python 游戏扫雷_Python游戏:扫雷

    原标题:Python游戏:扫雷 本文代码基于 python3.6 和 pygame1.9.4. 这次,我们来模仿做一个 XP 上的扫雷,感觉 XP 上的样式比 win7 上的好看多了. 原谅我手残,扫 ...

  9. 使用C语言写一个扫雷小游戏

    前言 相信扫雷游戏小伙伴们肯定都玩过吧,学习了C语言中的数组.函数等基础内容之后就可以自己写一个简易的扫雷小游戏了,今天就我写扫雷小游戏的过程及思路写一篇博客,希望大家看完我的博客能有所收获. 软件及 ...

最新文章

  1. poj 1904 King's Quest
  2. Javascript调试技巧整理
  3. 归并排序改良 java_Java 八种排序算法总结
  4. 12个月大厂主机免费领AWS Azure Google-Cloud还不快到碗里来
  5. matlab打开矩阵表,如何将Excel数据导入MATLAB中?:EXCLE中通过矩阵表输出选项
  6. c性能大容量cket_5千左右预算,既轻薄(高颜值)又高性能的笔记本推荐(畅玩LOL、CF、DNF、流放之路、梦幻西游)...
  7. 单片机c语言程序设计软件下载,《手把手教你学单片机C程序设计》PDF免费版下载...
  8. IDEA初学者 常用注解意思
  9. Windows——如何关闭笔记本自带键盘
  10. Java征兵系统(可拓展)
  11. mac charles网页代理https使用笔记
  12. LeetCode 6036. 构造字符串的总得分和
  13. IntelliJ IDEA如何修改版权信息
  14. 编程c语言差商表,计算方法C语言编程总汇.doc
  15. 每周读书#6 - 《写给大家的中国美术史》
  16. Keras深度学习实战——使用深度Q学习进行SpaceInvaders游戏
  17. 《密码学系列》—信息安全威胁
  18. method ID not in [0, 0xffff]: 65536” error解决办法
  19. 倾我万缕柔情,共你一帘幽梦
  20. 类型多样的鸡尾酒免抠摄影素材,速来收藏

热门文章

  1. 2016年《大数据》杂志调查问卷
  2. 【计算机科学基础】计算机概述
  3. 兔八哥与猎人(洛谷P1170题题解,Java语言描述)
  4. 洛谷入门题P1046、P1047、P1427、P1428、P2141、P1567题解(Java语言描述)
  5. Scrapy 爬虫框架初体验三 —— 工程优化及其完善
  6. 光栅图形学算法基础其三 (消隐算法)
  7. py2exe打包pyqt程序
  8. 为什么要重写toString()方法和hashcode()方法
  9. 设置ArcGIS的外观改回到出厂
  10. 013年十大急需的热门IT技能