[导读]本系列博文内容链接如下:
【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++实现模块化设计的主要方法有两种,一种是利用类,另外一种就是函数及头文件。类涉及的内容比较多,暂时先不讲,只简单介绍下函数和头文件的使用。
每个函数实现一种特定的功能,是一个小功能模块,函数之间可以通过形参或者全局变量进行信息的交互。在主函数内,调用具体功能函数来实现一定的控制目的,主函数内的语句非常少,具体的代码都在各个功能函数之中。
函数根据有无返回值分为两种,一种是有返回值的,另外一种是无返回值的,有返回值的,声明函数时需要声明函数(也就是返回值)的数据类型,函数调用后,要将运算的结果返回,无返回值的函数类型为void,函数调用后只执行了一些动作,没有运算结果,或无需将运算的结果返回。
函数可以有形式参量,如果有,则需要声明和定义函数时,同时声明形参的数据类型。函数也可以没有形式参量,用void来表示。
头文件中一般包含两类内容,一类是全局变量,一类是全局函数。注意,头文件中只声明函数,不定义函数的具体内容。
这类文件中没有主函数,只有各个功能函数的具体定义,一个文件里可以有多个功能函数。
主函数中要想引用头文件中声明的变量和函数,需要在文件中标明#include "头文件名.h"。
本例中由键盘控制飞机移动,程序主体由5个功能模块组成:初始化、清屏、显示飞机图标、获取键盘指令、计算飞机新的坐标。
程序流程图如图1所示。
头文件control_plane.h具体内容如下所示。
#ifndef CONTROL_PLANE_H
#define CONTROL_PLANE
#include
#include
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
#include "control_plane.h"
#include
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文件中定义。
本函数为无参无返回值函数,具体代码如下:
//初始化函数
void init(void)
{
plocation.x=rb/2; //初始化飞机图标的x坐标为屏幕横轴最大值的一半
plocation.y=bb; //初始化飞机图标的y坐标为屏幕纵轴最大值
}
本函数是无参函数,根据键盘的指令,判断出控制方向的意图,返回值为枚举类型。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;
}
}
}
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减1
if(ybb) //限定y高度
{
y=bb;
}
break;
case left_cmd:
x--; //字符左移一列,列值x减1
if(xrb)
{
x=rb; //限定x宽度
}
break;
}
plct.x=x;
plct.y=y;
return plct;
}
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
#include
#include "conio.h"
#include
#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;jbb) //限定y高度
{
y=bb;
}
break;
case left_cmd:
x--; //字符左移一列,列值x减1
if(xrb)
{
x=rb; //限定x宽度
}
break;
}
plct.x=x;
plct.y=y;
return plct;
}
由于本例中用到了自定义函数和头文件,需要新建项目,并把主函数、自定义函数库和头文件都加载进来。项目布局截图如下图所示。
(未完待续)