飞机大战纯c课程设计报告(里面的本来有图的,但是我就懒得导入)

源码连接:https://blog.csdn.net/weixin_44688297/article/details/94836698

目录
一、需求分析 2
二、概要设计 3
三、详细设计 5
四、调试分析 16
五、总结分析 17
六、参考文献 17

一、需求分析
程序具备的基本的功能如下:

  1. 对玩家进行说明如何操作飞机。
  2. 能让玩家自由选择游戏的难度,共有A、B、C三个难度,难度依次增加。
  3. 随着难度的增加敌机飞机的数量也会增加。
  4. 玩家可以使用ADWS对飞机进行控制。
  5. 玩家可以按R键对飞机开启大招模式。
  6. 达到一定的分数后飞机的子弹会增加,且敌军飞机的移动速度会加快。
  7. 可以随时退出游戏,退出游戏后有两个选择。1重新开始游戏2退出游戏
  8. 打死敌军飞机后飞机的颜色会改变。
  9. 敌飞机飞过屏幕,玩家的生命值会减少,生命值为0时,游戏同样也结束。
    10.玩家的飞机遇到敌军飞机后结束游戏。
    11.玩家结束游戏后会自动保存游戏的最高分,并显示最高分数。
    程序目前使用的数据结构有:
    1二维数组。(用于存取地图上的信息)
    2 文件。(用于存取游戏的最高记录)
    程序运行时的要求:
  10. 所有的输入都是有键盘操作的。
  11. 输入时大小的字母输入都是可以的。
  12. 程序运行性能:良好。

二、概要设计
1.
// 全局变量
int max=0;//最高分数
int EnemyNum;// 敌机个数
int life; //生命值
int level;//代表难度水平
int position_x,position_y; // 飞机位置
int enemy_x[10],enemy_y[10]; // 敌机位置
int canvas[High][Width] = {0}; // 二维数组存储游戏画布中对应的元素
// 0为空格,1为飞机*,2为子弹|,3为敌机@
int score=0; // 得分
int BulletWidth; // 子弹宽度
int EnemyMoveSpeed; // 敌机移动速度
int restart=0;//判断是否重新开始游戏
int isPF=1;//退出游戏后显示的内容打印与否
int BigFire;//大招次数
2.
int setcolor(int n) //飞机颜色变化------------产生一个随机数并传给viod color(),然后
改变颜色。
void read_file(int k) //读取最高记录----将文档里面的贮存的最高分数读取出来
void write_file( int level) //保存最高记录----将文档最高分数修改
void HideCursor() //隐藏光标
void menu() //菜单—介绍游戏的玩法以及一些说明
void gotoxy(int x,int y) //光标移动到(x,y)位置----类似清屏函数
void planemodle() //消除飞机—飞机进行移动后在地图数据进行更变
void PlaneModle() //飞机模型—飞机的形状大小
void startup() // 数据初始化—飞机初始位置数据,以及地图的大小,敌军飞机产生的初始位置
void low() //选择难度—根据玩家选择的难度进行读取文档,初始化飞机命值,,敌军飞机的数量,敌军飞机最快速度。
void show() // 显示画面—打印实时游戏画面
void color() //飞机变色—根据int setcolor()产生的随机数改变颜色
void updateWithoutInput() // 与用户输入无关的更新—根据飞机的实时情况修改打印所显示的信息。打死飞机后产生新的飞机,子弹上移,判断飞机是否死亡,分数的增加。
int updateWithInput() // 与用户输入有关的更新----根据用户玩家输入的数据对飞机做出相应的改变,如,发射散弹,重新开始游戏,飞机位置的移动,以及结束游戏等操作。
3.
int main()
{
system(“title 飞机大战”);
system(“color 0F”);
low(); //难度的选择
startup(); // 基本的数据初始化
while (1) // 游戏循环执行
{
show(); // 显示画面
updateWithoutInput(); // 与用户输入无关的更新
if(updateWithInput()==0) // 与用户输入有关的更新
break;
}
return 0;
}

三、详细设计
不变的参数设定:
#define High 18 // 游戏画面尺寸的高度和宽度
#define Width 30
#define DL1 5 //难度水平 1
#define DL2 3 //难度水平 2
#define DL3 1 //难度水平 3
#define EnemyMoveSpeedmax 10//敌军飞机的最大移速

// 全局变量
int max=0;//最高分数
int EnemyNum;// 敌机个数
int life; //生命值
int level;//代表难度水平
int position_x,position_y; // 飞机位置
int enemy_x[10],enemy_y[10]; // 敌机位置
int canvas[High][Width] = {0}; // 二维数组存储游戏画布中对应的元素
// 0为空格,1为飞机*,2为子弹|,3为敌机@
int score=0; // 得分
int BulletWidth; // 子弹宽度
int EnemyMoveSpeed; // 敌机移动速度
int restart=0;//判断是否重新开始游戏
int isPF=1;//退出游戏后显示的内容打印与否
int BigFire;//大招次数

