Qt 扫雷小游戏学习分享

Qt 扫雷小游戏学习分享

首页休闲益智扫雷手游更新时间:2024-06-06

最近搞了一个qt的小游戏,现在在这里分享给大家,一起来学习一下。

一、功能简介:

1、鼠标左键翻开格子。若周围没有雷,则会爆出一大片,效果如图1所示。

2、右键插上红旗,表示有雷,效果如图2所示。

3、左上角的数字表示剩余雷数。当点击右键给格子插上红旗时,数字会自动减1。当减少到零时,游戏会自动提示扫雷成功或失败,效果如图3所示。

4、顶部的笑脸表示游戏继续,伤心表示游戏结束。当鼠标左键点击该位置时,表示重新开始游戏。

5、右上角的数字表示扫雷的时间(s)。当时间大于999s时,游戏会自动弹出超时提示框,并结束游戏。

图1

图2

图3

二、原理描述:

1、每个格子都保存一位数字。0~8表示这一格周围8格子中的雷数;50~58表示格子插上红旗;99表示该格子为雷;当左键翻开后,将格子中的数加上100,保存新的数值,即——100~108表示该格子已翻开,并且不是雷(0~8加上100);150~158表示插有红旗的格子翻开(10~58 100);199表示埋雷的格子被翻开。。。

2、当左键翻开一个格子时,程序会自动检测其周围格子,并将不是雷的翻开。当遇到格子周围都没有雷的时候,程序会递归点击周围的8个格子。

3、当确定格子埋有雷的时候,可右键点击插上红旗作标注。

接下来教大家如何创建工程并用代码实现该游戏。

三、实现过程

1、创建工程

打开qt creator软件,然后点击New Project。

图4

2、选择模板

模板选择Application -> Qt Widget Application,之后点击“Choose”。

图5

3、项目名称和位置

给项目添加名称,并可以修改项目保存的位置,然后点击“下一步”。

图6

3、类名

可修改类名。删掉“创建界面”的沟。

图7

4、完成创建

直接点击“完成”即可。

图8

之后可看到如下界面。

图9

5、初始化界面

初始化窗口大小以及标题,在mainwindow.h文件中添加以下信息。

#define GRID_X 20 //行 多少行地雷

#define GRID_Y 15 //列 多少列地雷

#define GAME_NAME "扫雷" //标题

在mainwindow.cpp中的构造函数MainWindow添加如下代码——

setWindowTitle("扫雷"); //设置标题

setFixedSize(GRID_X*20,GRID_Y*20 40); //设置窗口大小 20表示格子大小,40是留给另外部件的

运行效果如下图:

图10

6、添加资源

为了美化游戏界面,我们需要添加一些图片资源。步骤如下——

6.1 右键点击项目,然后点击“添加新文件”,如图:

图11

选择Qt -> Qt Resourse File;

图12

设置资源文件名,如:res

图13

生成资源文件res.qrc

图14

在项目的同级目录下创建文件夹res,并将准备好的图片文件粘贴进去

图15

然后鼠标右键点击res.qrc文件,选中Open in Editor

图15

添加前缀" / "

图16

添加res文件夹下的图片资源。直接选中所有图片文件,然后“打开”即可。保存所有文件

图17

7、添加图标

在mainWindow.cpp的构造函数追加如下代码,即可给界面添加图标

setWindowIcon(QIcon(":/res/mine.ico"));

运行测试:

图18

8、实现顶部界面

在界面顶部实现地雷数目、表情以及游戏时间的展示。

首先在mainwindow.h的类中添加以下代码——

int nMine; //地雷数目

int rtime; //游戏时间

int m_face; //表情包

void paintEvent(QPaintEvent *); //绘画事件

此外还要添加两个头文件

#include <QPixmap>

#include <QPainter>

对于mainwindow.cpp文件,先在构造函数中添加以下代码,初始化变量——

