麒麟等基于linux操作系统下的几款扫雷游戏总觉得不过瘾,自己动手做了一个。本程序参考了网上的几款主流游戏代码,加入自己的一些想法,分享一下。
开发环境:开发工具QTCreator,系统环境:麒麟操作系统。
游戏截图:
1.开发思路:
(1)难度设置,分为初级,中级和高级(自定义在下一个版本)。
初级:10行10列,10%的雷即10个雷;
中级:10行15列,15%的雷即20个雷;
高级:15行20列,20%的雷即60个雷。(上图中演示的中级难度已标记7个雷的效果)
需要在类定义中将行、列、雷概率分别定义。
(2)根据行、列、雷概率计算底图。
根据雷概率计算雷的数量,然后随机分配雷的位置,在计算每个非雷位置周围雷的数量,周围无雷则不显示数量。
(3)显示。
底图上显示周围雷数量(数字不同,颜色不同),雷用图标显示;之后在位置上加盖按钮掩盖这些数字和雷。
(4)游戏。
主要是按键操作。
鼠标左键时,位置上层按钮隐藏,显示下层数字。若数字为空(表示该位置周围没有1个雷),则打开一片区域(即从该位置遍历,直到周围都是数字)。
鼠标右键时,标记该位置为地雷。即使用旗帜图标在上层按钮上显示,按钮不隐藏。
(双键暂未实现,下一个版本实现)
(5)判断结束。
左键点击雷时,失败结束。
每次点击左键或右键时,做成功检验。当标记出全部雷时成功(无论是否还有未标记和未翻开的位置);剩余未翻开的位置均是雷时成功(无论标记数量和雷的总数是否相等)。
(6)计时和记录。
当游戏开始或重置时,开始计时(精度为100毫秒);游戏结束计时停止;游戏成功保存游戏记录(玩家、难度、用时)。
2.代码实现。
话不多说,关键代码实现如下(完整程序和工程文件、代码在附件中下载)。
(1)初始化。
定义行、列、雷概率等成员变量。
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
void initItems();
void display();
void allOpen();
void openArea(int);
void showMineNum();
void displayRecord();
void timerEvent(QTimerEvent *event);
bool checkwin();
~MainWindow();
private:
Ui::MainWindow *ui;
QVector<Item> items;
QVector<mineRecoder> records;
int m_num; // 数组行、列数
int m_row;
int m_column;
int m_minePro; // 雷概率
int mineNum; // 剩余雷数量
int useTime; //使用时间
int timerID; //时钟ID
bool eventFilter(QObject *watched, QEvent *event);
void readRecord();
void writeRecord();
}
其中,Item类定义为(定义位置):
class Item
{
public:
Item();
Item(QPoint pos);
QPoint m_pos;
bool m_bIsMine;
bool m_bIsMarked;
int m_nNumber;
bool m_bOpen;
};
初始化数据和位置:
void MainWindow::initItems()
{
// 初始化数组
int i,j,k,rx,ry ;
items.resize(m_row * m_column); // 行数*列数 数组
this->useTime = 0;
for(i = 0 ; i < items.length();i++ )
{
items[i].m_bIsMarked = false;
items[i].m_bIsMine = false;
items[i].m_bOpen = false;
items[i].m_nNumber = 0;
rx = static_cast<int> (i / m_