导语:

哈喽吖!有许多铁汁们私信小编说用Python自行制作小游戏 ‍ ‍ 之后简直就是上头了~让wo多出一点小游戏合集(看来铁汁们跟小编一样都酷爱游戏) 有求必应~小游戏立刻安排上啦~~(扫雷真的是家里还是那种老式电脑的时候就迷上了的)

想要更多完整源码或Python学习资料可点击这行字体或私信wo

游戏介绍:

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

开发工具

Python版本:3.6.4

相关模块:

pygame模块;

以及一些python自带的模块。

环境搭建:

安装Python并添加到环境变量,pip安装需要的相关模块即可。

在终端运行如下命令即可:

python Game25.py

效果预览:

Python制作扫雷小游戏演示

游戏规则:

游戏界面左上角的数字代表所有方格中埋有雷的数目,右上角是一个计时器。你要做的就是根据提示找出方格中所有的雷。
那么提示是啥呢?很简单,游戏刚开始的时候你需要随便点一个方格,就像这样:

上面的数字代表以该数字为中心的九宫格内埋有的雷的数目。所以如果你人品不好,一开始就点到雷的话,这局游戏就直接GG了。
ok,了解了游戏规则之后,我们就可以开始写代码了。首先还是先初始化一下游戏:

# 游戏初始化
pygame.init()
screen = pygame.display.set_mode(cfg.SCREENSIZE)
pygame.display.set_caption('mine sweeper —— Charles的皮卡丘')

然后把需要用到的字体,图片,音乐啥的都导入进来:

# 导入所有图片
images = {}
for key, value in cfg.IMAGE_PATHS.items():if key in ['face_fail', 'face_normal', 'face_success']:image = pygame.image.load(value)images[key] = pygame.transform.smoothscale(image, (int(cfg.GRIDSIZE*1.25), int(cfg.GRIDSIZE*1.25)))else:image = pygame.image.load(value).convert()images[key] = pygame.transform.smoothscale(image, (cfg.GRIDSIZE, cfg.GRIDSIZE))
# 载入字体
font = pygame.font.Font(cfg.FONT_PATH, cfg.FONT_SIZE)
# 导入并播放背景音乐
pygame.mixer.music.load(cfg.BGM_PATH)
pygame.mixer.music.play(-1)

接着,我们来定义一个文字板,用于显示左上角的埋雷数量和右上角的游戏已进行时间:

