今天给大家分享一个由Python3(当然python3.5 3.6 3.7 3.8 ...都行)与pygame模块结合制作的一个经典小游戏“扫雷”

代码是完全可运行的,请大家放心运行。当然了别忘了下载素材(下方代码位置处写明了下载地址)

一、运行效果

二、完整代码

下面的代码用到了一些素材(图片、字体等),下载地址为:https://www.itprojects.cn/detail.html?example_id=dd0fdfb421f61089547578d235b3fce7

import random
import sys
import time import pygame # 地雷数量
MINE_COUNT = 99
# 每个方格的大小(宽、高都为20)
SIZE = 20
# 方格的行数
BLOCK_ROW_NUM = 16
# 方格的列数
BLOCK_COL_NUM = 30
# 游戏窗口的宽、高
SCREEN_WIDTH, SCREEN_HEIGHT = BLOCK_COL_NUM * SIZE, (BLOCK_ROW_NUM + 2) * SIZE def get_mine_flag_num(board_list):
"""
计算还剩多少颗雷
"""
num = 0
for line in board_list:
for num_dict in line:
if num_dict.get("closed_num") == "雷标记":
num += 1 return num def open_all_mine(board_list):
"""
显示所有的雷
"""
for row, line in enumerate(board_list):
for col, num_dict in enumerate(line):
if num_dict.get("opened_num") == "雷":
num_dict["opened"] = True def get_mine_num(row, col, board_list):
"""
计算点击的空格周围的雷的数量
"""
# 生成起始位置、终止位置
row_start = row - 1 if row - 1 >= 0 else row
row_stop = row + 2 if row + 1 <= BLOCK_ROW_NUM - 1 else row + 1
col_start = col - 1 if col - 1 >= 0 else col
col_stop = col + 2 if col + 1 <= BLOCK_COL_NUM - 1 else col + 1 # 循环遍历当前方格周围的雷的数量
mine_num = 0
for i in range(row_start, row_stop):
for j in range(col_start, col_stop):
if board_list[i][j].get("opened_num") == "雷":
mine_num += 1
return mine_num def set_nums_blank(row, col, board_list):
"""
判断当前位置的周边位置是否为空,如果是则继续判断,
最终能够实现点击一个空位置后连续的空位置都能够显示出来
"""
mine_num = get_mine_num(row, col, board_list)
print("row=%d, col=%d, mine_num=%d" % (row, col, mine_num))
if mine_num == 0:
board_list[row][col]['opened'] = True
board_list[row][col]["opened_num"] = 0
board_list[row][col]["closed_num"] = "空"
# 判断对角是否是数字
for i, j in [(-1, -1), (1, 1), (1, -1), (-1, 1)]:
if 0 <= row + i <= 15 and 0 <= col + j <= 29:
mine_num = get_mine_num(row + i, col + j, board_list)
if mine_num:
board_list[row + i][col + j]['opened'] = True
board_list[row + i][col + j]["opened_num"] = mine_num
board_list[row + i][col + j]["closed_num"] = "空" # 判断剩下4个位置是否是也是0,即空
for i, j in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
if 0 <= row + i <= 15 and 0 <= col + j <= 29:
if not board_list[row + i][col + j].get("opened"):
set_nums_blank(row + i, col + j, board_list)
else:
board_list[row][col]['opened'] = True
board_list[row][col]["opened_num"] = mine_num
board_list[row][col]["closed_num"] = "空" def left_click_block(row, col, board_list):
"""
左击空格后的处理
"""
if board_list[row][col].get("opened") is False and board_list[row][col].get("opened_num") != "雷":
# 如果不是雷,那么就计算当前位置数字
mine_num = get_mine_num(row, col, board_list)
print("地雷数:", mine_num)
board_list[row][col]["opened_num"] = mine_num
board_list[row][col]["opened"] = True # 标记为"打开"状态
board_list[row][col]["closed_num"] = "空" # 标记为"未打开时的状态为空格",防止显示剩余雷数错误
if mine_num == 0:
# 如果方格周边没有雷此时,判断是否有连续空位置
set_nums_blank(row, col, board_list)
elif board_list[row][col].get("opened") is False and board_list[row][col].get("opened_num") == "雷":
board_list[row][col]["opened_num"] = "踩雷" # 标记为"踩雷"图片
board_list[row][col]["opened"] = True # 标记为"打开"状态
board_list[row][col]["closed_num"] = "空" # 标记为"未打开时的状态为空格",防止显示剩余雷数错误
return True def create_random_board(row, col, mine_num):
"""
得到一个随机的棋盘
"""
# 随机布雷
nums = [{"opened": False, "opened_num": 0, 'closed_num': "空"} for _ in range(row * col - mine_num)] # 16x30-99 表示的是生成381个0
nums += [{"opened": False, "opened_num": "雷", 'closed_num': "空"} for _ in range(mine_num)] # 99颗地雷
random.shuffle(nums) # 乱序,此时nums是乱的
return [list(x) for x in zip(*[iter(nums)] * col)] def right_click_block(row, col, board_list):
"""
右击方格后更新其状态(标记为雷、问号?、取消标记)
"""
if board_list[row][col].get("opened") is False:
if board_list[row][col]["closed_num"] == "空":
board_list[row][col]["closed_num"] = "雷标记"
elif board_list[row][col]["closed_num"] == "雷标记":
board_list[row][col]["closed_num"] = "疑问标记"
elif board_list[row][col]["closed_num"] == "疑问标记":
board_list[row][col]["closed_num"] = "空" def click_block(x, y, board_list):
"""
检测点击的是哪个方格(即第x行,第y列)
"""
# 计算出点击的空格的行、列
for row, line in enumerate(board_list):
for col, _ in enumerate(line):
if col * SIZE <= x <= (col + 1) * SIZE and (row + 2) * SIZE <= y <= (row + 2 + 1) * SIZE:
print("点击的空格的位置是:", row, col)
return row, col def run(screen):
bgcolor = (225, 225, 225) # 背景色 # 要显示的棋盘
# board_list = [[0] * BLOCK_COL_NUM for _ in range(BLOCK_ROW_NUM)]
board_list = create_random_board(BLOCK_ROW_NUM, BLOCK_COL_NUM, MINE_COUNT) # 16行、30列,有99颗地雷 # 默认的方格图片
img_blank = pygame.image.load('resource/blank.bmp').convert()
img_blank = pygame.transform.smoothscale(img_blank, (SIZE, SIZE))
# "雷标记"图片
img_mine_flag = pygame.image.load('resource/flag.bmp').convert()
img_mine_flag = pygame.transform.smoothscale(img_mine_flag, (SIZE, SIZE))
# "雷"图片
img_mine = pygame.image.load('resource/mine.bmp').convert()
img_mine = pygame.transform.smoothscale(img_mine, (SIZE, SIZE))
# "疑问标记"图片
img_ask = pygame.image.load('resource/ask.bmp').convert()
img_ask = pygame.transform.smoothscale(img_ask, (SIZE, SIZE))
# "踩雷"图片
img_blood = pygame.image.load('resource/blood.bmp').convert()
img_blood = pygame.transform.smoothscale(img_blood, (SIZE, SIZE))
# "表情"图片
face_size = int(SIZE * 1.25)
img_face_fail = pygame.image.load('resource/face_fail.bmp').convert()
img_face_fail = pygame.transform.smoothscale(img_face_fail, (face_size, face_size))
img_face_normal = pygame.image.load('resource/face_normal.bmp').convert()
img_face_normal = pygame.transform.smoothscale(img_face_normal, (face_size, face_size))
img_face_success = pygame.image.load('resource/face_success.bmp').convert()
img_face_success = pygame.transform.smoothscale(img_face_success, (face_size, face_size))
# "表情"位置
face_pos_x = (SCREEN_WIDTH - face_size) // 2
face_pos_y = (SIZE * 2 - face_size) // 2
# 类的数量图片
img0 = pygame.image.load('resource/0.bmp').convert()
img0 = pygame.transform.smoothscale(img0, (SIZE, SIZE))
img1 = pygame.image.load('resource/1.bmp').convert()
img1 = pygame.transform.smoothscale(img1, (SIZE, SIZE))
img2 = pygame.image.load('resource/2.bmp').convert()
img2 = pygame.transform.smoothscale(img2, (SIZE, SIZE))
img3 = pygame.image.load('resource/3.bmp').convert()
img3 = pygame.transform.smoothscale(img3, (SIZE, SIZE))
img4 = pygame.image.load('resource/4.bmp').convert()
img4 = pygame.transform.smoothscale(img4, (SIZE, SIZE))
img5 = pygame.image.load('resource/5.bmp').convert()
img5 = pygame.transform.smoothscale(img5, (SIZE, SIZE))
img6 = pygame.image.load('resource/6.bmp').convert()
img6 = pygame.transform.smoothscale(img6, (SIZE, SIZE))
img7 = pygame.image.load('resource/7.bmp').convert()
img7 = pygame.transform.smoothscale(img7, (SIZE, SIZE))
img8 = pygame.image.load('resource/8.bmp').convert()
img8 = pygame.transform.smoothscale(img8, (SIZE, SIZE))
img_dict = {
0: img0,
1: img1,
2: img2,
3: img3,
4: img4,
5: img5,
6: img6,
7: img7,
8: img8,
'雷标记': img_mine_flag,
'雷': img_mine,
'空': img_blank,
'疑问标记': img_ask,
'踩雷': img_blood,
}
# 标记是否踩到雷
game_over = False
# 游戏状态
game_status = "normal"
# 显示雷的数量、耗时用到的资源
font = pygame.font.Font('resource/a.TTF', SIZE * 2) # 字体
f_width, f_height = font.size('999')
red = (200, 40, 40)
# 标记出雷的个数
flag_count = 0
# 记录耗时
elapsed_time = 0
last_time = time.time()
start_record_time = False # 创建计时器(防止while循环过快,占用太多CPU的问题)
clock = pygame.time.Clock()
while True:
# 事件检测(鼠标点击、键盘按下等)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN and event.button:
b1, b2, b3 = pygame.mouse.get_pressed()
mouse_click_type = None
if b1 and not b2 and not b3: # 左击
mouse_click_type = "left"
elif not b1 and not b2 and b3: # 右击
mouse_click_type = "right"
print("点击了鼠标的[%s]键" % mouse_click_type)
x, y = pygame.mouse.get_pos()
if game_status == "normal" and 2 * SIZE <= y <= SCREEN_HEIGHT:
# 计算点击的是哪个空
position = click_block(x, y, board_list)
if position:
if mouse_click_type == "right":
# 如果右击方格,那么就更新其状态
right_click_block(*position, board_list)
# 更新标记的雷的数量
flag_count = get_mine_flag_num(board_list)
start_record_time = True # 开始记录耗时
elif mouse_click_type == "left":
# 点击空格的处理
game_over = left_click_block(*position, board_list)
print("是否踩到雷", game_over)
start_record_time = True # 开始记录耗时
# 更新标记的雷的数量
flag_count = get_mine_flag_num(board_list)
if game_over:
# 将所有雷的位置,标记出来
open_all_mine(board_list)
# 更改游戏状态
game_status = "fail"
# 停止记录耗时
start_record_time = False
elif face_pos_x <= x <= face_pos_x + face_size and face_pos_y <= y <= face_pos_y + face_size:
# 重来一局
print("点击了再来一局...")
return # 填充背景色
screen.fill(bgcolor) # 显示方格
for i, line in enumerate(board_list):
for j, num_dict in enumerate(line):
if num_dict.get("opened"):
screen.blit(img_dict[num_dict.get("opened_num")], (j * SIZE, (i + 2) * SIZE))
else:
screen.blit(img_dict[num_dict.get("closed_num")], (j * SIZE, (i + 2) * SIZE)) # 显示表情
if game_status == "win":
screen.blit(img_face_success, (face_pos_x, face_pos_y))
elif game_status == "fail":
screen.blit(img_face_fail, (face_pos_x, face_pos_y))
else:
screen.blit(img_face_normal, (face_pos_x, face_pos_y)) # 显示剩余雷的数量
mine_text = font.render('%02d' % (MINE_COUNT - flag_count), True, red)
screen.blit(mine_text, (30, (SIZE * 2 - f_height) // 2 - 2)) # 显示耗时
if start_record_time and time.time() - last_time >= 1:
elapsed_time += 1
last_time = time.time()
mine_text = font.render('%03d' % elapsed_time, True, red)
screen.blit(mine_text, (SCREEN_WIDTH - f_width - 30, (SIZE * 2 - f_height) // 2 - 2)) # 刷新显示(此时窗口才会真正的显示)
pygame.display.update()
# FPS(每秒钟显示画面的次数)
clock.tick(60) # 通过一定的延时,实现1秒钟能够循环60次 def main():
"""
循环调用run函数,每调用一次就重新来一局游戏
"""
pygame.init()
pygame.display.set_caption('扫雷')
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
while True:
run(screen) if __name__ == '__main__':
main()

Python3+pygame实现Windows经典扫雷的更多相关文章

  1. TensorFlow 1.2.0新版本完美支持Python3.6,windows在cmd中输入pip install tensorflow就能下载应用最新tensorflow

    TensorFlow 1.2.0新版本完美支持Python3.6,windows在cmd中输入pip install tensorflow就能下载应用最新tensorflow 只需在cmd中输入pip ...

  2. 基于jQuery经典扫雷游戏源码

    分享一款基于jQuery经典扫雷游戏源码.这是一款网页版扫雷小游戏特效代码下载.效果图如下: 在线预览   源码下载 实现的代码. html代码: <center> <h1>j ...

  3. Python3.x(windows系统)安装matplotlib库

    Python3.x(windows系统)安装matplotlib库 cmd命令: pip install matplotlib 执行结果:

  4. Python3.x(windows系统)安装requests库

    Python3.x(windows系统)安装requests库 cmd命令: pip install requests 执行结果:

  5. Python3.x(windows系统)安装libxml2库

    Python3.x(windows系统)安装libxml2库 cmd安装命令: pip install lxml 执行结果: 再执行命令: pip install virtualenv 执行结果:

  6. Python3.6(windows系统)安装pip.whl

    Python3.6(windows系统)安装pip.whl 1,下载whl文件:https://pypi.python.org/pypi/pip#downloads 2,将下载的文件放入Python的 ...

  7. Python3.6(windows系统)通过pip安装bs4

    Python3.6(windows系统)通过pip安装bs4 cmd安装命令: pip install beautifulsoup4 执行结果:

  8. Python3.6(windows系统)解决编码问题

    Python3.6(windows系统)解决编码问题 1,py文件代码: import urllib.request url = "http://www.douban.com/" ...

  9. Python3+pygame实现的90坦克大战 代码完整 有演示效果

    我是一个典型的80后,年轻时玩过了特别多的游戏,所以这几天用Python3+pygame实现了一个另外小游戏"坦克大战"(其他的游戏,请翻阅我的博客) 本实例代码量有些多,完整的版 ...

随机推荐

  1. HDU6331 Problem M. Walking Plan【Floyd + 矩阵 + 分块】

    HDU6331 Problem M. Walking Plan 题意: 给出一张有\(N\)个点的有向图,有\(q\)次询问,每次询问从\(s\)到\(t\)且最少走\(k\)条边的最短路径是多少 \ ...

  2. python+fiddler下载vip视频 && ts视频可合并

    如果你只想在线看视频可以去看这篇博客:python实现通过指定浏览器免费观看vip视频  先看一下我们程序运行的结果 我们要解析的接口就是(就是这个"接口+视频地址"可以解析出vi ...

  3. Panasonic Programming Contest (AtCoder Beginner Contest 186) E.Throne (数学,线性同余方程)

    题意:有围着一圈的\(N\)把椅子,其中有一个是冠位,你在离冠位顺时针\(S\)把椅子的位置,你每次可以顺时针走\(K\)个椅子,问最少要走多少次才能登上冠位,或者走不到冠位. 题解:这题和洛谷那个青 ...

  4. 仿ATM程序软件

    一.目标: ATM仿真软件 1 系统的基本功能 ATM的管理系统其基本功能如下:密码验证机制:吞锁卡机制:存取款功能:账户查询功能:转账功能等. 要求 要能提供以下几个基本功能: (1)系统内的相关信 ...

  5. 行业动态 | 腾讯合作商Babylon使用Cassandra保护患者数据并提高医疗效果

    医疗世界正在快速朝向个性化和低成本的方向发展,Babylon Health看到了这样的机会--通过开创性的云端应用来大幅扩张和改进他们所提供的服务.   通过使用基于Apache Cassandra的 ...

  6. 错误: 未能完成程序集的安装(hr = 0x8007000b)。探测终止。

     解决方案:VS中"工具"->"选项"->"Web项目"->"对网站和项目使用IIS Express的64位版& ...

  7. C++ 结构体 segment fault

    形如 struct node { int key; int height; int size; //tree node 个数 node *left, *right; node(int x) : key ...

  8. mybatis(三)配置mapper.xml 的基本操作

    参考:https://www.cnblogs.com/wuzhenzhao/p/11101555.html XML 映射文件 本文参考mybatis中文官网进行学习总结:http://www.myba ...

  9. How to get the real screen size(screen resolution) by using js

    How to get the real screen size(screen resolution) by using js 获取用户屏幕的真实像素分辨率, 屏幕实际尺寸 window.deviceP ...

  10. HTML5 download 执行条件

    HTML5 download 执行条件 同一个域名下的资源 http only 绝对路径/相对路径 都可以 demo https://cdn.xgqfrms.xyz/ https://cdn.xgqf ...