Qt实现打地鼠游戏的方法详解

目录
  • 功能讲解
    • 1.确定地鼠数量
    • 2.定义游戏难易程序
    • 3.难度切换
    • 4.定时器处理
  • 总结

今天与大家分享一个小游戏的实现:打地鼠

看一下实现效果吧~

在指定的时间内打中一定数额的地鼠,否则失败,就如上述展示效果一样,自己写的小程序,居然连第二关也过不去,还挺尴尬的!

实现打地鼠小游戏不难,最主要的核心就是依靠定时器,按照一定间隔触发。接下来,我来讲解下是如何实现的吧!

功能讲解

开发环境:VS2017 + Qt5.14.2 x64

1.确定地鼠数量

对于打地鼠这款游戏来说,地鼠是从任意的洞口钻出。

在效果中,一共存在6个地鼠洞,最容易实现的方式:创建6个地鼠,每个地鼠洞都对应一个地鼠。

实现代码如下:

for (int i = 0; i < num; i++)
{
	QPushButton *btn = new QPushButton(this);
	int nTop = i / 3 == 0 ? 300 : 450;
	int nRemainder = i % 3;
	if (nRemainder == 0)
	{
		btn->setGeometry(190, nTop, 180, 130);
	}
	else if (nRemainder == 1)
	{
		btn->setGeometry(480, nTop, 180, 130);
	}
	else if(nRemainder == 2)
	{
		btn->setGeometry(780, nTop, 180, 130);
	}
	btn->setStyleSheet(qsBtnStyle);
	btn->setProperty("num", i);
	btn->hide();
	connect(btn, &QPushButton::clicked, this, &QGrameWhacAmole::OnBnClickedSusliks); //选中地鼠
	m_vetBtnCtrls.push_back(btn);
}

代码解析:

num:此刻代表的是6,表明了需要创建6个地鼠,平均分配到每个洞中。

对每个地鼠按钮响应对应的clicked消息,每当打中一个地鼠,OnBnClickedSusliks消息内就对分数+1。

并且,创建出的地鼠默认是隐藏状态的。

2.定义游戏难易程序

在程序中定义了四种难度,设置了枚举类型:

enum ENUM_GameMode
{
	GameMode_difficulty1,
	GameMode_difficulty2,
	GameMode_difficulty3,
	GameMode_difficulty4,
	GameMode_OK,
	GameMode_Failed,
};

GameMode_difficulty1:难度1,说明有1个地鼠出没

GameMode_difficulty2:难度2,说明有2个地鼠出没,

GameMode_difficulty3:难度3,说明有3个地鼠出没,

GameMode_difficulty4:难度4,说明有4个地鼠出没

在程序中,如何判断通过某一关呢?

宏定义确定通关分数

#define  difficulty1Count 10 //难度1个数
#define  difficulty2Count 30
#define  difficulty3Count 60
#define  difficulty4Count 100

当第一关时,只需要打中10个地鼠;第二关需要累计打中30个地鼠,以此类推。

3.难度切换

在OnBnClickedSusliks消息中,根据当前的分数来确定是否要晋级。

响应消息后,对分数进行+1处理

m_nScore += 1;

m_nScore是当前类的成员变量,表示:打中的地鼠次数也就是当前分数。

打中后隐藏该地鼠

当打中某个地鼠后,需要立刻隐藏地鼠,此时就运用到了刚刚在创建地鼠时"setProperty"绑定的变量了。

QPushButton *btn = qobject_cast<QPushButton*>(sender());
int num = btn->property("num").toInt();
m_vetBtnCtrls[num]->hide(); //隐藏对应编号控件

分数判断是否晋级

当分数到达难度1时,晋升成难度2,其它的关卡都一样

if (m_nScore == difficulty1Count) //难度1通过
{
	killTimer(m_nTimerStartId);
	m_nTimerStartId = 0;

	this->HideTotalSucliks();

	m_enumMode = GameMode_difficulty2;
	this->SetTipsStyle(m_enumMode);

	m_nTimerStartId = startTimer(difficulty2Time);
	m_dwBeginTime = GetTickCount();
}

当通过第一关后,停止定时器,隐藏正在展示的所有地鼠,更改模式状态,重新设置提示文本,开始定时器,重新记录开始通关时间。

