先上几张效果图,本人QT刚刚入门一个星期不到,如果你和我一样是个初学者,我觉得这篇文章还有那么点参考价值,如果你是老手,不喜勿喷哈。(全部代码以及工程地址会在最后贴出)
界面比较粗糙,功能也有很多需要完善的,比如计时和分数排名,但是核心的内容应该就是这些了。
如果你感兴趣,下面我就从代码逻辑和界面交互两个方面分别介绍我的编写过程。
1.游戏的内部逻辑:
首先分析一下抽象的游戏过程,把一个单元格看作一个数据结构,一个游戏地图看作是一个由各个单元格构成的整体,包含完成各式各样任务的成员函数。
一个单元格的互斥状态有:未被挖掘,被标记,被挖掘。同时存储自己是否有地雷的状态,并存储自己周围的地雷数量。根据以上分析,我们定义数据结构如下:
enum State{
UNDIGGED,
DIGGED,
REDFLAG
};
struct unit{
State curState;
int bombNum;
bool isBomb;
unit():curState(UNDIGGED),bombNum(0),isBomb(false) {}
~unit() = default;
};
然后就是游戏地图的设计,首先考虑游戏这个抽象数据结构的数据成员,首先应该包含一组单元格阵列,当前阵列的行数和列数。总的地雷数,剩余的没有被挖掘的单元数(与地雷数比对可以判断是否通过游戏),最后还有一个枚举量,记录当前游戏的状态。
然后分析游戏中的操作,逆向分析,我们可以得到几个基本的动作,比如挖掘dig,标记mark,当然了,还有一些返回私有成员的方法。为了和界面分开测试,我还添加了一个draw()方法,简单的将游戏地图输出。
这么一分析,这个模型还是很简单的。不废话,上代码:
enum gameState{
PLAYING,
WIN,
LOSE
};
class block {
public:
block(int theRow = 8,int theCol = 15,int theTotalBomb = 20);
~block() = default;
public:
//method
void draw() const;
void dig(int theRow,int theCol);
void mark(int theRow, int theCol);
bool isBomb(int theRow,int theCol) const;
int getRow() const;
int getCol() const;
int getBombNum() const;
gameState checkGame();
public:
vector<vector<unit>> map;
private:
int row;//行
int col;//列数
int totalBomb;
int restNum;
gameState curGameState;
private:
void calBombNum();
int calBombnum(int theRow,int theCol) const;
};
这里大部分的方法还是很好编写的,因为最后会给出完整工程,所以我就不一一介绍了,主要把最关键的方法思路介绍一下。dig()在挖掘的时候如果遇到周围地雷数量为0的情况会自动向周围扩散,所以需要特别关注