龙空技术网

Qt 扫雷小游戏学习分享

老码身边那些趣事儿 95

前言:

现时朋友们对“扫雷递归算法java”大体比较注重,咱们都想要了解一些“扫雷递归算法java”的相关知识。那么小编同时在网络上网罗了一些关于“扫雷递归算法java””的相关文章,希望同学们能喜欢,兄弟们快快来学习一下吧!

最近搞了一个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%10 * 20, 0, 20, 27);
    //时间
    painters.drawPixmap(337, 7, num, rtime/100 *20, 0, 20, 27);
    painters.drawPixmap(357, 7, num, rtime%100/10 *20, 0, 20, 27);
    painters.drawPixmap(377, 7, num, rtime%10 *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);

运行测试,效果如图

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

标签: #扫雷递归算法java