C++控制台界面扫雷程序(包含所有基本功能)

C++控制台界面扫雷程序
提示:本程序使用了ICUF_HEAD_03.h作为头文件。
可以参考:ICUF_HEAD_03.h.

开发环境:Visual Studio 2019
一、系统功能分析

地图设置功能根据所选择的难度、或者自定义的设置给地图数组赋值。地图生成功能给地图、地图状态、指针状态数组进行初始化,然后用随机数逐一布雷。扫雷操作功能可以用键盘选择各种功能进行扫雷操作,并且正下方显示了各种数据,包括最高分数以及开始时间(分数)。每进行一次操作,就进入胜负判断阶段,如果没有判断出胜或负则返回扫雷操作,如果判断出了胜负则立即停止,并弹出结束界面,如果是失败,还会在地图上显示所有雷的位置。最后从文件中读取分数记录,如果成绩更加优秀则将其存入文件。

二、各功能模块设计与分析
Main
主函数中并没有加入任何可以对程序造成实际影响的代码,因为考虑到后面的功能调用主函数功能时可能会产生不必要的输出,所以主函数设置为一个过渡的函数,后面的每个函数都单独负责一个功能。
MineSweeper
主函数通过调用初始化难度的函数选择数值对变量进行初始化,然后调用地图生成函数通过刚才初始化的数据生成地图,然后在一个无限循环中进行扫雷操作、胜负判断,在胜负判断有结果后停止并调用展示地雷、展示地图和分数功能,玩家此时可以选择继续或者退出程序。
DifficultyInit(int Set)
此函数用于选择难度,默认提供了三种难度:简单、普通、困难。简单难度下是九乘九的地图加十个地雷,普通难度是十六乘十六的地图加四十个地雷,困难难度是十六乘三十的地图加九十九个地雷。此外还提供了一个自定义的功能,可以自己输入X轴、Y轴的长度以及地雷的数量,在玩家输入数据后进行判断,如果地雷数量大于或等于X轴乘Y轴则数据无效,重新返回选择难度界面。传入值Set可以在调用此函数时通过Set值直接选择难度,但在此项目中没有使用此功能。
InitMap(int SetX,int SetY)
此功能先对默认的长数组进行整体赋值,一共设定了三个二维数组:3X3地雷数组、格子状态数组、指针位置数组。在3X3地雷数组中显示周围3X3的格子中雷的数量,数值为0到8,地雷也在这个数组中赋值为9。初始化函数给此数组所有值初始化为2,而不是0,避免指针在边缘翻开格子时因为判断未显示的数组为0而翻开右边和下边一圈的格子。指针位置二维数组一共有8种状态:0. 未翻开状态、1.指向未翻开状态、2.插旗状态、3.指向插旗状态、4.疑问状态、5.指向疑问状态、6.已翻开状态、7.指向已翻开状态。这八种状态都设定为指向时的状态值加一,在后面的移动指针时可以大幅简化代码,此函数在此阶段不初始化。格子状态二维数组只有0和1两个状态,0代表未翻开,1代表已翻开,初始化为0。然后再根据传入的地图X,Y值给三个数组在X,Y部分赋值为0,再用一个循环来逐一添加地雷,如果添加随机到了一样的X,Y坐标则此次循环不执行加一,确保能生成指定数量的地雷,然后整体计算给3X3地雷数组赋值,完成地图初始化的工作。
ShowMap(int SetX, int SetY)
此函数首先根据上面生成的数据和头文件ICUF_HEAD_03.h中的Col输出颜色功能,对游戏界面进行输出,每种状态都对应一种颜色,格子状态数组中的0. 未翻开状态对应白色1.指向未翻开状态对应紫色2.插旗状态对应红色3.指向插旗状态对应黄色4.疑问状态对应蓝色5.指向疑问状态对应淡蓝色6.已翻开状态不绘制颜色7.指向已翻开状态对应紫色。然后用_getch()不回显的获取一个键盘输入,在SWITCH中进行判断,然后执行操作,由于格子状态数组的八种状态都设定为指向时的状态值加一所以在控制指针移动时,只需要给要移动到的地方状态值加一,离开的地方状态值减一即可,省去了复杂繁琐的逐一赋值。SWITCH中除了上下左右的移动还提供了J、L、Q、E四种额外操作,J是插旗功能,L是标记疑问功能,Q是对一个已经揭开的方块根据周围插的旗判断,如果周围一圈的旗子数等于该格子上写的雷数,则翻开周围其他所有未翻开的格子。E则是用来排查问题时加入的功能,按下后会显示所有格子下的数字,再按一次关闭。
CheckZero(int tempX, int tempY)
此功能在翻开格子为0或者按下Q翻开0的格子后启动,对0周围八个格子进行判断,如果有0则继续在另一个0的坐标上执行此函数。无论周围有没有零,其附近的八个格子都会翻开,一直执行下去知道不满足条件为止。为避免两个0相邻然后无限重复执行,加入了一个判断,只有未翻开的格子且下面时0才能执行全部功能。
CheckMap()
对整个地图进行搜索,如果有翻开的地雷格子则立刻判定失败,并显示所有地雷的位置,进入结束界面。然后再判断不为雷的所有格子是否已经翻开,如果是则提示成功输出分数并进入结束界面。
ShowMine()
展示所有地雷,而不展示其他格子。
ShowMapEnd()
结束页面,输出分数。
Rank(int Fun, int goal)
对文件里的分数进行判断,是否打破纪录,是则用此分数覆盖文件里的分数,否则提示未能打破纪录。
三、系统实现
ICUF_HEAD_03.h:
MineSweeper.cpp
开始界面

难度选择

运行阶段
展示所有数字功能(9为雷)

红色为插旗,蓝色为疑问

失败界面

翻开后的反应

2020/12/1 23:20 纠正了188行的错误
Key[x][y] = 1; (Key[KeyX][KeyY] = 1;)
2021/5/2 12:09 发现了B站的代码块中不显示尖括号之间的内容.
include《iostream》(尖括号打出来不显示,用书名号表示原来的的样子)改为include"iostream"