透彻解析Qt入门级项目——贪吃蛇游戏

2023-11-06

1、项目目的:

本项目主要通过编写贪吃蛇游戏来学习,熟悉Qt中封装的类。

2、编译环境

VS2019+Qt5.9

3、功能实现

主要实现下面所列基本功能:

  1. 控制贪吃蛇吃食物
    1. 表示蛇
    2. 控制贪吃蛇上下左右移动
    3. 控制食物的随机分配
    4. 控制蛇的增长  
  2. 暂停游戏
  3. 结束游戏

4、需求分析

4.1、控制贪吃蛇吃食物

4.1.1、表示蛇

贪吃蛇的核心功能就是控制贪吃蛇吃食物,我们很容易可以想到可以用一个个小方块来表示蛇身,那我们应该用什么样的容器来存储这些小方块呢?

蛇的移动我们可以理解为在蛇头处添加一个小方块,在蛇尾处删除掉一个小方块,如下图:

因此会在容器的头部进行插入操作,所以底层数据结构为数组的容器肯定不能选,因为数组的头部插入时间复杂度是o(n),链表就是个非常合适的数据结构,因为它在头部插入的时间复杂度是o(1),所以我们应该选底层数据结构为链表的容器,这里选的是QList,它是Qt中封装的一个类。用该容器存储蛇身后,在构造函数中对其进行初始化,再通过渲染函数将其画在界面里。

//SnakeWidget.h文件
class Snake : public QMainWindow
{
    Q_OBJECT

public:
    Snake(QWidget *parent = nullptr);
    ~Snake();


    private:
    Ui::SnakeClass ui;

    //表示蛇
    QList<QRectF> snake;

    //表示蛇身的小方块的宽高
    int nodeWidth = 20;
    int nodeHeight = 20;


    //渲染(绘图)
    void paintEvent(QPaintEvent* event);

};

4.1.2、控制蛇上下移动

使用QTimer类定义一个定时器,该定时器不断地发出timeout信号,相应的槽函数就会不断地接收该信号来执行动作以控制蛇移动,然后不断地进行重新渲染,以达到蛇不断移动的效果。前面说过蛇的移动实际上是在头部增加一个小方块,在尾部删除一个小方块,因此我们可以封装4个成员函数分别控制蛇在4个方向的头部增加,同时再封装一个成员函数表示尾部的删除。

//SnakeWidget.h文件
class Snake : public QMainWindow
{
    Q_OBJECT

public:
    Snake(QWidget *parent = nullptr);
    ~Snake();


private:
    Ui::SnakeClass ui;

    //表示蛇
    QList<QRectF> snake;

    //表示蛇身的小方块的宽高
    int nodeWidth = 20;
    int nodeHeight = 20;

    //定时器
    QTimer* timer;
    int time = 100;//超时时间间隔,单位毫秒

    //渲染(绘图)
    void paintEvent(QPaintEvent* event);

    //4个成员函数控制蛇4个方向头部的增加
    void addUp();
    void addDown();
    void addLeft();
    void addRight();

    //删除尾部
    void deleteLast();

private slots:
    void timeout();

};

4.1.3、控制食物的随机分配

食物可以用一个小方块来表示,然后封装一个成员函数来随机分配食物这个小方块的位置,先在构造函数中对其进行初始化,最后通过渲染函数将其画在界面中。

//SnakeWidget.h文件
class Snake : public QMainWindow
{
    Q_OBJECT

public:
    Snake(QWidget *parent = nullptr);
    ~Snake();


private:
    Ui::SnakeClass ui;

    //表示蛇
    QList<QRectF> snake;

    //食物
    QRectF food;

    //表示蛇身的小方块的宽高
    int nodeWidth = 20;
    int nodeHeight = 20;


    //渲染(绘图)
    void paintEvent(QPaintEvent* event);

    //4个成员函数控制蛇4个方向的移动
    void addUp();
    void addDown();
    void addLeft();
    void addRight();

    //添加食物
    void addFood();
};

4.1.4、控制蛇的增长