void setcolor(int n) //飞机颜色变化
{
switch(n)
{
case 0: system(“color 0F”);break;
case 2: system(“color 05”);break;
case 3: system(“color 06”);break;
case 5: system(“color 02”);break;
case 6: system(“color 07”);break;
default: system(“color 0F” );break;
}
}
void color() //飞机变色
{
srand(time(NULL));
int c;
c=rand()%7;
setcolor©;
}
将void color函数中产生的c的随机数传给void setcolor中然后令颜色做出相应的改变。

void read_file(int k) //读取最高记录
{
switch (k)
{
case 1:
{
FILE *fp;
fp=fopen(“飞机大战的难度A最高记录.txt”,“r+”);
if(fpNULL)
{
fp=fopen(“飞机大战的难度A最高记录.txt”,“w+”);//如果文件为空,新建文件
fwrite(&max,sizeof(int),1,fp); //写入max最大记录
}
fseek(fp,0,0);
fread(&max,sizeof(int),1,fp);
fclose(fp); //关闭文件
break;
}
case 2:
{
FILE *fp;
fp=fopen(“飞机大战的难度B最高记录.txt”,“r+”);
if(fp
NULL)
{
fp=fopen(“飞机大战的难度B最高记录.txt”,“w+”);//如果文件为空,新建文件
fwrite(&max,sizeof(int),1,fp); //写入max最大记录
}
fseek(fp,0,0);
fread(&max,sizeof(int),1,fp);
fclose(fp); //关闭文件
break;
}
case 3 :
{
FILE *fp;
fp=fopen(“飞机大战的难度C最高记录.txt”,“r+”);
if(fp==NULL)
{
fp=fopen(“飞机大战的难度C最高记录.txt”,“w+”);//如果文件为空,新建文件
fwrite(&max,sizeof(int),1,fp); //写入max最大记录
}
fseek(fp,0,0);
fread(&max,sizeof(int),1,fp);
fclose(fp); //关闭文件
break;
}
}
}
void write_file( int level) //保存最高记录
{
switch (level)
{
case 5:
{
FILE *fp;
fp=fopen(“飞机大战的难度A最高记录.txt”,“w”);
fwrite(&max,sizeof(int),1,fp);//将最高记录写入文件中
fclose(fp); //关闭文件
break;
}
case 3:
{
FILE *fp;
fp=fopen(“飞机大战的难度B最高记录.txt”,“w”);
fwrite(&max,sizeof(int),1,fp); //将最高记录写入文件中
fclose(fp); /关闭文件
break;
}
case 1:
{
FILE *fp;
fp=fopen(“飞机大战的难度C最高记录.txt”,“w”);
fwrite(&max,sizeof(int),1,fp); //将最高记录写入文件中
fclose(fp); //关闭文件
break;
}
}
}

void HideCursor() //隐藏光标
{
CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

void menu() //菜单
{
printf(" ┏ 欢迎来到飞机大战小游戏 ┓\n");
printf(" ┣ 玩法介绍: ┫\n");
printf(" ┣ 按WSAD是上下左右控制飞机 ┫\n");
printf(" ┗B是退出游戏**┛\n");
printf("-----------------------------------------\n");
}

void gotoxy(int x,int y) //光标移动到(x,y)位置
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle,pos);
}
void planemodle() //消除飞机
{
canvas[position_x-1][position_y] = 0;
canvas[position_x][position_y-1] = 0;
canvas[position_x][position_y+1] = 0;
canvas[position_x][position_y-2] = 0;
canvas[position_x][position_y+2] = 0;
canvas[position_x+1][position_y+1] = 0;
canvas[position_x+1][position_y-1] = 0;
}

void PlaneModle() //飞机模型
{
canvas[position_x-1][position_y] = 1;
canvas[position_x][position_y-1] = 1;
canvas[position_x][position_y+1] = 1;
canvas[position_x][position_y-2] = 1;
canvas[position_x][position_y+2] = 1;
canvas[position_x+1][position_y+1] = 1;
canvas[position_x+1][position_y-1] = 1;
}
void startup() // 数据初始化
{
srand(time(NULL));
position_x = High-6;
position_y = Width/2;
PlaneModle(); //飞机模型
int k;
for (k=0;k<EnemyNum;k++)
{
enemy_x[k] = rand()%2; //随机产生飞机
enemy_y[k] = rand()%Width;
canvas[enemy_x[k]][enemy_y[k]] = 3;
}
score = 0;
BulletWidth = 0;
}

