Qt--扫雷游戏---教程+源码

  好久之前写了个扫雷,趁着今天有时间,将其发布上来,废话不多说,Let's do it!

  先看一下初步效果图

                                                                                                                Qt--扫雷游戏---教程+源码_第1张图片

1、简介

    本项目采用QT编程实现扫雷游戏。项目可分为如下四个模块:界面显示、操作响应、子窗口与菜单栏实现、游戏类的设计。使用Qpixmap类向界面绘制基本的bmp图片,包括标题、表情、红旗数、时间计时、雷区,使用QmouseEvent事件对鼠标操作进行监听,当用户操作时,确定相应的鼠标位置与类型,更改游戏类的属性后再次调用界面绘制函数update,对界面实现更新重绘,然后等待用户下一次操作或结束。本项目实现了扫雷游戏的基本操作,左键挖雷、右键插旗,添加计时器对游戏计时,添加菜单栏,提供不同难度的雷区供用户选择,可让用户自主设置雷区行列,添加了提示框与基于对话框的子窗口与用户进行交互。

  流程图如下:

Qt--扫雷游戏---教程+源码_第2张图片


2、游戏类block的实现


     2.1、雷区的分析抽象

游戏地图即(雷区)由一个个雷块组成, 因此可将雷区定义为一个block类,用二维雷块数组表示雷区。那么下一步的问题在于如何去描述这个雷块?

对雷块进行需求分析,雷块中必须包含有扫雷所需的信息,如:此雷块是否为炸弹、是否被标上红旗、是否被挖掘、若不是炸弹则需保存周围炸弹的数量。总结后归纳此雷块需包含以下四个方面信息:

1、是否炸弹

2、挖掘状态

3、周围雷数

4、有无红旗

所以将雷块的数据结构定义为一个结构体,包含以上信息?

经过思考后发现这太浪费内存资源,实际上可以用Int类型便可表示以上信息。

0-8         -----      该块周围雷数(未翻开)   X

50-58       -----      该块有红旗。             X+50 

100-108     -----      该块周围雷数(已翻开)   X+100

99          -----      该块为雷 

145         -----      该块为雷且有红旗

简单来说即每个雷块存储一个0-8范围内的数设为X,当其被标记上红旗时,将其加上50,即为X+50,若其被挖掘,则将其加上100,即为X+100.若其为雷,则其内数为99,标上红旗则加上50,即为145.

    

 2.2、block类成员分析

block类中的私有成员需包括雷区的行数、列数、炸弹数、红旗数、计时时间及雷块的二维数组。由于本课题扫雷支持用户选择难度,可自定义雷区行列及炸弹数,因此需要能动态创建雷块的二维数组,即动态创建一个Int类型的二维数组,其参数为行数、列数、炸弹数。

因此block类中需要保存一个二级指针**p,用其指向一个指针数组,再将指针数组内的每一个指针指向一个数组。

如下图所示从而实现动态创建二维数组的功能。

                                          Qt--扫雷游戏---教程+源码_第3张图片


2.3、block类具体实现

block类构造函数流程如下图所示:

                                                               Qt--扫雷游戏---教程+源码_第4张图片

3、游戏界面绘制


3.1、标题框架的绘制

框架的绘制包括标题、表情、计时时间、红旗数的绘制。

其主要用到了QPainter函数作为窗口重绘事件函数提供接口被调用。

需要注意的是:当用户在操作游戏时,游戏界面在不断进行重绘,进行刷新。

使用Qpixmap类对如下bmp图像进行绘制在窗口上。


                                              

由于本游戏提供雷区大小可变,如初中高级或用户自定义行列数,所以在绘制的时候不能简单的将图片贴上,还需要进行缩放,以及位置的确定。

游戏中将每个图片的像素大小进行定义,采用等比例的方法进行位置确定,如titil为200时表情的位置应在10,则titil为300时,表情的位置应该为10*300/200。下图为定义的图标的像素大小。


                                                                                          Qt--扫雷游戏---教程+源码_第5张图片

3.2、雷区的绘制

 雷区的绘制需要根据游戏的不同状态而进行不同的绘制,如失败与成功的雷区绘制就不同。但雷区总体的绘制是思路是一样的,通过遍历block类中二维数组内的信息进行绘制。下面就拿正常情况下左键点击一个非炸弹块的雷区绘制作为例子。

     1.雷区绘制函数遍历二维数组。

     2.若某块p[row][col]属于0-8或99,说明其未挖掘,则绘制该块为未挖掘的图片。

     3.若某块p[row][col]属于50-58,说明其未挖掘且其上有红旗,绘制该块为红旗。

     4.若某块p[row][col]属于100-108,说明其已挖掘,则绘制该块为该块内存的数字。

     5.若某块p[row][col]等于149,说明其为炸弹且标有红旗,绘制该块为红旗。


