基于Qt的连连看小游戏(总结)

自学Qt也有一段时间了,最近用Qt写了一个连连看的小游戏。总结一下在这个小程序中用到的技术。
为了把游戏的消除逻辑和界面分开,分别设计了两个类来进行封装,此外还设计了一个类用于设定关卡和计算得分。

-消除类
游戏中要消除的方块使用的是QPushButton,可以根据isCheck()判断按钮是否被选中。为了标志两个按钮的图案(图标)是否相同,继承了QPushButton类实现了自己的自定义按钮,并在按钮中添加了成员变量flag,把具有相同图标的按钮设定为相同flag。

用QVector类保存在游戏中要用到的button,因为QVector是变长的,可以很方便的从里面增加或者删除元素,而且可以用下标访问里面的元素。

进行消除判定时,首先需要找到两个被选中的按钮。找到相同按钮有几种思路:
1).用一个循环不断遍历Vector中的元素,以找到两个被选中的按钮。
这种方法十分耗时,并且容易造成界面卡死。舍弃。
(如果在Qt中进行比较耗时的操作时,可以创建一个线程单独运行耗时操作)
2).不是连续不断遍历数组,而是创建一个定时器,每隔一定时间间隔(比如100ms)遍历一次Vector,找到两个被选中的按钮。
这种思路可行,但是同样可能会对Vector进行一些不必要的访问
3).通过查找帮助手册,QObject类有一个sender()成员函数,可以获得发出信号的对象的指针。按钮被点击时会发出clicked()信号,因此先用一个循环将Vector中的所有按钮的clicked()信号和查找按钮的槽函数连接起来,在槽函数中调用sender函数,这样每当有按钮被点击时,就可以得到被点击的按钮的指针。
该程序中使用的是方案三。代码如下:

//连接按钮的信号和槽
for( int i=0; i<m_hor*m_ver; i++ )connect( m_block[i], SIGNAL(clicked()),this,SLOT(runGame()));
//在槽中调用sender()函数得到被点击的按钮的指针
MyPushButton* btn = qobject_cast<MyPushButton*>(QObject::sender());

找到两个按钮后,需要判断这两个按钮是否可以消除。思路是从当前按钮出发,向上、下、左、右四个方向寻找目标按钮,如果没有找到,就以下一个按钮作为当前按钮。用递归来实现。在递归中要注意的两个问题:
1).为了避免无限递归,该按钮不应向它的上一个按钮进行递归调用。
2).连连看的规则要求两个消除方块间的连线不能超过三条,即按钮的转弯次数不能超过两次。所以在递归函数中增加一个参数传入转弯次数。此外,转弯次数不超过两次也可以避免递归调用回到原始位置。
递归的部分代码如下:

if(dir != DOWN){//如果转弯,转弯次数+1if(dir==LEFT || dir==RIGHT)turn++;if(current > current%m_hor){if(current-m_hor == dest && turn <= 2)return true;else if(!m_block[current-m_hor]->isVisible()){if(judgement(current-m_hor,dest,UP,turn))return true;}}//如果没有找到目标按钮,恢复转弯次数if(dir == LEFT || dir == RIGHT)turn--;}

-界面类
-多界面切换
游戏共有四个界面:主界面、游戏界面、规则说明界面及最高分界面。使用Qt的QStackWidget类添加界面,用setCurrentIndex(int)函数切换界面。
-绘制背景图片
重写QPaintEvent()函数

QPainter painter (this);//绘制主界面QRect rcMain = rect();painter.setClipRect(rcMain);for (int m = rcMain.left (); m < rcMain.right ();m += m_mainBackground.width ())for (int n = rcMain.top ();n < rcMain.bottom ();n += m_mainBackground.height ())painter.drawImage(m,n,m_mainBackground);

-设置按钮在不同状态下的显示
通过样式表设定按钮的不同显示状态。
可以直接在按钮上右键点击,选择改变样式表,设置样式表:

也可以在代码中设置:

btnStart->setStyleSheet(
"QPushButton{border-image:url(:image/Image/red2.png)};"
"QPushButton:hover{border-image:url(":image/Image/red2clicked.png")};");

设置好的按钮:
正常态:

悬停态(鼠标停留在按钮上时):

-设置时间槽样式
游戏中的时间槽用的QSlider类。为了让游戏的时间槽更好看一点,也可以通过样式表实现。

设置好的时间槽:

在设置样式表时需要注意的一个问题是,如果给当前窗口设置了样式表,该窗口的所有子部件也会被设置为相同的样式表

-背景音乐
最开始用QSound类的对象播放背景音乐,该类中有一个setLoops(int)成员函数,当参数为-1时,表示无限循环播放。该类只支持WAV格式的音频。
在该程序中,采用Phonon多媒体框架来播放音频。
使用Phonon需要在项目文件中添加 QT+=Phonon。
音频/或者视频不能放在资源文件中,只能以外部文件形式存在。

//添加并播放背景音乐
mediaObject = new Phonon::MediaObject(this);mediaObject->setCurrentSource(Phonon::MediaSource("../LinkGame1.1/music/music.wav"));Phonon::AudioOutput *audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);Phonon::createPath(mediaObject, audioOutput);mediaObject->play();

