扫雷 MineSweeper
用过Windows XP的用户一定不会忘记那一款有趣、烧脑(maybe)的扫雷游戏。(反正我是没有怎么玩过)这里将用C++控制台程序简单实现这个扫雷游戏。
Win7下的扫雷就是下面这个画风的:
首先,我们分析以下这个游戏:
- 地图由正方形小方块组成的矩形,每个小方块内要么有雷,要么没有雷
- 随意点击一个方块开始,如果有雷,爆炸了,则游戏结束,没有爆炸则继续
- 没有爆炸的方块会显示出以它为中心的九宫格内的雷的数量,为空则表示没有
- 一次点击后,如果没有爆炸,且周围有雷,则不会显示出多余方块,如果周围没有雷,则会显示出周围所有没有雷的方块,并且显示出数字的方块会作为边界
- 为什么要这样呢?因为为空白的话,可以直接将周围剩余8个方块依次点击出来(都没有雷),所以电脑帮我们做了这一步,让我们进行接下来的分析
可以看到,上面的过程中最重要的就是:点击的块周围没有雷时,显示出整个可以确定没有雷的一块区域和边界。这很显然要用到广度优先搜索,用队列实现,并不复杂。
实现效果图:
因为是纯粹的C++控制台游戏,所以输入坐标进行挖雷。
游戏逻辑就是:每一次接受输入,然后挖雷,刷新状态,清屏,输出,挖到雷就结束。
雷的数量作为输入,自己设置。然后程序随机生成雷的位置。
实现
IDE:VS 2017 Community
文件结构
|
|----block.h //block类以及Map类的声明
|----stdafx.h //VS必须有这个头文件,可以将一些所有源文件都能用到的头文件在其中声明
|----block.cpp //Map类的方法实现
|____game-MineSweeper.cpp //主函数,逻辑主体
block.h
——block
和Map
类定义
// 2018.4.5 In XDU
// block class and Map class definition
// IDE: VS 2017 Community
#pragma once
#include <cstdlib>
#include <iostream>
#include <queue>
#include <ctime>
using std::cout;
using std::cin;
using std::endl;
using std::queue;
using std::pair;
const int max_X = 20; //也可以将block改造为模板类,将这两个参数作为模板参数传入接口
const int max_Y = 20; //如果要实现输入控制地图大小,可在堆上分配数组,作为参数传入构造函数,一维数组模拟二维数组即可
const int offset_X = 5; //打印地图时相对纵轴偏移量,下为横轴
const int offset_Y = 3;
template<typename T>
T max(T a, T b)
{
return a > b ? a : b;
}
template<typename T>
T min(T a, T b)
{
return a < b ? a : b;
}
struct block
{
bool has_mine; //是否有雷
int mine_around_num; //周围的雷的数量
bool digged; //是否已经被挖开,挖开有雷则直接返回,没有则显示周围的雷的数量
};
class Map
{
private:
block Cube[max_X][max_Y];
public:
//传入雷的数量,将Cube初始化
Map(int n);
//应该要采用广度优先搜索,将所有位置显示出来,挖到雷返回false
bool dig(int x, int y);
//打印地图,若碰到有雷炸了的情况,最后由下一个函数清屏打印最终结果
void print();
//雷挖炸了之后