m_dwBeginTime:是记录每次开始游戏时的时间,主要作用于挑战失败的判断,也就是说,每次触发定时器时,当前最新时间与最开始通关时间的差值 大于 通关时间时,说明当前关卡挑战失败!

4.定时器处理

这也是当前小游戏中最核心的处理部分了~

为了方便起见,直接使用QWidget自带的定时器,而不是使用new QTimer的方式

virtual void timerEvent(QTimerEvent *event);

在定时器的处理中,分成了4部分,我们分别讲述~

获取定时器Id的触发消息

if (event->timerId() == m_nTimerStartId)
{
    //消息处理
}

只有当定时器的触发id与我们设定的id一致时,才可以。

关闭提示页面

在进行难度切换时,设置了提示文本,也就是效果图中的“开始”、“开始第二关”等文字提示信息,在进入到定时器事件中,首先判断,该控件是否隐藏?如果未隐藏,先进行隐藏。

if (ui.labTips->isHidden() == false)
{
	ui.labTips->hide();
}

在这里需要我走过一个坑:使用isVisible()不一定获取出控件的显示状态,但是isHidden()始终是有效的

判断当前关卡是否超时?

这也就是上文说到的m_dwBeginTime与最新触发时间的差值

DWORD dwTime = GetTickCount() - m_dwBeginTime;
if (dwTime > difficultyTimeout)
{
	this->RunningFailed();
}

根据关卡不同,显示不同的地鼠

这里,就是对地鼠显示的逻辑处理了,根据枚举模式不同,分别处理

switch (m_enumMode)
{
case QGrameWhacAmole::GameMode_difficulty1:
	this->RunningGamedifficulty(1);
break;
case QGrameWhacAmole::GameMode_difficulty2:
	this->RunningGamedifficulty(2);
break;
case QGrameWhacAmole::GameMode_difficulty3:
	this->RunningGamedifficulty(3);
break;
case QGrameWhacAmole::GameMode_difficulty4:
	this->RunningGamedifficulty(4);
break;
default:
break;
}

核心函数是:RunningGamedifficulty

如何让地鼠进行随机显示呢?

在当前例子中,获取随机数[0,6)之间的值,随机到哪个数,哪个下标下对应的地鼠被显示,其余的地鼠处于隐藏状态。

随机数生成方法:

int QGrameWhacAmole::GetRandomNumber()
{
	QTime time = QTime::currentTime();
	qsrand(time.msec() + time.second() * 1000);
	int n = qrand() % 6;
	return n;
}

有人说使用这种方法可以在短时间内生成的随机数不相同,这个方法我已经验证过了,不行!

还有的人说可以添加sleep,我也尝试过了,不行!

那么,该如何获取不重复的随机数呢?

在这里,采用了std::set<int>容器的方式,RunningGamedifficulty中的部分代码如下:

void QGrameWhacAmole::RunningGamedifficulty(int nCount)
{
    1:随机数生成
    std::set<int> setRandom; //存储随机数
    for (int i = 0; setRandom.size() < nCount; i++)
    {
	//获取随机数
	int num = this->GetRandomNumber();
	//如果随机数在容器中从未出现过,存储并应用
	if (setRandom.size() != 0)
	{
		std::set<int>::iterator itFind = setRandom.find(num);
		if (itFind != setRandom.end())
		{
			continue; //存在重复值,后续不进行处理
		}
	}
	//容器中存在数据,存储之前进行判断
	setRandom.insert(num);
     }

}

根据上述代码也可以看出,每生成一个随机数,就进行存储,当容器中出现相同的随机数时,重新生成。

nCount:就是需要展示的地鼠个数,在for循环中,中间的判断条件与以往不同,当有效地地鼠编号大于地鼠个数后,就不再获取随机数了。

这种方式,无论是获取多少个地鼠个数都是适用的。

其次,根据获取的显示的地鼠下标数就可以对所有的地鼠进行做显示、隐藏操作了,代码如下:

for (int m = 0; m < m_vetBtnCtrls.size(); m++)
{
	std::set<int>::iterator itNum = setRandom.find(m);
	if (itNum != setRandom.end())
	{
		m_vetBtnCtrls[m]->show();
	}
	else
	{
		m_vetBtnCtrls[m]->hide();
	}
}

总结

到这里,核心的实现功能就已经讲解完了,功能难点:

1:根据地鼠个数随机显示地鼠位置(RunningGamedifficulty处理逻辑)。