''文字板'''
class TextBoard(pygame.sprite.Sprite):def __init__(self, text, font, position, color, **kwargs):pygame.sprite.Sprite.__init__(self)self.text = textself.font = fontself.position = positionself.color = colordef draw(self, screen):text_render = self.font.render(self.text, True, self.color)screen.blit(text_render, self.position)def update(self, text):self.text = text

其实很简单,只需要把用字体渲染之后的文本对象绑定到屏幕上就行,然后设置一个update函数,来实时更新里面的文本内容。

然后,我们再定义一个表情按钮类:

'''表情按钮'''
class EmojiButton(pygame.sprite.Sprite):def __init__(self, images, position, status_code=0, **kwargs):pygame.sprite.Sprite.__init__(self)# 导入图片self.images = imagesself.image = self.images['face_normal']self.rect = self.image.get_rect()self.rect.left, self.rect.top = position# 表情按钮的当前状态self.status_code = status_code'''画到屏幕上'''def draw(self, screen):# 状态码为0, 代表正常的表情if self.status_code == 0:self.image = self.images['face_normal']# 状态码为1, 代表失败的表情elif self.status_code == 1:self.image = self.images['face_fail']# 状态码为2, 代表成功的表情elif self.status_code == 2:self.image = self.images['face_success']# 绑定图片到屏幕screen.blit(self.image, self.rect)'''设置当前的按钮的状态'''def setstatus(self, status_code):self.status_code = status_code

当鼠标点击到这个按钮的时,就重新开始新的游戏(无论当前的游戏状态如何,都将重新开始新的游戏):

接下来,我们需要定义的就是下面的方格类了:

'''雷'''
class Mine(pygame.sprite.Sprite):def __init__(self, images, position, status_code=0, **kwargs):pygame.sprite.Sprite.__init__(self)# 导入图片self.images = imagesself.image = self.images['blank']self.rect = self.image.get_rect()self.rect.left, self.rect.top = position# 雷当前的状态self.status_code = status_code# 真雷还是假雷(默认是假雷)self.is_mine_flag = False# 周围雷的数目self.num_mines_around = -1'''设置当前的状态码'''def setstatus(self, status_code):self.status_code = status_code'''埋雷'''def burymine(self):self.is_mine_flag = True'''设置周围雷的数目'''def setnumminesaround(self, num_mines_around):self.num_mines_around = num_mines_around'''画到屏幕上'''def draw(self, screen):# 状态码为0, 代表该雷未被点击if self.status_code == 0:self.image = self.images['blank']# 状态码为1, 代表该雷已被点开elif self.status_code == 1:self.image = self.images['mine'] if self.is_mine_flag else self.images[str(self.num_mines_around)]# 状态码为2, 代表该雷被玩家标记为雷elif self.status_code == 2:self.image = self.images['flag']# 状态码为3, 代表该雷被玩家标记为问号elif self.status_code == 3:self.image = self.images['ask']# 状态码为4, 代表该雷正在被鼠标左右键双击elif self.status_code == 4:assert not self.is_mine_flagself.image = self.images[str(self.num_mines_around)]# 状态码为5, 代表该雷在被鼠标左右键双击的雷的周围elif self.status_code == 5:self.image = self.images['0']# 状态码为6, 代表该雷被踩中elif self.status_code == 6:assert self.is_mine_flagself.image = self.images['blood']# 状态码为7, 代表该雷被误标elif self.status_code == 7:assert not self.is_mine_flagself.image = self.images['error']# 绑定图片到屏幕screen.blit(self.image, self.rect)@propertydef opened(self):return self.status_code == 1

它的主要作用就是记录游戏地图中某个方格的状态(比如是不是埋了雷呀,有没有被点开呀,有没有被标记呀之类的)。
最后定义一个游戏地图类,来把游戏地图中的所有方格都整合在一起方便在游戏主循环里调用更新:

''扫雷地图'''
class MinesweeperMap():def __init__(self, cfg, images, **kwargs):self.cfg = cfg# 雷型矩阵self.mines_matrix = []for j in range(cfg.GAME_MATRIX_SIZE[1]):mines_line = []for i in range(cfg.GAME_MATRIX_SIZE[0]):position = i * cfg.GRIDSIZE + cfg.BORDERSIZE, (j + 2) * cfg.GRIDSIZEmines_line.append(Mine(images=images, position=position))self.mines_matrix.append(mines_line)# 随机埋雷for i in random.sample(range(cfg.GAME_MATRIX_SIZE[0]*cfg.GAME_MATRIX_SIZE[1]), cfg.NUM_MINES):self.mines_matrix[i//cfg.GAME_MATRIX_SIZE[0]][i%cfg.GAME_MATRIX_SIZE[0]].burymine()count = 0for item in self.mines_matrix:for i in item:count += int(i.is_mine_flag)# 游戏当前的状态self.status_code = -1# 记录鼠标按下时的位置和按的键self.mouse_pos = Noneself.mouse_pressed = None'''画出当前的游戏状态图'''def draw(self, screen):for row in self.mines_matrix:for item in row: item.draw(screen)'''设置当前的游戏状态'''def setstatus(self, status_code):# 0: 正在进行游戏, 1: 游戏结束, -1: 游戏还没开始self.status_code = status_code'''根据玩家的鼠标操作情况更新当前的游戏状态地图'''def update(self, mouse_pressed=None, mouse_pos=None, type_='down'):assert type_ in ['down', 'up']# 记录鼠标按下时的位置和按的键if type_ == 'down' and mouse_pos is not None and mouse_pressed is not None:self.mouse_pos = mouse_posself.mouse_pressed = mouse_pressed# 鼠标点击的范围不在游戏地图内, 无响应if self.mouse_pos[0] < self.cfg.BORDERSIZE or self.mouse_pos[0] > self.cfg.SCREENSIZE[0] - self.cfg.BORDERSIZE or \self.mouse_pos[1] < self.cfg.GRIDSIZE * 2 or self.mouse_pos[1] > self.cfg.SCREENSIZE[1] - self.cfg.BORDERSIZE:return# 鼠标点击在游戏地图内, 代表开始游戏(即可以开始计时了)if self.status_code == -1:self.status_code = 0# 如果不是正在游戏中, 按鼠标是没有用的if self.status_code != 0:return# 鼠标位置转矩阵索引coord_x = (self.mouse_pos[0] - self.cfg.BORDERSIZE) // self.cfg.GRIDSIZEcoord_y = self.mouse_pos[1] // self.cfg.GRIDSIZE - 2mine_clicked = self.mines_matrix[coord_y][coord_x]# 鼠标按下if type_ == 'down':# --鼠标左右键同时按下if self.mouse_pressed[0] and self.mouse_pressed[2]:if mine_clicked.opened and mine_clicked.num_mines_around > 0:mine_clicked.setstatus(status_code=4)num_flags = 0coords_around = self.getaround(coord_y, coord_x)for (j, i) in coords_around:if self.mines_matrix[j][i].status_code == 2:num_flags += 1if num_flags == mine_clicked.num_mines_around:for (j, i) in coords_around:if self.mines_matrix[j][i].status_code == 0:self.openmine(i, j)else:for (j, i) in coords_around:if self.mines_matrix[j][i].status_code == 0:self.mines_matrix[j][i].setstatus(status_code=5)# 鼠标释放else:# --鼠标左键if self.mouse_pressed[0] and not self.mouse_pressed[2]:if not (mine_clicked.status_code == 2 or mine_clicked.status_code == 3):if self.openmine(coord_x, coord_y):self.setstatus(status_code=1)# --鼠标右键elif self.mouse_pressed[2] and not self.mouse_pressed[0]:if mine_clicked.status_code == 0:mine_clicked.setstatus(status_code=2)elif mine_clicked.status_code == 2:mine_clicked.setstatus(status_code=3)elif mine_clicked.status_code == 3:mine_clicked.setstatus(status_code=0)# --鼠标左右键同时按下elif self.mouse_pressed[0] and self.mouse_pressed[2]:mine_clicked.setstatus(status_code=1)coords_around = self.getaround(coord_y, coord_x)for (j, i) in coords_around:if self.mines_matrix[j][i].status_code == 5:self.mines_matrix[j][i].setstatus(status_code=0)'''打开雷'''def openmine(self, x, y):mine_clicked = self.mines_matrix[y][x]if mine_clicked.is_mine_flag:for row in self.mines_matrix:for item in row:if not item.is_mine_flag and item.status_code == 2:item.setstatus(status_code=7)elif item.is_mine_flag and item.status_code == 0:item.setstatus(status_code=1)mine_clicked.setstatus(status_code=6)return Truemine_clicked.setstatus(status_code=1)coords_around = self.getaround(y, x)num_mines = 0for (j, i) in coords_around:num_mines += int(self.mines_matrix[j][i].is_mine_flag)mine_clicked.setnumminesaround(num_mines)if num_mines == 0:for (j, i) in coords_around:if self.mines_matrix[j][i].num_mines_around == -1:self.openmine(i, j)return False'''获得坐标点的周围坐标点'''def getaround(self, row, col):coords = []for j in range(max(0, row-1), min(row+1, self.cfg.GAME_MATRIX_SIZE[1]-1)+1):for i in range(max(0, col-1), min(col+1, self.cfg.GAME_MATRIX_SIZE[0]-1)+1):if j == row and i == col:continuecoords.append((j, i))return coords'''是否正在游戏中'''@propertydef gaming(self):return self.status_code == 0'''被标记为雷的雷数目'''@propertydef flags(self):num_flags = 0for row in self.mines_matrix:for item in row: num_flags += int(item.status_code == 2)return num_flags'''已经打开的雷的数目'''@propertydef openeds(self):num_openeds = 0for row in self.mines_matrix:for item in row: num_openeds += int(item.opened)return num_openeds