我们只需判断蛇头小方块是否和食物小方块重合,一旦重合,那我们在头部多增加一个小方块,就表示蛇增长了。比如蛇朝右移动,我们在头部增加一个小方块,尾部删除一个小方块,表示蛇的移动,那现在,我们在头部增加两个小方块,在尾部删除一个小方块,就表示蛇增长了。

4.2、暂停游戏

当定时器调用stop()函数时就会停止发送timeout()信号,那么timeout()信号相应的槽函数也就停止执行,timeout()相应的槽函数是控制蛇移动的,timeout相应的槽函数停止执行,那么对应的蛇也就停止了移动,也就呈现出暂停的效果了。

timer->stop();

4.3、结束游戏

可以封装一个成员函数来判断游戏是否结束,这里判断游戏结束的标志就是蛇头碰到蛇身。

bool SnakeWideget::checkContact()
{
	for (int i = 0; i < snake.length(); i++)
	{
		for (int j = i+1;j < snake.length(); j++)
		{
			if (snake[i] == snake[j])
				return true;
		}
	}
	
	return false;
}

2023.2.13更新:新增背景音乐,更换了背景图片,优化了界面

源码链接:Snake · IT大文豪/MyProject - 码云 - 开源中国 (gitee.com)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

透彻解析Qt入门级项目——贪吃蛇游戏 的相关文章

  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • 在模板类中声明模板友元类时出现编译器错误

    我一直在尝试实现我自己的链表类以用于教学目的 我在迭代器声明中指定了 List 类作为友元 但它似乎无法编译 这些是我使用过的 3 个类的接口 Node h define null Node
  • 机器Epsilon精度差异

    我正在尝试计算 C 中双精度数和浮点数的机器 epsilon 值 作为学校作业的一部分 我在 Windows 7 64 位中使用 Cygwin 代码如下 include
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐

  • qt 一个线程接收数据 主线程更新界面 会造成界面退出 怎么解决_打造一个好产品

    原标题 打造一个好产品 让产品自己说话 编辑导语 一个好的产品 关键在于产品经理和团队 产品经理对于产品如何理解以及产品更新迭代时的需求变化 产品如何实现更好的体验等等 本文作者分享了关于产品经理经常犯的七个问题 我们一起来看一下 不管怎么
  • c++双链表【构造函数、运算符重载、析构函数、增删查改及逆置等】

    c 中的双向链表写法 主要实现 增删查改 链表逆置 构造函数 运算符重载 等 建立头文件SList h pragma once typedef int DataType class ListNode friend class List 友元
  • Vue学习-基础篇4

    目录 组件结构讲解 如何在组件中引入其它组件 组件中如何使用外部插件 组件间的传值 Vue cli项目创建 什么是脚手架 创建项目 Vue cli项目结构 Vue cli 入口文件main js分析 组件结构讲解 把每个组件都放到一个独立的
  • 【Shell牛客刷题系列】SHELL28 nginx日志分析6-统计每分钟的请求数

    该系列是基于牛客Shell题库 针对具体题目进行查漏补缺 学习相应的命令 刷题链接 牛客题霸 Shell篇 该系列文章都放到专栏下 专栏链接为 专栏 Shell 欢迎关注专栏 本文知识预告 本文首先学习了sprintf 函数的用法 然后复习
  • python爬虫实战之模拟正方教务系统登录查询成绩

    最近由于某些需要 开始入门Python网络爬虫 想通过一个Python程序来访问正方教务管理系统并且抓取到期末的成绩 由于我并没有深入了解过过其他的编程语言 所以 也比较不出Python和其他语言 如JAVA PHP 的优缺点 只是因为我会
  • JAVA通配符

    上限通配符 我们想要的是一个确切元素类型未知的列表 这一点与数组是不同的 List
  • 一、红外遥控介绍(NEC协议)

    目录 1 1 红外线的介绍 1 2 红外遥控器的工作原理 1 3 NEC协议的介绍 1 引导码的组成 2 地址码 3 数据码 4 反码 5 连发码 1 4 红外接受装置 1 在数码管显示红外解码遥控器的按键值 1 1 红外线的介绍 红外是红
  • Kitti数据集标签中yaw角在不同坐标系的转换

    KITTI数据集中坐标系的定义如下图 相机坐标系 激光雷达坐标系 在标签文件 label 中 最后一个值为物体前进方向与x轴夹角的弧度值 在相机坐标系下 且以顺时针为正 逆时针为负 举个例子 如上图第一个car数据为例 其前进方向与x轴夹角
  • 三、IOC容器原理

    三 IOC容器原理 1 概述 Sun ONE技术体系下的IOC容器有 轻量级的有Spring Guice Pico Container Avalon HiveMind 重量级的有EJB 不轻不重的有JBoss Jdon等等 Spring框架
  • nodejs安装

    CentOS7安装NodeJS 1 官网下载二进制文件 https nodejs org en download 2 下载后上传到目标位置 3 解压包 依次执行 cd soft nodejs xz d node v12 18 2 linux
  • Python3 + xpath + excel 实现对boss直聘网的爬取

    一 项目简介 1 内容 抓取boss直聘网上广州地区的 python 相关工作的招聘信息 并且将招聘信息循环保存在excel表中 2 目标网站 https www zhipin com c101280100 query python pag
  • Linux中用gdb 查看代码堆栈的信息

    core dump 一般是在segmentation fault 段错误 的情况下产生的文件 需要通过ulimit来设置才会得到的 调试的话输入 gdb filename core filename就是产生core文件的可执行文件 core
  • Windows server 远程桌面连接用户不活动自动注销配置

    Windows server 远程桌面连接用户不活动自动注销配置
  • VMware三种网络模式配置详解。

    VMware网络 本质上不会配置VMware网络 是因为对其不够熟悉 VMware提供了三种可靠的网络模式 我相信只要了解了他们的区别 配置起来应该是如鱼得水的 如果还在为你的虚拟机上不了网而发愁 那么请跟随我的脚步 让我们来探究他们到底有
  • Flowable 用户问题

    Flowable用户和系统用户问题 springboot集成flowable modeler 实现免登 权限管理 Flowable引擎使用统一权限管理
  • 《信号与系统》解读 第4章 连续信号的离散化:采样与采样定理、奈奎斯特准则、脉冲编码调制PCM

    前言 如果你对采样定理和奈奎斯特准则一知半解 本文将给茅塞顿开 如果你对为什么采样频率必须大于等于原始信号的带宽的2倍 本文将给你答案 目录 1 信号与系统的模型 2 为什么要对连续信号离散化 3 连续信号离散化 采样 的模型 3 1 采样
  • 使用Hexo搭建博客并部署到Github

    一 博客环境搭建 Hexo 是一个静态博客框架 基于 Node js 将 Markdown 文章通过渲染引擎 生成一个静态网页 再结合 Git 命令 ssh Hexo 是一个快速 简洁且高效的博客框架 Hexo 使用 Markdown 或其
  • 深入理解 Java 垃圾回收机制

    一 垃圾回收机制的意义 java 语言中一个显著的特点就是引入了java回收机制 是c 程序员最头疼的内存管理的问题迎刃而解 它使得java程序员在编写程序的时候不在考虑内存管理 由于有个垃圾回收机制 java中的额对象不在有 作用域 的概
  • 解决Excel打开UTF-8编码的CSV文件乱码的问题

    解决Excel打开UTF 8编码的CSV文件乱码的问题 引用自 https en wikipedia org wiki Comma separated values CSV formats are not limited to a part
  • 透彻解析Qt入门级项目——贪吃蛇游戏

    1 项目目的 本项目主要通过编写贪吃蛇游戏来学习 熟悉Qt中封装的类 2 编译环境 VS2019 Qt5 9 3 功能实现 主要实现下面所列基本功能 控制贪吃蛇吃食物 表示蛇 控制贪吃蛇上下左右移动 控制食物的随机分配 控制蛇的增长 暂停游