2:关卡晋级。

3:挑战失败处理。

到此这篇关于Qt实现打地鼠游戏的方法详解的文章就介绍到这了,更多相关Qt打地鼠游戏内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • QT实现简单五子棋游戏

    本文实例为大家分享了QT实现简单五子棋游戏的具体代码,供大家参考,具体内容如下 FIR.pro #------------------------------------------------- # # Project created by QtCreator 2012-09-01T15:09:11 # #------------------------------------------------- QT += core gui TARGET = FIR TEMPLATE = app SO

  • QT实现五子棋游戏

    本文实例为大家分享了QT实现五子棋游戏的具体代码,供大家参考,具体内容如下 有点bug 但是能运行 每次点击右边会出现提示图标,表示是黑方落子还是白方并计时,不过不知道为什么点的次数多了 就不出现提示了 然后过一会又有了![Alt] 代码片: #include "widget.h" #include "ui_widget.h" #include <QPainter> #include <QBrush> #include <QMouseE

  • QT实现贪吃蛇游戏代码详解

    目录 一.新建一个Qt项目 二.添加要用到的头文件 三.写类声明信息 四.对类函数的实现 构造函数 界面刷新 随机奖励的生成 移动 绘图 按键事件 判断蛇身是否相撞 五.结束 一.新建一个Qt项目 新建Qt Widgets Application,项目名称为HappySnake,基类选择QWidget,类名默认 二.添加要用到的头文件 #include <QKeyEvent> #include <QRectF> #include <QPainter> #include

  • Qt实现棋盘游戏

    本文实例为大家分享了Qt实现棋盘游戏的具体代码,供大家参考,具体内容如下 知识点 1.画背景图.线条 2.qDebug()与QString联合使用 qDebug()<<QString("(%1,%2)").arg(checkX).arg(checkY); 结果演示 widget.h #ifndef WIDGET_H #define WIDGET_H #include <QWidget> namespace Ui { class Widget; } class W

  • QT实现简单打地鼠游戏

    本文实例为大家分享了QT实现简单打地鼠游戏的具体代码,供大家参考,具体内容如下 开发工具:VS2017,qt5.9.8 开发语言:c++ 实现功能: 有若干地鼠洞,每次出现一只地鼠,当击中地鼠后,分数加1,地鼠更换位置.当分数大于20时,游戏结束. 实现思路: 1.先初始化一个页面,放一只地鼠和若干个地鼠洞,为地鼠和地鼠洞添加槽函数.  2.当点击时就执行相应函数.判断是否击中,从而对其进行加分或者减分.  3.当击中地鼠后,应该刷新页面,让地鼠换个位置出现.  4.重复2.3,直到分数到达一定

  • Qt实现打地鼠游戏的方法详解

    目录 功能讲解 1.确定地鼠数量 2.定义游戏难易程序 3.难度切换 4.定时器处理 总结 今天与大家分享一个小游戏的实现:打地鼠 看一下实现效果吧~ 在指定的时间内打中一定数额的地鼠,否则失败,就如上述展示效果一样,自己写的小程序,居然连第二关也过不去,还挺尴尬的! 实现打地鼠小游戏不难,最主要的核心就是依靠定时器,按照一定间隔触发.接下来,我来讲解下是如何实现的吧! 功能讲解 开发环境:VS2017 + Qt5.14.2 x64 1.确定地鼠数量 对于打地鼠这款游戏来说,地鼠是从任意的洞口钻

  • python为QT程序添加图标的方法详解

    Qt是一种基于C++的跨平台图形用户界面应用程序开发框架.如何跨平台?上到服务器上位机,下到嵌入式GUI,上天入地无所不能.Qt最早是由1991年由Qt Company开发,但是到2008年,Qt Company科技被诺基亚公司收购,是的,就是拥有着我们很多情怀的诺基亚.但在2012年,Qt又被Digia收购.等到了2014年,跨平台集成开发环境Qt Creator 3.1.0正式发布出来,至此,全面支持iOS.Android.WP,QT的时代开始逐步展开. 本文重点给大家介绍python为QT

  • Python实现猜拳与猜数字游戏的方法详解

    至此,我们的 Python零基础入门篇 的系列专栏到今天基本上算是结束了.今天没有任何的知识点,只是运用我们之前学习过的知识做两个小游戏的案例.第一个是模拟猜拳的小游戏,第二个就是猜数字的游戏. 猜拳小游戏 需求: 运用至今所学的 Python 知识编写脚本,实现一个人与计算机玩猜拳的石头剪刀布的小游戏. 这里我们先思考一下,如果将石头.剪刀.布分别用数字0.1.2表示,那么如何判定谁胜谁负呢? user robot 结果 0(石头) 0(石头) 平局 0(石头) 1(剪刀) user 获胜 0

  • Java实现简易拼图游戏的方法详解

    目录 效果展示 游戏结构 实现代码 效果展示 介绍:游戏共有五张图片可以选择,分成了4 X 4 十六个方格,点击开始就可以开始游戏.游戏运行的截图如下: 游戏结构 实现代码 代码如下:MedleyGame.java类 package game.medleyPicture; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.even

  • JavaScript实现五子棋游戏的方法详解

    本文实例讲述了JavaScript实现五子棋游戏的方法.分享给大家供大家参考,具体如下: 最近半个月一直在看深入的学习JavaScript,里面有很多重点和难点,比如闭包.词法分析.面向对象等.今天给大家分享一个由JavaScript编写的五子棋游戏,主要用到JavaScript的面向对象.事件委托.闭包等知识,还是挺有分量的,正好可以检测学习的成果. 老规矩,先上图,再说话. 效果图: 五子棋素材图: 代码: <!DOCTYPE html> <html> <head>

  • 原生javascript制作的拼图游戏实现方法详解

    本文实例讲述了原生javascript制作的拼图游戏实现方法.分享给大家供大家参考,具体如下: 实现方法 //1.让所有的li(在ul里)可以拖拽 //2.交换li的位置  计算背景图位置 //1.让所有的li(在ul里)可以拖拽 //根据鼠标的位置,计算目标li的序号 //根据行号和列号计算下标 //行号*3+列号 //2.归位 此处没有背景图  请自行添加 css样式 <!DOCTYPE html> <html> <head> <meta charset=&q

  • Qt写入Json文件的方法详解(含源码+注释)

    目录 一.示例Json文件内容 二.Json写入会使用的类(介绍写入所使用的类在本文中的作用,个人理解) 三.Json文件的写入 3.1 常规类型的写入 3.2 对象及数组类型的添加 3.3 Json串写入文件 总结 一.示例Json文件内容 下方为本文所使用的Json文件的内容,其中包含字符串.数值.布尔.null.对象.数组等(写入方式在本文第三节) { "array": [ "str", 88, null ], "bool": true,

  • Qt读写ini文件的方法详解(含源码+注释)

    目录 一.示例Ini文件内容 二.Ini文件的写入 三.Ini文件的读取 3.1 第一种读取方式 3.2 第二种读取方式 3.3 读取结果示例 补充:获取所有节点和key以及节点的遍历 相关文章 总结 一.示例Ini文件内容 下方为本文所使用的ini文件的内容 [group1] key1=val1 key2=val2 sameKay=sameVal [group2] jian1=zhi1 jian2=zhi2 sameKay=sameZhi 二.Ini文件的写入 ini文件不需要像xml和jso

  • Qt控件点击消息获取的方法详解

    目录 1.QPushButton响应鼠标点击消息 1.1自身响应消息clicked 1.2事件过滤器响应消息 1.3mousePressEvent事件获取 2.QLabel响应鼠标点击消息 2.1事件过滤器响应消息 2.2mousePressEvent事件获取 今日为大家分享一个小功能实现:如何获取控件点击响应. 在这里,我以两个最简单并且具有代表性的控件来进行功能讲解. 举例控件:QLabel.QPushButton 对于这两个控件大家应该都不会陌生了,做界面开发经常会用到的. 开发环境:VS

  • QT委托代理机制之Model View Delegate使用方法详解

    目录 本地数据加载(Data) 添加数据模型(Model) 添加代理模型(Proxy) 添加元素的代理(Delegate) 添加视图层(View) 使用效果 之前的一篇文章中介绍过QT的委托代理机制,那时候由于理解的比较浅就简单的给了一个例子.最近又做了一部分相关的工作,发现之前的理解有点问题.这里就详细的介绍一下QT的委托代理机制的用法,希望对大家有帮助. Model-View-Delegate机制可以简单的理解为将本地的一些数据以特定的UI形式呈现出来.常见的数据结构包括列表数据(list)

随机推荐