基于 qt creator 4.8.1 的贪吃蛇游戏

基于 qt creator 4.8.1 的贪吃蛇游戏

这里其实只是把 readme 复制过来了,甚至 readme 还没写完。老懒狗了,希望后面的看官踹我一脚,让我补全……

readme

项目尝试基于 qt creator 4.8.1 写一个贪吃蛇游戏

项目地址:https://gitee.com/polaris347/little_project/tree/master/greedy_snake


前言

我先安利一波 google c++ 编程规范,本项目也将尽力遵守该规范。其中以下几条非常值得关注

纯接口

当一个类满足以下要求时, 称之为纯接口:

  • 只有纯虚函数 (“=0”) 和静态函数 (除了下文提到的析构函数).
  • 可以存在静态数据成员,但不能有非静态数据成员.
  • 没有定义任何构造函数,或者构造函数为不含参数的 protected 类型函数。
  • 如果它是一个子类,它只能继承自纯接口
  • 为确保接口类的所有实现可被正确销毁, 必须为之声明虚析构函数

流程设计

我们采取多层分层架构来设计这个软件。具体地,分为以下几层:

  • 界面层:负责组织用户交互界面、调用通信层界面
  • 通信层:从自身界面收集用户操作信息,并调用逻辑层;从逻辑层收集信息,并更新自身界面、存储逻辑层的初始化参数
  • 逻辑层:负责软件的核心逻辑、向通信层提供接口、执行通信层的指令
逻辑层
通信层
界面层
GameLoop 类
GameMap 类
Food 类
Snake 类
GameDisplayer 类
GameSetting 类
Instruction 类
GameArg 类
EntryInterface 类

其中箭头表示信息流动方向,或者类继承

逻辑层思路

首先,我们应该将贪吃蛇的各个核心游戏要素定义为类,这包括:

  • 地图
  • 食物

其次,我们也希望游戏的结算机制高度封装,并为通信类提供简洁的接口,所以我们应该通过嵌套或者继承的方式将上述元素组合成一个游戏类。

GameLoop
GameMap
Food
Snake

最后,我们的游戏类只需要向其传入相关的游戏参数便可运行。

这里我们暂且不论参数存储在哪儿、由谁传入、在哪儿传入

代码详见此处

我们的思路是将上述三个基本游戏元素抽象为接口类,然后使 gameloop 继承这几个接口。接口类的内容请看此处:

通信层思路

这里我们主要解决一个问题:**如何在不同的 cpp 文件中通信?**我们首先会有两个思路:函数传参和 extern 外部链接的全局变量。

先来说说函数传参的缺点:

  • 这么做把风险提高了一倍:调用者传参失误、执行者使用失误,
  • 有额外的风险,如爆栈、拷贝构造等
  • 大量参数容易引发开发者的负面情绪,尤其是协同开发时。

再来说一说 extern 的缺点:

  • 外部链接的全局变量污染全局环境,这是非常不可取的事情!
  • 全局变量的声明位置不显然。你会发现在哪个 cpp 中声明它都“不公平”,且要想找到它并不是一件显然的事情
  • 不可靠。考虑协同开发,每个人写一个 cpp。你并不知道其它 cpp 中是否初始化了它,即使你们约定好了
  • 变量类型不能体现这是一个全局共享的信息,这点后面你会看到

较好的一个方法是,使用接口类,并在头文件中将数据声明成静态数据,在对应的 cpp 中定义并初始化,优点如下:

  • 变量类型即能体现数据作用。这个类的静态成员全部为全局共享信息,你也不需要在变量名后面添加其它后缀
  • 使用方便。你只需要 include,便能使用、修改类中的全部变量。你不会因为名称相似而 extern 错误的变量。
  • 互斥。信息唯一,它不会产生函数传参导致的数据副本
  • 变量位置是显然的,即在对应的 cpp 中

代码详见…/greedy_snake/gamearg.h

界面层思路

界面层我们几乎采用纯界面的制作方案,这样能使制作时有最直观的效果。

代码详见…/greedy_snake/entryinterface.h, …/greedy_snake/entryinterface.cpp

简单来说,我们只是定义了几个信号,然后在槽中调用对应类并阻塞执行罢了,例如:

void EntryInterface::on_start_button_clicked() {
    this->setVisible(false);
    GameDisplayer game;
    game.exec();  // 阻塞执行
    this->setVisible(true);
}

void EntryInterface::on_setting_button_clicked() {
    this->setVisible(false);
    GameSetting a;
    a.exec();  // 阻塞执行
    this->setVisible(true);
}

void EntryInterface::on_instruction_button_clicked() {
    this->setVisible(false);
    Instruction a;
    a.exec();  // 阻塞执行
    this->setVisible(true);
}

打包

我们在 images 文件夹的同级目录下,建立 pack 文件夹,并将 exe 文件复制到其中。然后打开 qt 终端,cd 进入 pack 目录,并执行以下指令进行打包:

windeployqt greedy_snake.exe

参考资料

  • https://blog.csdn.net/perfectguyipeng/article/details/84611569
  • https://blog.csdn.net/Lee567/article/details/106162978
  • https://www.qter.org/portal.php?mod=view&aid=29&page=1
  • https://blog.csdn.net/weixin_42653531/article/details/97810964
  • https://blog.csdn.net/lhw19931201/article/details/103817425
  • https://blog.csdn.net/ccc369639963/article/details/122699085
  • https://www.qter.org/portal.php?mod=view&aid=37
  • https://blog.csdn.net/qq_22642239/article/details/121228338
  • https://blog.csdn.net/ZZ123ZZWW/article/details/122377242
  • https://blog.csdn.net/kenfan1647/article/details/116266875
  • https://jasonlee.blog.csdn.net/article/details/89359191
  • https://blog.csdn.net/weijifen000/article/details/102537640
  • https://blog.csdn.net/kongshuai19900505/article/details/82625569
  • https://blog.csdn.net/jiezhj/article/details/37597929
  • https://blog.csdn.net/qq_15710245/article/details/83151212
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

岚花落_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值