怎样实现循环播放呢?查找帮助手册,MediaObject类中有一个aboutToFinish()信号,当播放将要结束时该信号会被发出,于是通过这个信号连接一个槽函数,在槽函数中再次播放音频。

connect(mediaObject,SIGNAL(aboutToFinish()),this,SLOT(playMusic()));
void LinkWidget::playMusic()
{mediaObject->setCurrentSource(Phonon::MediaSource("../LinkGame1.1/music/music.wav"));mediaObject->play();
}

这样即可实现背景音乐的循环播放
-音量调节

volumeSlider = new Phonon::VolumeSlider(this);volumeSlider->setAudioOutput(audioOutput);volumeSlider->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);volumeSlider->resize(150,8);ui->horLayout->addWidget(volumeSlider);

-得分类
该类中定义计分规则,包括连击数的计算,时间得分等,并根据消除的情况进行计分
-更新最高分
利用QFile读写文件

QFile file("../LinkGame1.1/hs.dat");file.open(QIODevice::ReadOnly);if(file.error() !=0 ){qDebug() << "open file failed!";return m_highScore;}QByteArray byte(20,'0');byte = file.readAll();if(file.error()){qDebug() << "read error!\n";file.close();return m_highScore;}bool ok;m_highScore = byte.toInt(&ok);file.close();

-生成和发布
生成release版本,将release文件夹中生成的exe可执行文件放入一个单独的文件夹,从Qt安装目录的bin目录下复制mingwm10.dll、lib_gcc_s_dw2-1.dll、QtCore4.dll、QtGui4.dll这四个文件到exe所在的目录,因为程序中使用了Phonon,所以还要复制phonon.dll文件和用到的音频/视频文件。此外,因为在程序中使用了非PNG格式的图片以及Phonon,所以还要复制Qt/plugins下的imageformats文件夹和phonon_backend文件夹。复制完打包之后就可以在别人的电脑上运行了。

本人第一次写博客,非常希望能和各位大牛们一起探讨学习。

附:游戏截图(图片素材来自于百度)
PS:自己P的界面,自己先吐槽一下。。。毕竟不是美工