4、鼠标操作响应


4.1、鼠标类型与坐标的确定

 Qt中存在有QmouseEvent类对鼠标操作事件进行监听,当用户点击事件产生时,会自动调用mousePressEvent(*event)函数,其中mousePressEvent是一个虚函数,可以根据用户的需求进行重写。

1.通过eventàbuttons()可获得鼠标点击类型。

例如判断用户是否点击了左键:if(event->buttons()==(Qt::LeftButton))。

2.通过eventàx(),eventày()可获得鼠标的点击位置。在Qt程序坐标系中,原点在整个窗口的左上角,向右为x正方向,想下为y正方向

                                Qt--扫雷游戏---教程+源码_第6张图片

  则若点击位置是雷区的某一块,则可使用以下转换获取点击的行列数。

  click_x = click_x/BLOCK_LENGTH;

  click_y =(click_y-TITILE_HEIGH)/BLOCK_HEIGH;


4.2、响应函数的逻辑编写

当用户进入鼠标函数时,总体逻辑如下。

   1.判断鼠标点击位置。

若为点击为笑脸处,则重新开始游戏,即重新创建类并调用重绘函数;

若点击处为标题上部的空白处(非雷区),则不做处理;

若点击位置为雷区,则进行下一步2。

   2.判断鼠标点击类型。

若为左键,则判断点击块是否为炸弹,若为炸弹,则结束游戏,即修改类属性后调用界面重绘函数;若不是炸弹,则检查用户是否胜利,随后修改类属性后调用重绘函数。

若为右键,则判断该块上是否有红旗,若有红旗则消去红旗,若无红旗则加上红旗,随后修改类属性即加减50数值,调用界面重绘函数。


4.3、左键点击算法分析

当一个格子(坐标为(x,y))被点下,如果个格子周围有雷,则p[x][y]值为100-108,将这个值减去100后进行显示便可.如果周围都没有雷,就会爆出一大片,就是下面这种效果


                                    Qt--扫雷游戏---教程+源码_第7张图片

解决思路:当点下该点发现其周围都没雷(即值为0)的时候就递归的点击周围8个格子,具体实现如下图所示:

Qt--扫雷游戏---教程+源码_第8张图片



5、子窗口与菜单栏


5.1、菜单栏及弹出窗口的实现

本游戏使用Qt Creator自带的图形界面绘制菜单栏,包括添加用户自定义难度选择,帮助、版权关于等栏项。
建立信号与相关槽函数的响应,进行相应的操作及弹出提示窗口。
当用户点击初级、中级、高级选项时,程序需要重新创建对应难度的雷区,并进行窗口重绘。当用户点击help、How to play 等选项时,进行调用QmessageBox类进行弹出窗口,将标题与内容作为参数传入函数即可。

下面是加载自定义图片的弹出窗口实现代码:


 QMessageBox message(QMessageBox::NoIcon, "so easy", "");
    message.setIconPixmap(QPixmap("baidu.png"));
  message.exec();

5.1、基于对话框的子窗口的实现

当用户点击自定义游戏时,界面会弹出子窗口对话框供用户选择输入行列数、炸弹数信息。如图所示

                                         Qt--扫雷游戏---教程+源码_第9张图片

子窗口的实现由代码绘制实现,在工程中加入子窗口类,并建立信号槽,当用户点击主窗口菜单栏选项时弹出。

当用户填写完雷区信息并点确定时,需要将子窗口内的填写信息返回,并将其用于block类的创建初始化,重新绘制界面。


6、实现效果


                            Qt--扫雷游戏---教程+源码_第10张图片
             

    其实要做一个扫雷,主要解决三个方面问题。

     1、如何管理雷区,用变量标定每个雷块的状态

     2、掌握信号槽,获取用户的点击鼠标的事件

     3、显示图片,游戏运行过程中不断的重绘界面,主要是绘制雷区

     剩下的就很简单,该优化的优化。

     源码下载处:http://download.csdn.net/download/qq_34771697/10180602

     注意:该文件分为两部分,一部分为文件,另一部分为扫雷工程,需要将图片放入QT编译后的文件夹才能正常运行。


 

本文章由@风浅_wei 出品,转载请注明出处。  

邮箱: [email protected]@qq.com

写作当前博文时配套使用的Qt版本: 5.0.2


你可能感兴趣的:(Qt--扫雷游戏---教程+源码)