【C++】做一个飞机空战小游戏(三)——模块化程序设计
[导读]本系列博文内容链接如下:
【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值
【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动
【C++】做一个飞机空战小游戏(三)——模块化程设设计
在前两讲当中,介绍了利用getch()函数实现了对单一字符图标的移动控制。今天要实现对于复杂图标的移动控制,经过分析发现前两讲中的程序当中还有些不够合理的地方。主要有以下几方面:
第一,主函数main()中包含了很多if语句、for循环、case语句这类的程序片段,主函数显得非常凌乱,程序的可移植性可扩展性太差;第二,程序当中编写了一个showplane函数,有了模块化的运用,但是这个函数也是在main函数所在的cpp文件中,程序的模块化程度不够高;第三,飞机图标的显示函数只适用于单个字符,要想换一个稍微复杂点的图标,就需要修改showplane函数内部代码,函数的通用性太差。
要想解决以上三方面存在的问题,就需要采用模块化设计思路,使程序结构性更强,可读性可移植性更好,也有利于多人协作共同开发,提高程序开发效率。
目录
一、什么是模块化程序设计
二、c++实现模块化设计的方法
(一)函数
(二)头文件
(三)功能函数定义文件(cpp文件)
三、本例的设计思路
(一)程序流程图
(二)头文件
(三)主函数
(四)功能函数库
1、初始化函数
2、获取键盘指令函数key()
3、计算飞机图标实时坐标函数
4、显示飞机图标函数showplane()
5、功能函数完整文件control_plane.cpp
四、项目文件
五、运行效果
一、什么是模块化程序设计
模块化程序设计是指在进行程序设计时将一个大程序按照功能划分为若干小程序模块,每个小程序模块完成一个确定的功能,并在这些模块之间建立必要的联系,通过模块的互相协作完成整个功能的程序设计方法。
在设计较复杂的程序时,一般采用自顶向下的方法,将问题划分为几个部分,各个部分再进行细化,直到分解为较好解决问题为止。模块化设计,简单地说就是程序的编写不是一开始就逐条录入计算机语句和指令,而是首先用主程序、子程序、子过程等框架把软件的主要结构和流程描述出来,并定义和调试好各个框架之间的输入、输出链接关系逐步求精的结果是得到一系列以功能块为单位的算法描述。以功能块为单位进行程序设计,实现其求解算法的方法称为模块化。模块化的目的是为了降低程序复杂度,使程序设计、调试和维护等操作简单化。利用函数,不仅可以实现程序的模块化,使得程序设计更加简单和直观,从而提高了程序的易读性和可维护性,而且还可以把程序中经常用到的一些计算或操作编写成通用函数,以供随时调用。
二、c++实现模块化设计的方法
c++实现模块化设计的主要方法有两种,一种是利用类,另外一种就是函数及头文件。类涉及的内容比较多,暂时先不讲,只简单介绍下函数和头文件的使用。
(一)函数
每个函数实现一种特定的功能,是一个小功能模块,函数之间可以通过形参或者全局变量进行信息的交互。在主函数内,调用具体功能函数来实现一定的控制目的,主函数内的语句非常少,具体的代码都在各个功能函数之中。
函数根据有无返回值分为两种,一种是有返回值的,另外一种是无返回值的,有返回值的,声明函数时需要声明函数(也就是返回值)的数据类型,函数调用后,要将运算的结果返回,无返回值的函数类型为void,函数调用后只执行了一些动作,没有运算结果,或无需将运算的结果返回。
函数可以有形式参量,如果有,则需要声明和定义函数时,同时声明形参的数据类型。函数也可以没有形式参量,用void来表示。
(二)头文件
头文件中一般包含两类内容,一类是全局变量,一类是全局函数。注意,头文件中只声明函数,不定义函数的具体内容。
(三)功能函数定义文件(cpp文件)
这类文件中没有主函数,只有各个功能函数的具体定义,一个文件里可以有多个功能函数。
主函数中要想引用头文件中声明的变量和函数,需要在文件中标明#include "头文件名.h"。
三、本例的设计思路
本例中由键盘控制飞机移动,程序主体由5个功能模块组成:初始化、清屏、显示飞机图标、获取键盘指令、计算飞机新的坐标。
(一)程序流程图
程序流程图如图1所示。
(二)头文件
头文件control_plane.h具体内容如下所示。
#ifndef CONTROL_PLANE_H
#define CONTROL_PLANE
#include <iostream>
#include <string>
using namespace std;#define tb 0 //图形显示区域上侧边界
#define lb 0 //图形显示区域左侧边界
#define rb 100 //图形显示区域右侧边界
#define bb 20 //图形显示区域下侧边界//定义飞机造型
const string icon_plane[]={" ■ ","■■■","■■■"};//定义图标坐标结构体
typedef struct{int x;int y;
} location;//定义移动方向命令枚举类型
typedef enum {up_cmd,down_cmd,left_cmd,right_cmd} direction_cmd;extern location plocation; //声明飞机坐标
static direction_cmd dir_cmd; //声明存放按键码值的两个变量//声明刷新飞机位置函数
void show_plane(location plct);//获取键盘指令
direction_cmd key(void);//计算出接收指令后的飞机坐标
location plane_locate(location plct,direction_cmd dircmd);void init(void); #endif
(三)主函数
主函数要引入定义的头文件control_plane.h,声明了一个外部全局变量plocation,类型为头文件中定义的location型,用于存放飞机的坐标。本例中的main函数带有两个参量int argc, char** argv,这个是以新建项目的方法创建的,两个参数自己生成的,具体含义可自行搜素其他相关文章。
主函数的内容与程序流程图一致,一共调用了5个函数,除system("cls")为系统函数外,init(),show_plane(),key(),plane_locate()4个函数都是自定义功能函数。
#include <iostream>
#include "control_plane.h"
#include <string>
using namespace std;location plocation;int main(int argc, char** argv) { init(); //初始化 while(1) //循环等待键盘指令 {system("cls"); //清屏show_plane(plocation); //刷新飞机图标 dir_cmd=key(); //获取按键指令 //计算收到键盘指令后的飞机坐标 plocation=plane_locate(plocation,dir_cmd); }return 0;
}
(四)功能函数库
主函数中调用的4个功能函数都在control_plane.h头文件声明,在control_plane.app文件中定义。
1、初始化函数
本函数为无参无返回值函数,具体代码如下:
//初始化函数
void init(void)
{plocation.x=rb/2; //初始化飞机图标的x坐标为屏幕横轴最大值的一半 plocation.y=bb; //初始化飞机图标的y坐标为屏幕纵轴最大值
}
2、获取键盘指令函数key()
本函数是无参函数,根据键盘的指令,判断出控制方向的意图,返回值为枚举类型。direction_cmd在头文件中进行了声明和定义。key()函数的具体代码如下:
//获取键盘指令函数
direction_cmd key(void)
{int key_value1,key_value2; //声明两个变量,存放键值 key_value1=getch(); //先获取第一个码值 if(key_value1==224) //如果第一个码值为224,则进行第二个码值的判断 {key_value2=getch(); //先获取第二个码值switch(key_value2){case 72: //向上方向键 return up_cmd;case 80: //向下方向键return down_cmd;case 75: //向左方向键return left_cmd;case 77: //向右方向键return right_cmd;}}
}
3、计算飞机图标实时坐标函数
location plane_locate(location plct,direction_cmd dircmd),有三个参量,plct是获得移动指令之前的位置坐标,dircmd是移动方向指令。函数返回值是一个结构体形式的location类型数据。
//计算获得移动指令后飞机的坐标
location plane_locate(location plct,direction_cmd dircmd)
{int x,y;x=plct.x;y=plct.y;switch(dircmd){case up_cmd:y--; //字符上移一行,行值y减1if(y<tb) //限定y值最小值为0{y=tb;}break;case down_cmd:y++; //字符下移一行,行值y加1if(y>bb) //限定y高度 {y=bb;}break;case left_cmd:x--; //字符左移一列,列值x减1if(x<lb){x=lb; //限定x最小值为0; }break;case right_cmd:x++; //字符右移一列,列值x加1if(x>rb){x=rb; //限定x宽度}break;}plct.x=x;plct.y=y;return plct;}
4、显示飞机图标函数showplane()
void show_plane(location plct),有一个参量,是飞机图标在获取移动指令后的坐标值。函数的作用是刷新飞机图标,无返回值。
//飞机图标刷新函数
void show_plane(location plct) //预先定义字符定位显示函数,x是列坐标,y是行坐标,原点(x=0,y=0)位于屏幕左上角
{int x,y;int i,j; int rows=sizeof(icon_plane)/sizeof(icon_plane[0]);x=plct.x;y=plct.y; for(j=0;j<y;j++) //图标上侧输出y个换行符{cout<<endl;}for(i=0;i<rows;i++) //图标每行前输出x个空格 {for(j=0;j<x;j++){cout<<" ";}cout<<icon_plane[i]<<endl;}
}
5、功能函数完整文件control_plane.cpp
#include <iostream>
#include "conio.h"
#include <string>
#include "control_plane.h"
using namespace std;//初始化函数
void init(void)
{plocation.x=rb/2; //初始化飞机图标的x坐标为屏幕横轴最大值的一半 plocation.y=bb; //初始化飞机图标的y坐标为屏幕纵轴最大值
}//飞机图标刷新函数
void show_plane(location plct) //预先定义字符定位显示函数,x是列坐标,y是行坐标,原点(x=0,y=0)位于屏幕左上角
{int x,y;int i,j; int rows=sizeof(icon_plane)/sizeof(icon_plane[0]);x=plct.x;y=plct.y; for(j=0;j<y;j++) //图标上侧输出y个换行符{cout<<endl;}for(i=0;i<rows;i++) //图标每行前输出x个空格 {for(j=0;j<x;j++){cout<<" ";}cout<<icon_plane[i]<<endl;}
}//获取键盘指令函数
direction_cmd key(void)
{int key_value1,key_value2; //声明两个变量,存放键值 key_value1=getch(); //先获取第一个码值 if(key_value1==224) //如果第一个码值为224,则进行第二个码值的判断 {key_value2=getch(); //先获取第二个码值switch(key_value2){case 72: //向上方向键 return up_cmd;case 80: //向下方向键return down_cmd;case 75: //向左方向键return left_cmd;case 77: //向右方向键return right_cmd;}}
}//计算获得移动指令后飞机的坐标
location plane_locate(location plct,direction_cmd dircmd)
{int x,y;x=plct.x;y=plct.y;switch(dircmd){case up_cmd:y--; //字符上移一行,行值y减1if(y<tb) //限定y值最小值为0{y=tb;}break;case down_cmd:y++; //字符下移一行,行值y加1if(y>bb) //限定y高度 {y=bb;}break;case left_cmd:x--; //字符左移一列,列值x减1if(x<lb){x=lb; //限定x最小值为0; }break;case right_cmd:x++; //字符右移一列,列值x加1if(x>rb){x=rb; //限定x宽度}break;}plct.x=x;plct.y=y;return plct;}
四、项目文件
由于本例中用到了自定义函数和头文件,需要新建项目,并把主函数、自定义函数库和头文件都加载进来。项目布局截图如下图所示。
五、运行效果
(未完待续)
相关文章:
【C++】做一个飞机空战小游戏(三)——模块化程序设计
[导读]本系列博文内容链接如下: 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动【C】做一个飞机空战小游戏(三)——模块化程设设计 在前两讲当中,介绍了利用…...
Django使用WebSocket
1、websocket 相关 实现一个系统,20 个用户同时打开网站,呈现出来一个群聊界面 解决方案 轮询:让浏览器每隔2s向后台发送一次请求,缺点:延迟,请求太多网站压力大 长轮询:客户端向服务端发送请…...
看完这篇 教你玩转渗透测试靶机Vulnhub——HarryPotter:Nagini
Vulnhub靶机HarryPotter:Nagini渗透测试详解 Vulnhub靶机介绍:Vulnhub靶机下载:Vulnhub靶机安装:Vulnhub靶机漏洞详解:①:信息收集:②:漏洞发现:③:SSRF漏洞利用…...
IPO要收紧?业内人士未予以完全确认
“IPO全面收紧、吃穿住等行业标的基本劝退(除非行业龙头)、科创板第五套标准暂停受理……”在上周末,一篇关于IPO收紧的“小作文”在投行圈内疯狂转发。 距离全面注册制正式实施已过去了5个半月,IPO节奏是否在发生较大变化&#…...
stable difussion Pytorch实现与测试
引言: Stable Diffusion是目前最火的AI绘画工具之一,它是一个免费开源的项目,可以被任何人免费部署和使用。通过Stable Diffusion,可以很轻松的通过文字描述,生成对应的图片。由于它是一个开源项目,开源社区(如:GitHub)中有很多插件和训练好的模型,我们可以直接使用。…...
Redis简述
Redis是什么Redis数据类型Redis应用场景缓存计数器分布式会话排行榜最新列表分布式锁消息队列 Redis出现的问题穿透击穿雪崩 Redis为什么速度快 Redis是什么 redis是一种高速缓存数据库 Redis数据类型 string hash list set zset Redis应用场景 缓存 Redis作为缓存层&…...
Redis 操作List
【分布式】Redis 分布式之List_redissonclient.getlist_比嗨皮兔的博客-CSDN博客 说明 配置文件参考:https://blog.csdn.net/qq_38428623/article/details/123217001?utm_sourceapp&app_version5.1.1&codeapp_1562916241&uLinkIdusr1mkqgl919blen ——…...
多个List 合并变成一个List+一个List 根据某个字段相等的另一个字段相加,并排序变成新的List
List<CurveTimeAndValueDomain> curves new ArrayList<>();for (int i 0; i < columnNames.size(); i){if (columnNames.get(i).equals(PlantConstant.TENDOWNFX) || columnNames.get(i).equals(PlantConstant.TENDOWNQP)) {//10千伏以下 数据 进行缓慢处理cu…...
华为流程体系:流程架构「OES方法」
目录 内容简介 OES方法 端到端的流程 专栏列表 CSDN学院 作者简介 内容简介 今天继续来谈谈华为流程体系中的流程架构。 在前期的内容已经介绍过 POS 流程架构的方法。 这里就先回顾一下 POS 方法的相关内容: 关于 POS,大家可以参看上面的这张图…...
c# 创建一个未定义类的临时对象列表
使用场景:要使用的数据太多,列表/字典无法满足需求,需要传入对象,但是又不想创建模型 new[] 是一种用于创建匿名类型数组的写法。它是 C# 中的一种语法糖,用于简化数组的初始化过程。 在下面代码示例中,ne…...
el-button增加下载功能
vue3和element-plus <el-uploadv-model:file-list"fileList"action"/api/upload"multiple:limit"1":headers"headers" ><el-button type"primary">选择文件</el-button><template #file"{ file …...
prometheus和cAdvisor组合
文章目录 docker内部署PromethuesPrometheuscAdvisorPrometheus和cAdvisor关系配置 docker内部署Promethues Prometheus Prometheus是一个开源的系统监控和报警工具,由SoundCloud开发并在2012年捐赠给了Cloud Native Computing Foundation (CNCF)。它被广泛用于监…...
计算机网络(2) --- 网络套接字UDP
计算机网络(1) --- 网络介绍_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/131967378?spm1001.2014.3001.5501 目录 1.端口号 2.TCP与UDP协议 1.TCP协议介绍 1.TCP协议 2.UDP协议 3.理解 2.网络字节序 发送逻辑…...
Idea 结合docker-compose 发布项目
Idea 结合docker-compose 发布项目 这里写目录标题 Idea 结合docker-compose 发布项目Docker 开启远程访问功能 添加相应端口配置IDEA 链接Docker配置项目 docker-compose.yml本地还需要安装 dockerwin11 安装本地Docker 可能存在问题 Linux内核不是最新 Docker 开启远程访问功…...
django
django学习 初识Django1.安装django2.创建项目2.1 在终端2.2 Pycharm 3. 创建app4.快速上手4.1 再写一个页面4.2 templates模板4.3 静态文件4.3.1 static目录4.3.2 引用静态文件 5.模板语法案例:伪联通新闻中心6.请求和响应案例:用户登录7.数据库操作7.1…...
c++游戏框架
游戏类 class Sprite { public:Sprite(int x, int y, int w, int h, const char* imagePath);~Sprite();void render(SDL_Renderer* renderer);void move(int x, int y); private:SDL_Texture* texture_;SDL_Rect rect_; }; 物理引擎类 class PhysicsEngine { public:Physi…...
v-model绑定checkbox无法动态更新视图
在vue2中使用v-model绑定checkbox <input type"checkbox" v-model"isChecked" :valueisChecked change"handleCheckboxChange" />监听change事件,并在change事件中做一些特殊处理,比如用户在登录时有没有阅读过隐私…...
原生html—摆脱ps、excel 在线绘制财务表格加水印(html绘制表格js加水印)
文章目录 ⭐前言⭐html标签💖table表格的属性💖实现财务报表 ⭐结束 ⭐前言 大家好,我是yma16,本文分享原生html——绘制表格报表加水印。 背景:解决没有ps的情况下使用前端html制作表格报表。 html介绍 HTML…...
微信小程序配置上传多个u-upload上传
微信小程序配置上传多个u-upload上传 使用的是uView框架 微信小程序配置上传多个u-upload上传图片 场景需求:根据PC端配置项追加图片配置 小程序根据配置的图片数量,图片名称,进行上传图片 难度在于 我们不知道用户会追加多少个图片配置字段 …...
python使用win32com库实现对Excel的操作
使用win32com库实现对Excel的操作 1. 引言 在日常工作中,我们经常需要对Excel文件进行操作,例如读取和写入数据、格式化和样式、插入和删除等。而使用Python的win32com库,我们可以通过代码来实现对Excel的自动化操作,提高工作效…...
从选型到焊接:一份给嵌入式新手的晶振避坑指南(含32.768KHz实例)
从选型到焊接:嵌入式开发者的晶振实战避坑手册 第一次点亮自己设计的电路板时,那颗小小的晶振就像电子世界的心跳起搏器。记得三年前我为一个智能家居项目调试STM32时,连续三天卡在"晶振不起振"的问题上——电路图反复检查无误&…...
开源新形态:从代码到Prompt的转变
【导语:3月末,开源作者yetone发布新项目voice-input-src,以独特方式“开源”,即用自然语言Prompt生成代码,此做法引发讨论,或预示开源模式新转变。】AI驱动的语音输入法开源项目开源作者yetone在GitHub上发…...
雯雯的后宫-造相Z-Image-瑜伽女孩部署教程:腾讯云TI-ONE平台模型服务一键部署
雯雯的后宫-造相Z-Image-瑜伽女孩部署教程:腾讯云TI-ONE平台模型服务一键部署 本文介绍如何在腾讯云TI-ONE平台上一键部署"雯雯的后宫-造相Z-Image-瑜伽女孩"文生图模型服务,使用Xinference框架和Gradio界面,快速生成高质量的瑜伽主…...
2026最权威的六大降重复率工具解析与推荐
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 飞速发展的人工智能技术,正深切地重塑着学术写作的范式,当下…...
从零构建STM32 OTA升级系统:BootLoader设计、IAP实现与APP无缝跳转实战
1. 为什么需要OTA升级系统 想象一下你开发的智能硬件产品已经卖出去几千台,突然发现固件有个致命bug需要修复,或者要增加一个用户期待已久的新功能。传统做法是让用户把设备寄回工厂,或者带着设备到维修点刷机——这简直是开发者的噩梦&#…...
STM32F4读写SD卡:填一填ST官方HAL库的坑
使用STM32读写SD卡在低功耗存储中的应用是比较常见的,但是网上大多数资料都是基于标准库或者基于寄存器的开发。随着嵌入式设备越来越复杂,使用HAL库能够大大降低开发者的学习成本,从而提高开发效率。近年来,ST官方主推以STM32Cub…...
Linux进程调度机制与性能优化实践
1. Linux进程调度概述在Linux操作系统中,进程调度是内核最核心的功能之一。作为一个多任务操作系统,Linux需要合理地分配有限的CPU资源给众多进程,使它们能够高效、公平地运行。理解Linux的调度机制,对于系统性能调优、应用开发以…...
NoSleep防休眠工具:系统唤醒与持续运行的高效解决方案
NoSleep防休眠工具:系统唤醒与持续运行的高效解决方案 【免费下载链接】NoSleep Lightweight Windows utility to prevent screen locking 项目地址: https://gitcode.com/gh_mirrors/nos/NoSleep 在数字化工作环境中,电脑意外休眠往往导致工作中…...
3分钟搞定加密音乐:Unlock-Music浏览器解密终极指南
3分钟搞定加密音乐:Unlock-Music浏览器解密终极指南 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库: 1. https://github.com/unlock-music/unlock-music ;2. https://git.unlock-music.dev/um/web 项目地址: https:/…...
League-Toolkit:告别繁琐操作,让英雄联盟玩家效率提升300%的智能助手
League-Toolkit:告别繁琐操作,让英雄联盟玩家效率提升300%的智能助手 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 副…...