基于Qt的连连看小游戏相关推荐

  1. 基于Qt的飞机小游戏实现

    目录 前言 一.准备工作 二.基本功能实现 1.主菜单 2.核心玩法 3.其他 资源文件 前言 这是学习Qt时期做的一个小项目,现在看感觉有很多可优化的地方,放在这里给新人朋友们提供一个参考. 一.准 ...

  2. java游戏界面制作_软件设计之基于Java的连连看小游戏(二)——游戏基础界面的制作及事件的添加...

    上次完成到游戏首页的制作,今天完成了游戏基础界面的制作以及事件的简单添加.由于功能尚未完全实现,因此游戏界面的菜单列表只是简单地添加了一下,其余菜单列表以及倒计时等在后续的制作中逐一完善. 1.首先在 ...

  3. 基于VS的连连看小游戏

    运行环境 Matlab R2018b x64 or x32 Visual Studio 2017 企业版 程序预览 目前功能只开发了基本模式,也即是基本的连连看功能和帮助功能,文末有完整程序代码下载地 ...

  4. 基于QT实现简单的连连看小游戏

    资源下载地址:https://download.csdn.net/download/sheziqiong/85788216 资源下载地址:https://download.csdn.net/downl ...

  5. QT横板格斗小游戏——基于网编的重构

    QT横板格斗小游戏--基于网编的重构 一.项目概览 二.具体功能设计 2.1 Npc基类 2.2 Boss子类 2.3 Hero类 2.4 Widget类 2.5 GameContral基类 2.6 ...

  6. eclipse如何做java游戏,:#急需基于eclipse的JAVA小游戏源代码!!!#-南开游戏网...

    #急需基于eclipse的JAVA小游戏源代码!!!# 2020-11-07 10:21:13 广告 急需基于eclipse的JAVA小游戏源代码!!! maxueruby001@163.COM 楼主 ...

  7. 基于pygame的射击小游戏制作(一)让飞船动起来

    基于pygame的射击小游戏制作(一)让飞船动起来 一.文件结构 alien_invasion.py 是整个系统的主文件,用来创建游戏中的一系列对象,ai_settings存储设置.screen存储显 ...

  8. 原生js实现一个连连看小游戏(一)

    前几天使用原生的js写了一个连连看小游戏,地址:连连看(js),基本功能都实现了,运行截图为: 根据游戏规则获取开发思路 创建棋盘格 生成随机不重复数字 映射到棋盘格 鼠标点击事件 寻路,无通路,则到 ...

  9. 基于 Blazor 开发五子棋小游戏

    今天是农历五月初五,端午节.在此,祝大家端午安康! 端午节是中华民族古老的传统节日之一.端午也称端五,端阳.此外,端午节还有许多别称,如:午日节.重五节.五月节.浴兰节.女儿节.天中节.地腊.诗人节. ...

  10. python连连看小游戏_利用Python制作一个连连看小游戏,边学边玩!

    导语 今天我们将制作一个连连看小游戏,让我们愉快地开始吧~ 开发工具 Python版本:3.6.4 相关模块: pygame模块: 以及一些Python自带的模块 环境搭建 安装Python并添加到环 ...

最新文章

  1. netstat [选项]
  2. Linux下route add 命令加入路由列表
  3. HDU 4634 Swipe Bo(搜索)
  4. 在微服务中如何管理数据
  5. 《Head First设计模式》第四章笔记 工厂模式
  6. 今天中国获得金牌数量是7块,位居奖牌榜首位
  7. 错误解决:src/cpp/cuda.hpp:  fatal error: cuda.h
  8. pyzabbix 删除触发器_Zabbix实现批量监控端口状态的方法
  9. 【考研日记1】:看到2016年数学考的如此之难后
  10. 今日制造怎么安装solidworks插件_PS插件安装后出现了登陆界面,无法使用怎么解决?保证一招搞定...
  11. ArcGIS各向异性计算
  12. IMDB电影评论文本的神经网络分类
  13. 【人脸表情识别】基于matlab GUI微表情识别系统【含Matlab源码 1852期】
  14. SMB 协议操作共享盘
  15. 关于 网易云音乐 我喜欢的音乐 排序无法改为添加时间 排序无法还原 的问题
  16. Oracle 12c 数据库的环境搭建以及安装过程
  17. vlookup使用步骤_vlookup怎么用详细步骤(vlookup函数的使用方法)
  18. ALLEGRO的约束规则的设置教程,手把手教你!
  19. 如何快速完成事业单位继续教育
  20. 二进制逻辑运算和基本门电路

热门文章

  1. Unity里加速纹理压缩
  2. 指令引用的内存不能为written怎么解决
  3. Java根据出生日期计算(判断)星座
  4. 现场总线PROFIBUS-DP在风力发电系统中的应用(内附详细说明)
  5. Jupyter notebook 运行时出现 “服务似乎挂掉了,但是会立刻重启的”
  6. Groovy 快速入门
  7. php设备巡检管理,设备巡检管理:你必须知道的4个玩法
  8. Java实现阿里云域名动态解析,DDNS功能
  9. 基于Php+MySql数据库架构的网络验证系统
  10. 考研日记2021年9月16日