void low() //选择难度
{
printf(" ╔ 您可以选择你想要玩的难度 ╗\n");
printf(" ╠ 难度等级为A~C级,等级越高越难。 ╣\n");
printf(" ╚如果你选择除A~C之外的难度,游戏默认为A难度╝\n");
HideCursor();//隐藏光标
char input; //输入
input = getch();//难度
if(input ==‘b’||input ‘B’)
{
read_file(2); //读取最高记录
life = 10; //生命值
level = DL2;
EnemyNum = 6;
EnemyMoveSpeed = 20;
BigFire = 3;
}
else if(input
’c’||input ==‘C’)
{
read_file(3); //读取最高记录
level = DL3;
life = 15; //生命值
EnemyNum = 8;
EnemyMoveSpeed = 30;
BigFire = 3;
}else
{
read_file(1); //读取最高记录
level = DL1;
life = 5; //生命值
EnemyNum = 4;//飞机数量
EnemyMoveSpeed = 40;//飞机移动的速度
BigFire = 3;
}
system(“cls”); // 清屏
}
void show() // 显示画面
{
gotoxy(0,0); // 光标移动到原点位置,以下重画清屏
HideCursor();//隐藏光标
menu(); //菜单
int i,j,plane=1;
for (i=0;i<High;i++)
{
for (j=0;j<Width;j++)
{
if (canvas[i][j]==0)
printf(" "); // 输出空格
else if (canvas[i][j]1)
printf(""); // 输出飞机
else if (canvas[i][j]2)
printf("|"); // 输出子弹|
else if (canvas[i][j]3)
{
if(plane)
{
printf("+"); // 输出飞机+
plane = 0;
}
else
{
printf("@"); // 输出飞机+
plane = 1;
}
}
}
printf("\n");
}
printf(“得分:%d 大招:%d 生命值:%d \n”,score,BigFire,life);
}
void updateWithoutInput() // 与用户输入无关的更新
{
int i,j,k;
srand(time(NULL));
for (i=0;i<High;i++)
{
for (j=0;j<Width;j++)
{
if (canvas[i][j]2)
{
for (k=0;k<EnemyNum;k++)
{
if ((i
enemy_x[k-1]) && (j
enemy_y[k])) // 子弹击中敌机
{
color(); //飞机变色
score++; // 分数加1
if (score%5
0 && EnemyMoveSpeed>EnemyMoveSpeedmax) // 达到一定积分后,敌机变快
EnemyMoveSpeed–;
if (score%5
0) // 达到一定积分后,子弹变厉害
if(BulletWidth<=level)//子弹个数的上限
BulletWidth++;
canvas[enemy_x[k]][enemy_y[k]] = 0;//飞机消失
canvas[i][j] = 0; // 子弹消失
enemy_x[k] = rand()%2; // 产生新的飞机
enemy_y[k] = rand()%Width;
canvas[enemy_x[k]][enemy_y[k]] = 3;
}
}
//子弹上移
canvas[i][j] = 0;
if (i>0)
canvas[i-1][j] = 2;
}
}
}

static int speed = 0;  
if (speed<EnemyMoveSpeed)
	speed++;
for (k=0;k<EnemyNum;k++)
{
	if ((position_x==enemy_x[k]) && (position_y==enemy_y[k])||life==0)  // 敌机撞到我机
	{
		if(score>max)
		{
			max=score;
			write_file(level);  //保存最高记录
		}
		printf("游戏结束!请重新开始游戏\n"); 
		printf("当前难度最高纪录为%d:\n",max);
		Sleep(300);
		getch(); 
		exit(0);
	}
	if (enemy_x[k]>High)   // 敌机跑出显示屏幕
	{		
		canvas[enemy_x[k]][enemy_y[k]] = 0;
		enemy_x[k] = rand()%2;           // 产生新的飞机
		enemy_y[k] = rand()%Width;
		canvas[enemy_x[k]][enemy_y[k]] = 3;
		score--;  // 减分
		life--; //生命减少 
	}
	
	if (speed == EnemyMoveSpeed)
	{
		// 敌机下落
		for (k=0;k<EnemyNum;k++)
		{
			canvas[enemy_x[k]][enemy_y[k]] = 0;
			enemy_x[k]++;			
			speed = 0;
			canvas[enemy_x[k]][enemy_y[k]] = 3;
		}
	}
}
if(restart) //重新开始游戏就把分数归零 
{
	system("cls");
	score = 0;
	restart = 0;
	EnemyMoveSpeed = 25;
	for (k=0;k<EnemyNum;k++)
	{
		canvas[enemy_x[k]][enemy_y[k]] = 0;
		enemy_x[k] = rand()%2;           // 产生新的飞机
		enemy_y[k] = rand()%Width;
		canvas[enemy_x[k]][enemy_y[k]] = 3;
	}
}

}
int updateWithInput() // 与用户输入有关的更新
{
char input;
if(kbhit()) // 判断是否有输入
{
input = getch(); // 根据用户的不同输入来移动,不必输入回车
if(input == ‘b’)
{
if(isPF == 1)
{
system(“cls”);
printf(“已退出游戏,想重新玩吗?\n”);
printf(“那就按Q,如果不想玩了就随意按一个键\n”);
HideCursor();//隐藏光标
isPF = 0;
}
input = getch();
if(input == ‘q’ )
{
low();//重新选择难度
restart = 1;//重新开始游戏
isPF = 1;
}
else
return 0;
}
else if (input == ‘a’||input == ‘A’ && position_y>2)
{
planemodle();
position_y–; // 位置左移
PlaneModle();
}
else if (input == ‘d’||input == ‘D’ && position_y<Width-3)
{
planemodle();
position_y++; // 位置右移
PlaneModle();
}
else if (input == ‘w’||input == ‘W’ && position_x>2)
{
planemodle();
position_x–; // 位置上移
PlaneModle();
}
else if (input == ‘s’||input == ‘S’ && position_x<High-2)
{
planemodle();
position_x++; // 位置下移
PlaneModle();
}else if(input == ‘r’||input == ‘R’)
{
if(BigFire>0)
{
int k;
for (k = 0;k <= Width-1;k++) // 发射闪弹
canvas[position_x-2][k] = 2; // 发射子弹的初始位置在飞机的正上方
BigFire–;
}
}
else if (input == ’ ') // 发射子弹
{
int left = position_y-BulletWidth;
int right = position_y+BulletWidth;
int k;
for (k = left;k <= right;k++) // 发射闪弹
canvas[position_x-2][k] = 2; // 发射子弹的初始位置在飞机的正上方
}
}
return 1;
}
int main()
{
system(“title 飞机大战”);
system(“color 0F”);
low(); //难度的选择
startup(); // 基本的数据初始化
while (1) // 游戏循环执行
{
show(); // 显示画面
updateWithoutInput(); // 与用户输入无关的更新
if(updateWithInput()==0) // 与用户输入有关的更新
break;
}
return 0;
}

2.流程图:

四、调试分析
游戏运行主要画面显示图:

1.飞机被打死后并没有死亡,仍然还可以出现在游戏画面中。我在withoutinput函数中里面在飞机打死敌军飞机时,同时敌军飞机重新产生,从而避免了飞机还会重新出现的情况。
2.飞机显示不正确,飞机移动时会画面仍然会出现上一次的飞机的标记。我另外重新设置两个函数对飞机移动进行标记,飞机移动后,飞机原来的标记会清空,飞机后来的位置我会重新标记,这样就解决了飞机回重复出现在地图上的问题了。
3.飞机子弹问题,飞机发射子弹后,子弹并不会移动。我在withouinput函数中,对地图进行绘制中先让子弹消失,然后将子弹下一个会进行标记。
4.飞机的存取最高记录无法正常进行。我看了书,对自己的代码进行了一个一个的分析,最后fseek函数调用出错了,进行了修改,解决了问题。

五、总结分析
1.对飞机的控制缺少仔细认真的分析,导致飞机运动时出现各种问题。
2.对文件的使用方法并不是很熟悉,所以才导致使用文件一直出现问题。
3.函数调用时不能清晰认识函数的作用,所以才导致使用文件时出现的各种的问题。
4.敌军飞机模型过于简单,我军的飞机也过于简单。
5.大招的模式过于单一,可以灵活多变些。
6.敌军飞机还不能发射子弹,导致游戏的难度比较容易。

六、参考文献
书籍参考:
吴启武.C语言课程设计案例精编(第三版).清华大学出版社
宋海燕.C语言程序设计项目教程.北京理工大学出版社
许真珍.C语言课程设计指导教程.清华大学出版社
童晶.C语言课程设计与游戏开发实践教程.清华大学出版社

网址参考:
https://zhuanlan.zhihu.com/p/24798125
https://wenku.baidu.com/view/1b9a2e24abea998fcc22bcd126fff705cc175c1d.html

附件:
1.fseek的使用方法:
fseek函数用于重定位流(数据流/文件)上的文件内部位置指针。
函数原型int fseek(FILE *stream, long offset, int fromwhere);
参数:
stream为文件流的指针
offset 偏移量
fromwhere 起始位置
具体功能:如果执行成功,stream将指向以fromwhere(起始位置:文件头0(SEEK_SET),当前位置1(SEEK_CUR),文件尾2(SEEK_END))为基准,偏移offset(指针偏移量)个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。
返回值:
成功,返回0,失败返回-1,并设置errno的值,可以用perror()函数输出错误。
2. system(“title C语言关机程序”);//设置cmd窗口标题

  • 8
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值