定义完这些游戏中必要的元素类之后就在游戏主函数里实例化它们:

# 实例化游戏地图
minesweeper_map = MinesweeperMap(cfg, images)
position = (cfg.SCREENSIZE[0] - int(cfg.GRIDSIZE * 1.25)) // 2, (cfg.GRIDSIZE * 2 - int(cfg.GRIDSIZE * 1.25)) // 2
emoji_button = EmojiButton(images, position=position)
fontsize = font.size(str(cfg.NUM_MINES))
remaining_mine_board = TextBoard(str(cfg.NUM_MINES), font, (30, (cfg.GRIDSIZE*2-fontsize[1])//2-2), cfg.RED)
fontsize = font.size('000')
time_board = TextBoard('000', font, (cfg.SCREENSIZE[0]-30-fontsize[0], (cfg.GRIDSIZE*2-fontsize[1])//2-2), cfg.RED)
time_board.is_start = False

然后写个游戏主循环以根据用户的操作来更新当前的游戏状态就ok啦:

# 游戏主循环
clock = pygame.time.Clock()
while True:screen.fill(cfg.BACKGROUND_COLOR)# --按键检测for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()elif event.type == pygame.MOUSEBUTTONDOWN:mouse_pos = event.posmouse_pressed = pygame.mouse.get_pressed()minesweeper_map.update(mouse_pressed=mouse_pressed, mouse_pos=mouse_pos, type_='down')elif event.type == pygame.MOUSEBUTTONUP:minesweeper_map.update(type_='up')if emoji_button.rect.collidepoint(pygame.mouse.get_pos()):minesweeper_map = MinesweeperMap(cfg, images)time_board.update('000')time_board.is_start = Falseremaining_mine_board.update(str(cfg.NUM_MINES))emoji_button.setstatus(status_code=0)# --更新时间显示if minesweeper_map.gaming:if not time_board.is_start:start_time = time.time()time_board.is_start = Truetime_board.update(str(int(time.time() - start_time)).zfill(3))# --更新剩余雷的数目显示remianing_mines = max(cfg.NUM_MINES - minesweeper_map.flags, 0)remaining_mine_board.update(str(remianing_mines).zfill(2))# --更新表情if minesweeper_map.status_code == 1:emoji_button.setstatus(status_code=1)if minesweeper_map.openeds + minesweeper_map.flags == cfg.GAME_MATRIX_SIZE[0] * cfg.GAME_MATRIX_SIZE[1]:minesweeper_map.status_code = 1emoji_button.setstatus(status_code=2)# --显示当前的游戏状态地图minesweeper_map.draw(screen)emoji_button.draw(screen)remaining_mine_board.draw(screen)time_board.draw(screen)# --更新屏幕pygame.display.update()clock.tick(cfg.FPS)

end:

这期分享结束啦~喜欢玩小游戏的友友算是遇到志同道合的伙伴了就是小编wo啦~我这里还有很多小游戏但是也一次性写不完所以小游戏系列会慢慢出的有什么想要的游戏源码也可直接私信小编啦~制作不易记得给三连哦~家人们的支持是小编更新最大的动力

Python【小游戏合集】之重温童年最爱的扫雷小游戏相关推荐

  1. Python表白代码合集:5种表白代码、比小心心、无限弹窗、520表白墙、抖音热门表白小软件、无套路表白

       一.介绍一下         写了5个Python表白代码,代码很简单,通俗易懂,都有注释.有什么问题联系本人QQ:483062431.文章最后教你们怎么打包成exe,如果你懒得搞懂代码怎么回事 ...

  2. 计算机工程师专用小工具,204个联想工程师专用小工具合集

    204个联想工程师专用小工具合集,为联想用户整理了204个常用的小工具,Flash修复工具.Fn+F5快捷键修复工具.Framework修复工具等. 204个联想工程师专用小工具合集简介 204个联想 ...

  3. 用Python制作【小游戏合集】之小鸟管道游戏附源码啊~

    导语 哈喽小编今日发现自己已经大半个月没有写小游戏啦~对于喜欢[小游戏合集]的铁汁们 深感歉意! 于是小编连忙给大家补上这一期!

  4. Python制作【小游戏合集】之愤怒的小鸟

    导语: 哈喽铁汁们!!几天不上线的小游戏合集它又来了(主要是每日写小游戏小编怕你们会觉得腻)

  5. 任天堂fc/sfc童年游戏合集视频发布了

    任天堂fc/sfc童年游戏合集是一款街机游戏的大合集,相信80后的玩家童年时都接触过任天堂的红白机游戏,当年你是不是祈求父母在周末玩上几个小时?或者你是不是很兴奋的到邻居家里噌上几把?绝对经典怀旧! ...

  6. 海洋小游戏合集 v2.0

    海洋小游戏合集是一款集合金弹头.斗地主 .俄罗斯方块.坦克大战.魂斗罗.炸弹台球.暴力摩托.五子棋.拳皇为一体的小游戏软件工具箱.  适度游戏易脑,过度游戏伤身,祝您玩的愉快. 下载地址 本文转自ha ...

  7. FC小游戏合集网页版HTML源码

    FC小游戏合集网页版HTML源码,上传到服务器即可访问,包含游戏文件在里面,操作键网页上有列出. 源码下载:FC小游戏合集网页版HTML源码-小程序文档类资源-CSDN下载

  8. c语言编写已知xyz,C语言编程基础——xyzGame小游戏合集

    这是一个由纯C语言标准库写的控制台小游戏合集.包含井字棋.贪吃蛇.俄罗斯方块三款简单的小游戏. 初学者非常适合借助这类简单的小游戏锻炼编程技能,同时感受编程的乐趣

  9. 小学计算机一个游戏梦游,梦游先生小游戏合集(上部)

    梦游先生小游戏合集包含了目前网络上流行的梦游先生系列的1到4部. 梦游先生是热门的冒险解谜类游戏,梦游先生1到4部,支持离线玩. 梦游先生1-疯狂都市 经典的华纳冒险系列之梦游先生操作简单,但是情节, ...

最新文章

  1. ajax 的理论以及需要的常用参数
  2. dede 二次开发系统迁移到 IIS 时会出现的问题及解决方案
  3. linux配置apache文件大小,linux下apache中httpd.conf文件配置参数说明
  4. [JavaWeb-MySQL]多表关系介绍
  5. highCharts使用中问题总结
  6. linux下PS1命令提示符设置
  7. 收藏!38所设有人工智能学院高校表单!
  8. python不可实现的领域3d_岩土工程新手入门指南---FLAC3D学习指导与建议
  9. 支撑位和压力位怎么看是什么意思?
  10. .NET简谈反射(动态调用)
  11. C语言实战之猜拳游戏
  12. 修改Tomcat8的默认访问端口8080
  13. php文件上传实验总结,php文件上传总结 - osc_jjc36t9p的个人空间 - OSCHINA - 中文开源技术交流社区...
  14. BLP模型(Bell-La Padula模型)
  15. Java项目:SSM网吧计费管理系统
  16. SPSS入门笔记记录
  17. 【学习体会】Lighttools8.4.0:简单光学系统实例
  18. [WUSTCTF2020]level3 笔记与自省
  19. 机器学习之感知机python实现
  20. 鲁能群英荟萃 萝卜开会

热门文章

  1. PR剪辑教学之定格动画的制作
  2. 【LGR-073】洛谷 7 月月赛 Div.2 B 混凝土数学
  3. 从军行的角度来看计算机故障分为,从军行
  4. Win7系统安装tensorflow2.1.0报错解决方案
  5. 全志R16_Tina SDK编译环境搭建
  6. R16 android4.4 常见问题参考手册
  7. vue实现一个鼠标滑动预览视频封面组件(精灵图版本)
  8. [Voice communications] 声道的转换
  9. 基于51单片机的超声波测距_液位检测_温度检测protues仿真
  10. 确认应答机制超时重传机制序列号延迟应答捎带应答