nMine = 50; //50个地雷

rtime = 0; //时间 0s

m_face = 1; //笑脸

然后重写绘画事件paintEvent——

void MainWindow::paintEvent(QPaintEvent *)

{

QPixmap num(":/res/item1.bmp");

QPixmap mine(":/res/item2.bmp");

QPixmap top(":/res/item3.bmp");

QPixmap face(":/res/item4.bmp");

QPainter painters(this);

//顶部框架

painters.drawPixmap(0, 0, top, 0, 0, 70, 40);

painters.drawPixmap(180, 0, top, 80, 0, 40, 40);

painters.drawPixmap(330, 0, top, 130, 0, 70, 40);

painters.drawPixmap(70, 0, 110, 40, top, 70, 0, 10, 40);

painters.drawPixmap(220, 0, 110, 40, top, 70, 0, 10, 40);

painters.drawPixmap(180 7, 7, face, m_face * 24, 0, 24, 24);

//剩余雷数目

painters.drawPixmap(27, 7, num, nMine/10 * 20, 0, 20, 27);

painters.drawPixmap(7, 7, num, 0, 0, 20, 27);

painters.drawPixmap(47, 7, num, nMine * 20, 0, 20, 27);

//时间

painters.drawPixmap(337, 7, num, rtime/100 *20, 0, 20, 27);

painters.drawPixmap(357, 7, num, rtime0/10 *20, 0, 20, 27);

painters.drawPixmap(377, 7, num, rtime *20, 0, 20, 27);

}

运行调试:

9、实现游戏时间跳转

实现界面右上角的时间跳转

在mainwindow.h文件中添加头文件

#include <QTimer>

在类中添加如下代码

QTimer m_timer; //定时器

public slots:

void updateTime(); //槽函数 更新时间

对于mainwindow.cpp文件,在构造函数添加如下代码,建立信号与槽,并启动定时器

connect(&m_timer, SIGNAL(timeout()), this, SLOT(updateTime()));

m_timer.start(1000); //超时时间为1s

再实现槽函数updateTime

void MainWindow::updateTime()

{

rtime ;

update();

}

测试运行,可看到右上角时间的变化

10、埋地雷

初始化界面下方的格子,并埋下50个地雷。

在mainwindow.h头文件中添加一头文件,

#include <ctime>

在类中添加以下代码

int grid[GRID_Y][GRID_X]; //表示格子

void restart(); //重新开始

对于mainwindow.cpp文件,在构造函数中调用restart函数

restart();

然后实现restart函数

void MainWindow::restart()

{

for(int j=0; j<GRID_X; j )

{

for(int i=0; i<GRID_Y; i )

{

grid[j][i] = 0;

}

}

qsrand(time(NULL));

for(int i=0; i<50; i ) //埋50个地雷

{

int x = rand() % GRID_X;

int y = rand() % GRID_Y;

if(grid[x][y] != 99)

{

grid[x][y] = 99;

}

else

{

i--;

}

}

for(int x=0; x<GRID_X; x ) //计算每个格子周围的地雷

{

for(int y=0; y<GRID_Y; y )

{

if(grid[x][y] == 99) //当检测到地雷时,将周围格子中的数加1

{

for(int i=-1; i<=1; i )

{

for(int j=-1; j<=1; j )

{

if(x i<0 || x i>=GRID_X || y j<0 || y j>=GRID_Y || grid[x i][y j]==99)

continue;

grid[x i][y j] ;

}

}

}

}

}

}

这里还需要将刚才的以下一些变量初始化代码剪切到restart函数里,这是因为重新开始游戏时,这些变量需要重新被初始化。

nMine = 50;

rtime = 0;

m_face = 1;

connect(&m_timer, SIGNAL(timeout()), this, SLOT(updateTime()));

m_timer.start(1000);

运行测试,效果如图

由于篇幅过长,剩余的功能留待下回讲解!!!

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved