C语言飞机大战小游戏(2万字!完整精讲解版+源代码)
C语言飞机大战小游戏(2万字!完整精讲解版+源代码)
- 运行效果
- 项目技术点
- 1、启动欢迎界面
- 2、游戏运行界面
- 3、结束界面
- 4、其他功能
- 细节注意
- 命名规范
- 主要思想
- 代码详解
- 函数定义
- 1、界面函数
- 2、绘制与清除飞机函数
- 3、运行刷新函数
- 4、碰撞检测函数
- 5、结束函数
- 6、随机位置生成函数
- 界面控制常量
- 结构体
- 1、创建己方飞机位置结构体
- 2、创建敌方飞机位置结构体
- 3、创建己方飞机炮弹结构体
- 4、创建敌方飞机炮弹结构体
- 5、创建敌方飞机横坐标随机参数及飞机大小
- 6、创建敌方飞机移动随机参数
- 开辟内存
- 1、开辟指针型己方及敌方内存
- 2、开辟指针型己方及敌方飞机炮弹内存
- 光标操作
- 简单绘制
- 1、启动图案及版权绘制
- 1、绘制墙壁
- 2、绘制清除飞机和炮弹
- 碰撞判断
- 1、我方碰撞
- 2、敌方碰撞
- 主要业务逻辑
- 1、敌方飞机移动
- 2、重绘
- 结束游戏
- 绘制总控
- 总代码
运行效果
项目技术点
1、启动欢迎界面
- 界面绘制
- 大小控制
- 按任意键启动游戏
2、游戏运行界面
- 飞机样式
- 键盘控制
- 炮弹飞行路线
- 飞机炮弹升级
- 飞机升级
- 炮弹离开界面消失
- 炮弹命中响应
- 敌方飞机自动生成
- 界面刷新
3、结束界面
- 结束界面显示
- 按任意键结束
4、其他功能
- 分数显示
- 分数更新
细节注意
当使用vs编译器以上应该添加依据宏定义,因为有些函数已经过时了
#define _CRT_SECURE_NO_WARNINGS
因为要实时接收键盘按键进行响应,getchar()效果不是太好,所以用windows.h里面的函数
#include<Windows.h>
因为要随机生成敌方飞机,所以要引入time.h,来依照当前时间随机生成数字
#include<time.h>
由于代码过长以及命名结构问题,代码中使用了重载技术,在新建工程时要选择新建C++项目,C项目时会报错
命名规范
我方飞机 Fly
敌方飞机 DisFly
绘制我方飞机 DrawFly
绘制敌方飞机 DrawDisFly
重新绘制我方飞机 ReDrawFly
重新绘制敌方飞机 ReDrawDisFly
我方飞机炮弹 FlyBoo
敌方飞机炮弹 DisFlyBoo
我方飞机是否被命中 isFlyBoo
敌方飞机是否被命中 isDisFlyBoo
主要思想
核心主要依靠Sleep函数进行控制游戏的速度,由于CPU运行速度非常快,所以使用Sleep来减慢速度
其实使用Sleep相当于每隔一段时间绘制一张的图片,每个100毫秒绘制一次,也就是界面刷新一次
int SleepTime = 100
void runGame(){while (1){ //进行游戏循环isFlyBoo();isDisFlyBoo();ReDrawFly();ReDrawDisFly();ReDrawFlyBoo();ReDrawDisFlyBoo();DisFlyMove();isUpFly();isUpDisFly();score();Sleep(SleepTime);}
}
代码详解
函数定义
1、界面函数
这部分代码用来控制游戏界面
void Cursor(int x, int y); //光标定位函数
void Draw(); //绘制初始化界面
void copy(); //绘制图标游戏名及版本号
void DrawWall(); //绘制墙壁
void runGame(); //游戏运行
void score(); //得分系统
2、绘制与清除飞机函数
void DrawFly(); //绘制己方飞机
void CleanFly(); //清除己方飞机
void DrawDisFly(); //绘制敌方飞机
void CleanDisFly(); //清除敌方飞机
void DrawFlyBoo(); //绘制己方飞机炮弹
void DrawFlyBoo(int x, int y); //重载绘制带位置参数的己方炮弹
void CleanFlyoo(); //清除己方炮弹
void CleanFlyBoo(int x,int y); //重载清除带位置参数的己方炮弹
void DrawDisFlyBoo(); //绘制敌方飞机炮弹
void DrawDisFlyBoo(int x,int y); //重载绘制带位置参数的敌方炮弹
void CleanDisFlyBoo(); //清除敌方炮弹
void CleanDisFlyBoo(int x,int y); //重载清除带位置参数的敌方炮弹
3、运行刷新函数
void ReDrawFly(); //重新绘制己方飞机
void ReDrawDisFly(); //重新绘制敌方飞机
void ReDrawFlyBoo(); //重新绘制己方炮弹
void ReDrawDisFlyBoo(); //重新绘制敌方炮弹
void DisFlyMove(); //控制敌方炮弹移动
4、碰撞检测函数
void isFlyBoo(); //判断敌方飞机炮弹是否碰撞到己方飞机
void isDisFlyBoo(); //判断己方飞机炮弹是否碰撞到敌方飞机
void isUpFly(); //判断己方飞机是否升级
void isUpDisFly(); //判断敌方飞机是否升级
5、结束函数
void OverDisFly(); //结束敌方飞机生命
void OverFly(); //结束己方飞机生命
6、随机位置生成函数
void ProductDisFlyRander(); //生成敌方飞机横坐标随机位置
void MoveDisFlyRander(); //生成敌方飞机移动随机值
界面控制常量
static const int Wall_x = 130; //设置墙壁宽度值
static const int Wall_y = 40; //设置墙壁高度值//设置刷新间隔时间SleepTime
//循环计数标志i
//当前循环计数标志i_now
//每次击中敌方飞机得分XXadd
//总得分XXscore
//当前击中敌方飞机得分XXscore_noe。
int SleepTime = 100, i = 0,i_now = 0;
int XXadd = 100, XXscore = 0, XXscore_now = 0;
结构体
1、创建己方飞机位置结构体
struct _Fly{int x, y;
};
2、创建敌方飞机位置结构体
struct Dis_Fly{int x, y;
};
3、创建己方飞机炮弹结构体
struct FlyBoo{int x, y;struct FlyBoo *next;
};
4、创建敌方飞机炮弹结构体
struct DisFlyBoo{int x, y;struct DisFlyBoo *next;
};
5、创建敌方飞机横坐标随机参数及飞机大小
struct DisFlyRander{int disflyRander_x;int disflybig;
}disflyRander;
6、创建敌方飞机移动随机参数
struct DisFlyMoveRander{int moveRander;
}disflymoveRander;
开辟内存
1、开辟指针型己方及敌方内存
_Fly* fly = (_Fly*)malloc(sizeof(_Fly));
Dis_Fly* disfly = (Dis_Fly*)malloc(sizeof(Dis_Fly));
2、开辟指针型己方及敌方飞机炮弹内存
FlyBoo* flyboo = (FlyBoo*)malloc(sizeof(FlyBoo));
DisFlyBoo* disflyboo = (DisFlyBoo*)malloc(sizeof(DisFlyBoo));
光标操作
void Cursor(int x, int y){COORD cursor; //实例化结构体HANDLE hOutput; //实例化句柄cursor.X = x; //传入横坐标参数cursor.Y = y; //传入纵坐标参数hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //获取输出框界面句柄SetConsoleCursorPosition(hOutput, cursor); //定位坐标位置
}
简单绘制
1、启动图案及版权绘制
void copy(){Cursor(0,Wall_y / 2 - 6 );printf(" ********************** * *\n");printf(" * * *\n");printf(" * * *\n");printf(" * * *\n");printf(" * * *\n");printf(" * **\n");printf(" * **\n");printf(" * **\n");printf(" * **\n");printf(" * **\n");printf(" * **\n");printf(" *********************** ** 。 。 。\n");Cursor(Wall_x-20, Wall_y );printf("打飞机 V 1.0");Cursor(0, Wall_y); //使光标处在左下角
}
1、绘制墙壁
void DrawWall(){for (int i = 1; i < Wall_x; i+=2){Cursor(i, 0); //定位上方墙壁printf("┰"); //绘制上方墙壁Cursor(i, Wall_y); //定位下方墙壁printf("┸"); //绘制下方墙壁}
}
2、绘制清除飞机和炮弹
void DrawFly(){Cursor(fly->x, fly->y); //定位己方待绘制飞机位置printf("◢■◣"); //绘制己方飞机
}void CleanFly(){Cursor(fly->x, fly->y); //定位己方待清除飞机位置printf(" "); //清除己方飞机
}void DrawDisFly(){Cursor(disfly->x, disfly->y); //定位敌方待绘制飞机位置printf("◥□◤"); //绘制敌方飞机
}void CleanDisFly(){Cursor(disfly->x, disfly->y); //定位敌方待清除飞机位置printf(" "); //清除敌方飞机
}void DrawFlyBoo(){Cursor(flyboo->x, flyboo->y); //定位己方待绘制炮弹位置printf("★"); //绘制己方炮弹
}void DrawFlyBoo(int x, int y){Cursor(x, y); //定位己方待绘制炮弹位置printf("★"); //绘制己方炮弹
}void CleanFlyBoo(){Cursor(flyboo->x, flyboo->y); //定位己方待清除炮弹位置printf(" "); //清除己方炮弹
}
void CleanFlyBoo(int x,int y){Cursor(x, y); //定位己方待清除炮弹位置printf(" "); //清除己方炮弹
}void DrawDisFlyBoo(){Cursor(disflyboo->x, disflyboo->y); //定位敌方待绘制炮弹位置printf("☆"); //绘制敌方炮弹
}void DrawDisFlyBoo(int x, int y){Cursor(x, y); //定位敌方待绘制炮弹位置printf("☆"); //绘制敌方炮弹
}void CleanDisFlyBoo(){Cursor(disflyboo->x, disflyboo->y); //定位敌方待清除炮弹位置printf(" "); //清除敌方炮弹
}void CleanDisFlyBoo(int x,int y){Cursor(x, y); //定位敌方待清除炮弹位置printf(" "); //清除敌方炮弹
}
碰撞判断
1、我方碰撞
void isFlyBoo(){DisFlyBoo* temp_disflyboo = (DisFlyBoo*)malloc(sizeof(DisFlyBoo)); //开辟指针型临时敌方飞机炮弹内存temp_disflyboo = disflyboo; //通过临时变量进行下游遍历查找do{if ((temp_disflyboo->x >= fly->x) && (temp_disflyboo->x <= fly->x + 6) && (temp_disflyboo->y == fly->y - 1)) //当敌方飞机炮弹位于己方飞机平面坐标时OverFly(); //执行结束己方飞机生命函数temp_disflyboo = temp_disflyboo->next; //指向下游节点} while (temp_disflyboo != NULL); //遍历至最后一枚敌方炮弹}
2、敌方碰撞
void isDisFlyBoo(){FlyBoo* temp_flyboo = (FlyBoo*)malloc(sizeof(FlyBoo)); //开辟指针型临时己方飞机炮弹内存temp_flyboo = flyboo; //通过临时变量进行下游遍历查找do{if ((temp_flyboo->x >= disfly->x) && (temp_flyboo->x <= disfly->x + 6) && (temp_flyboo->y == disfly->y + 1)) //当己方飞机炮弹位于敌方飞机平面坐标时OverDisFly(); //执行结束敌方飞机生命函数temp_flyboo = temp_flyboo->next; //指向下游节点} while (temp_flyboo != NULL); //遍历至最后一枚己方炮弹
}
主要业务逻辑
1、敌方飞机移动
void DisFlyMove(){MoveDisFlyRander(); //调用随机函数生成运动随机数if (!(disfly->x > Wall_x - 5 && disflymoveRander.moveRander > 0) && !(disfly->x < 5 && disflymoveRander.moveRander < 0)){//控股敌方飞机运动至墙面边界时无法持续滑动CleanDisFly(); //将原有敌方飞机清除disfly->x += disflymoveRander.moveRander; //向指定随机方向进行运动DrawDisFly(); //重新绘制敌方飞机}
}
2、重绘
void ReDrawFlyBoo(){FlyBoo* temp_flyboo = (FlyBoo*)malloc(sizeof(FlyBoo)); //开辟指针型己方临时飞机炮弹内存temp_flyboo->next = NULL; //将其链接接口赋值为空//清除原有己方飞机炮弹temp_flyboo = flyboo; //通过临时变量进行下游查找遍历do{ //至少进行一次遍历,普适第一枚己方炮弹CleanFlyBoo(temp_flyboo->x,temp_flyboo->y); //清除己方飞机炮弹temp_flyboo = temp_flyboo->next; //指向下游节点} while (temp_flyboo != NULL); //遍历至最后一枚己方炮弹//将每个炮弹进行向上移动temp_flyboo = flyboo; //通过临时变量进行下游查找遍历do{ //至少进行一次遍历,普适第一枚己方炮弹temp_flyboo->y -= 1; //将每一枚己方炮弹纵坐标减一temp_flyboo = temp_flyboo->next; //指向下游节点} while (temp_flyboo != NULL); //遍历至最后一枚己方炮弹//依照当前己方飞机链接新炮弹FlyBoo* next_flyboo = (FlyBoo*)malloc(sizeof(FlyBoo)); //开辟指针型递进己方飞机炮弹内存next_flyboo->x = fly->x + 2; //通过当前己方飞机横坐标位置定位己方炮弹横坐标位置next_flyboo->y = fly->y - 1; //通过当前己方飞机纵坐标位置定位己方炮弹纵坐标位置next_flyboo->next = flyboo; //将炮弹首部控制在前端flyboo = next_flyboo;//将己方炮弹全部重绘temp_flyboo = flyboo; //通过临时变量进行下游查找遍历do{ //至少进行一次遍历,普适第一枚己方炮弹DrawFlyBoo(temp_flyboo->x, temp_flyboo->y); //绘制己方炮弹temp_flyboo = temp_flyboo->next; //指向下游节点} while (temp_flyboo != NULL); //遍历至最后一枚己方炮弹//判断己方炮弹是否超出画布if (i > 5){ //避免己方初始炮弹无二阶next指向temp_flyboo = flyboo; //通过临时变量进行下游查找遍历while (temp_flyboo->next->next != NULL) //查找至炮弹第后三个,避免无法指定释放内存炮弹上游指向为空temp_flyboo = temp_flyboo->next; //指向下游节点if (temp_flyboo->next->y <= 1){ //当己方飞机炮弹末端纵坐标小于墙面时CleanFlyBoo(temp_flyboo->next->x, temp_flyboo->next->y); //清除己方飞机炮弹free(temp_flyboo->next); //释放己方飞机炮弹末端内存空间temp_flyboo->next = NULL; //使被释放空间上游节点指向为空}}i++; //运行循环次数递增
}void ReDrawDisFlyBoo(){DisFlyBoo* temp_disflyboo = (DisFlyBoo*)malloc(sizeof(DisFlyBoo)); //开辟指针型敌方临时飞机炮弹内存temp_disflyboo->next = NULL; //将其链接接口赋值为空//清除原有敌方飞机炮弹temp_disflyboo = disflyboo; //通过临时变量进行下游查找遍历do{ //至少进行一次遍历,普适第一枚敌方炮弹CleanDisFlyBoo(temp_disflyboo->x,temp_disflyboo->y); //清除敌方飞机炮弹temp_disflyboo = temp_disflyboo->next; //指向下游节点} while (temp_disflyboo != NULL); //遍历至最后一枚敌方炮弹//将每个炮弹进行向上移动temp_disflyboo = disflyboo; //通过临时变量进行下游查找遍历do{ //至少进行一次遍历,普适第一枚敌方炮弹temp_disflyboo->y += 1; //将每一枚敌方炮弹纵坐标减一temp_disflyboo = temp_disflyboo->next; //指向下游节点} while (temp_disflyboo != NULL); //遍历至最后一枚敌方炮弹//依照当前敌方飞机链接新炮弹DisFlyBoo* next_disflyboo = (DisFlyBoo*)malloc(sizeof(DisFlyBoo)); //开辟指针型递进敌方飞机炮弹内存next_disflyboo->x = disfly->x + 2; //通过当前敌方飞机横坐标位置定位敌方炮弹横坐标位置next_disflyboo->y = disfly->y + 1; //通过当前敌方飞机纵坐标位置定位敌方炮弹纵坐标位置next_disflyboo->next = disflyboo; //将炮弹首部控制在前端disflyboo = next_disflyboo;//将敌方炮弹全部重绘temp_disflyboo = disflyboo; //通过临时变量进行下游查找遍历do{ //至少进行一次遍历,普适第一枚敌方炮弹DrawDisFlyBoo(temp_disflyboo->x, temp_disflyboo->y); //绘制敌方炮弹temp_disflyboo = temp_disflyboo->next; //指向下游节点} while (temp_disflyboo != NULL); //遍历至最后一枚敌方炮弹//判断敌方炮弹是否超出画布if (i > 5){ //避免敌方初始炮弹无二阶next指向temp_disflyboo = disflyboo; //通过临时变量进行下游查找遍历while (temp_disflyboo->next->next != NULL) //查找至炮弹第后三个,避免无法指定释放内存炮弹上游指向为空temp_disflyboo = temp_disflyboo->next; //指向下游节点if (temp_disflyboo->next->y >= Wall_y - 1){ //当敌方飞机炮弹末端纵坐标小于墙面时CleanDisFlyBoo(temp_disflyboo->next->x, temp_disflyboo->next->y); //清除敌方飞机炮弹free(temp_disflyboo->next); //释放敌方飞机炮弹末端内存空间temp_disflyboo->next = NULL; //使被释放空间上游节点指向为空}}
}
结束游戏
void OverDisFly(){ CleanDisFly(); //清除敌方飞机ProductDisFlyRander(); //生成敌方飞机待生成位置随机函数disfly->x = disflyRander.disflyRander_x + 2; //指定敌方飞机所在横坐标disfly->y = 2; //指定敌方飞机所在纵坐标DrawDisFly(); //绘制敌方飞机XXscore += XXadd; //更新当前得分i_now = i; //更新当前循环计数器XXscore_now = XXscore; //更新当前分数计数器
}
void OverFly(){Sleep(600); //给予失败证据提示system("cls"); //清屏for (int i = 0; i <= 500; i++) //进行失败效果制作printf("Game Over! "); //输出游戏失败system("pause"); //等待用户按任意键退出游戏exit(0); //结束游戏关闭程序
}
绘制总控
void Draw(){system("mode con cols=132 lines=42"); //改变DOS大小copy(); //绘制商标信息system("pause"); //使用户按任意键继续system("cls"); //清屏,防止欠覆盖留白DrawWall(); //绘制墙体//初始化己方飞机fly->x = Wall_x / 2; //依照墙体指定己方飞机横坐标fly->y = Wall_y - 1; //依照墙体指定己方飞机纵坐标DrawFly(); //绘制己方飞机//初始化敌方飞机ProductDisFlyRander(); //生成敌方飞机待生成位置随机函数disfly->x = disflyRander.disflyRander_x + 2; //依照随机数指定敌方飞机横坐标disfly->y = 2; //依照随机数指定敌方飞机纵坐标DrawDisFly(); //绘制敌方飞机//绘制己方飞机炮弹disflyRander.disflybig = 6; //指定敌方飞机初始大小flyboo->x = fly->x + 2; //依照当前己方飞机横坐标指定己方飞机炮弹横坐标flyboo->y = fly->y - 1; //依照当前己方飞机纵坐标指定己方飞机炮弹纵坐标flyboo->next = NULL; //将初始飞机炮弹下游指向位置赋值为空DrawFlyBoo(); //绘制己方飞机炮弹//绘制敌方飞机炮弹disflyboo->x = disfly->x + 2; //依照当前敌方飞机横坐标指定敌方飞机炮弹横坐标disflyboo->y = disfly->y + 1; //依照当前敌方飞机纵坐标指定敌方飞机炮弹纵坐标disflyboo->next = NULL; //将初始飞机炮弹下游指向位置赋值为空DrawDisFlyBoo(); //绘制敌方飞机炮弹
}
总代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<Windows.h>
#include<time.h>//界面函数
void Cursor(int x, int y); //光标定位函数
void Draw(); //绘制初始化界面
void copy(); //绘制图标游戏名及版本号
void DrawWall(); //绘制墙壁
void runGame(); //游戏运行
void score(); //得分系统//绘制与清除飞机函数
void DrawFly(); //绘制己方飞机
void CleanFly(); //清除己方飞机
void DrawDisFly(); //绘制敌方飞机
void CleanDisFly(); //清除敌方飞机
void DrawFlyBoo(); //绘制己方飞机炮弹
void DrawFlyBoo(int x, int y); //重载绘制带位置参数的己方炮弹
void CleanFlyoo(); //清除己方炮弹
void CleanFlyBoo(int x,int y); //重载清除带位置参数的己方炮弹
void DrawDisFlyBoo(); //绘制敌方飞机炮弹
void DrawDisFlyBoo(int x,int y); //重载绘制带位置参数的敌方炮弹
void CleanDisFlyBoo(); //清除敌方炮弹
void CleanDisFlyBoo(int x,int y); //重载清除带位置参数的敌方炮弹//运行刷新函数
void ReDrawFly(); //重新绘制己方飞机
void ReDrawDisFly(); //重新绘制敌方飞机
void ReDrawFlyBoo(); //重新绘制己方炮弹
void ReDrawDisFlyBoo(); //重新绘制敌方炮弹
void DisFlyMove(); //控制敌方炮弹移动//碰撞检测函数
void isFlyBoo(); //判断敌方飞机炮弹是否碰撞到己方飞机
void isDisFlyBoo(); //判断己方飞机炮弹是否碰撞到敌方飞机
void isUpFly(); //判断己方飞机是否升级
void isUpDisFly(); //判断敌方飞机是否升级//结束函数
void OverDisFly(); //结束敌方飞机生命
void OverFly(); //结束己方飞机生命//随机位置生成函数
void ProductDisFlyRander(); //生成敌方飞机横坐标随机位置
void MoveDisFlyRander(); //生成敌方飞机移动随机值//界面控制
static const int Wall_x = 130; //设置墙壁宽度值
static const int Wall_y = 40; //设置墙壁高度值//创建己方飞机位置结构体
struct _Fly{int x, y;
}; //创建敌方飞机位置结构体
struct Dis_Fly{int x, y;
};//创建己方飞机炮弹结构体
struct FlyBoo{int x, y;struct FlyBoo *next;
};//创建敌方飞机炮弹结构体
struct DisFlyBoo{int x, y;struct DisFlyBoo *next;
};//设置刷新间隔时间SleepTime, 循环计数标志i, 当前循环计数标志i_now, 每次击中敌方飞机得分XXadd, 总得分XXscore, 当前击中敌方飞机得分XXscore_noe。
int SleepTime = 100, i = 0,i_now = 0, XXadd = 100, XXscore = 0, XXscore_now = 0;//开辟指针型己方及敌方内存
_Fly* fly = (_Fly*)malloc(sizeof(_Fly));
Dis_Fly* disfly = (Dis_Fly*)malloc(sizeof(Dis_Fly));//开辟指针型己方及敌方飞机炮弹内存
FlyBoo* flyboo = (FlyBoo*)malloc(sizeof(FlyBoo));
DisFlyBoo* disflyboo = (DisFlyBoo*)malloc(sizeof(DisFlyBoo));//创建敌方飞机横坐标随机参数及飞机大小
struct DisFlyRander{int disflyRander_x;int disflybig;
}disflyRander;//创建敌方飞机移动随机参数
struct DisFlyMoveRander{int moveRander;
}disflymoveRander;void ProductDisFlyRander(){srand((unsigned)time(NULL));disflyRander.disflyRander_x = (rand() % (Wall_x - 3 * disflyRander.disflybig) + disflyRander.disflybig) / 2 * 2 + 1;//创建横坐标并使创建的横坐标在不可超出墙壁并处在偶数坐标格中(使用/2*2使得处在偶数格中)
}void MoveDisFlyRander(){srand((unsigned)time(NULL));disflymoveRander.moveRander = rand() % 3 - 1;//使生成-1,0,1的随机数控制敌方飞机向左,静止或向右运动
}void Cursor(int x, int y){COORD cursor; //实例化结构体HANDLE hOutput; //实例化句柄cursor.X = x; //传入横坐标参数cursor.Y = y; //传入纵坐标参数hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //获取输出框界面句柄SetConsoleCursorPosition(hOutput, cursor); //定位坐标位置
}void copy(){Cursor(0,Wall_y / 2 - 6 );printf(" ********************** * *\n");printf(" * * *\n");printf(" * * *\n");printf(" * * *\n");printf(" * * *\n");printf(" * **\n");printf(" * **\n");printf(" * **\n");printf(" * **\n");printf(" * **\n");printf(" * **\n");printf(" *********************** ** 。 。 。\n");Cursor(Wall_x-20, Wall_y );printf("打飞机 V 1.0");Cursor(0, Wall_y); //使光标处在左下角
}void DrawWall(){for (int i = 1; i < Wall_x; i+=2){Cursor(i, 0); //定位上方墙壁printf("┰"); //绘制上方墙壁Cursor(i, Wall_y); //定位下方墙壁printf("┸"); //绘制下方墙壁}
}
void DrawFly(){Cursor(fly->x, fly->y); //定位己方待绘制飞机位置printf("◢■◣"); //绘制己方飞机
}void CleanFly(){Cursor(fly->x, fly->y); //定位己方待清除飞机位置printf(" "); //清除己方飞机
}void DrawDisFly(){Cursor(disfly->x, disfly->y); //定位敌方待绘制飞机位置printf("◥□◤"); //绘制敌方飞机
}void CleanDisFly(){Cursor(disfly->x, disfly->y); //定位敌方待清除飞机位置printf(" "); //清除敌方飞机
}void DrawFlyBoo(){Cursor(flyboo->x, flyboo->y); //定位己方待绘制炮弹位置printf("★"); //绘制己方炮弹
}void DrawFlyBoo(int x, int y){Cursor(x, y); //定位己方待绘制炮弹位置printf("★"); //绘制己方炮弹
}void CleanFlyBoo(){Cursor(flyboo->x, flyboo->y); //定位己方待清除炮弹位置printf(" "); //清除己方炮弹
}
void CleanFlyBoo(int x,int y){Cursor(x, y); //定位己方待清除炮弹位置printf(" "); //清除己方炮弹
}void DrawDisFlyBoo(){Cursor(disflyboo->x, disflyboo->y); //定位敌方待绘制炮弹位置printf("☆"); //绘制敌方炮弹
}void DrawDisFlyBoo(int x, int y){Cursor(x, y); //定位敌方待绘制炮弹位置printf("☆"); //绘制敌方炮弹
}void CleanDisFlyBoo(){Cursor(disflyboo->x, disflyboo->y); //定位敌方待清除炮弹位置printf(" "); //清除敌方炮弹
}void CleanDisFlyBoo(int x,int y){Cursor(x, y); //定位敌方待清除炮弹位置printf(" "); //清除敌方炮弹
}void ReDrawFly(){if (GetAsyncKeyState(VK_LEFT) && fly->x > 4){ //当用户键入左键CleanFly(); //清除原有己方飞机fly->x -= 2; //向左移动单位网格长度DrawFly(); //重新绘制己方飞机}else if (GetAsyncKeyState(VK_RIGHT) && fly->x < Wall_x - 4){ //当用户键入右键CleanFly(); //清除原有己方飞机fly->x += 2; //向右移动单位网格长度DrawFly(); //重新绘制己方飞机}else{DrawFly(); //若用户没有键入按键,进行刷新己方飞机,防止得分刷新覆盖}
}void ReDrawDisFly(){DrawDisFly(); //当敌方飞机死亡时,进行重新绘制}void ReDrawFlyBoo(){FlyBoo* temp_flyboo = (FlyBoo*)malloc(sizeof(FlyBoo)); //开辟指针型己方临时飞机炮弹内存temp_flyboo->next = NULL; //将其链接接口赋值为空//清除原有己方飞机炮弹temp_flyboo = flyboo; //通过临时变量进行下游查找遍历do{ //至少进行一次遍历,普适第一枚己方炮弹CleanFlyBoo(temp_flyboo->x,temp_flyboo->y); //清除己方飞机炮弹temp_flyboo = temp_flyboo->next; //指向下游节点} while (temp_flyboo != NULL); //遍历至最后一枚己方炮弹//将每个炮弹进行向上移动temp_flyboo = flyboo; //通过临时变量进行下游查找遍历do{ //至少进行一次遍历,普适第一枚己方炮弹temp_flyboo->y -= 1; //将每一枚己方炮弹纵坐标减一temp_flyboo = temp_flyboo->next; //指向下游节点} while (temp_flyboo != NULL); //遍历至最后一枚己方炮弹//依照当前己方飞机链接新炮弹FlyBoo* next_flyboo = (FlyBoo*)malloc(sizeof(FlyBoo)); //开辟指针型递进己方飞机炮弹内存next_flyboo->x = fly->x + 2; //通过当前己方飞机横坐标位置定位己方炮弹横坐标位置next_flyboo->y = fly->y - 1; //通过当前己方飞机纵坐标位置定位己方炮弹纵坐标位置next_flyboo->next = flyboo; //将炮弹首部控制在前端flyboo = next_flyboo;//将己方炮弹全部重绘temp_flyboo = flyboo; //通过临时变量进行下游查找遍历do{ //至少进行一次遍历,普适第一枚己方炮弹DrawFlyBoo(temp_flyboo->x, temp_flyboo->y); //绘制己方炮弹temp_flyboo = temp_flyboo->next; //指向下游节点} while (temp_flyboo != NULL); //遍历至最后一枚己方炮弹//判断己方炮弹是否超出画布if (i > 5){ //避免己方初始炮弹无二阶next指向temp_flyboo = flyboo; //通过临时变量进行下游查找遍历while (temp_flyboo->next->next != NULL) //查找至炮弹第后三个,避免无法指定释放内存炮弹上游指向为空temp_flyboo = temp_flyboo->next; //指向下游节点if (temp_flyboo->next->y <= 1){ //当己方飞机炮弹末端纵坐标小于墙面时CleanFlyBoo(temp_flyboo->next->x, temp_flyboo->next->y); //清除己方飞机炮弹free(temp_flyboo->next); //释放己方飞机炮弹末端内存空间temp_flyboo->next = NULL; //使被释放空间上游节点指向为空}}i++; //运行循环次数递增
}void ReDrawDisFlyBoo(){DisFlyBoo* temp_disflyboo = (DisFlyBoo*)malloc(sizeof(DisFlyBoo)); //开辟指针型敌方临时飞机炮弹内存temp_disflyboo->next = NULL; //将其链接接口赋值为空//清除原有敌方飞机炮弹temp_disflyboo = disflyboo; //通过临时变量进行下游查找遍历do{ //至少进行一次遍历,普适第一枚敌方炮弹CleanDisFlyBoo(temp_disflyboo->x,temp_disflyboo->y); //清除敌方飞机炮弹temp_disflyboo = temp_disflyboo->next; //指向下游节点} while (temp_disflyboo != NULL); //遍历至最后一枚敌方炮弹//将每个炮弹进行向上移动temp_disflyboo = disflyboo; //通过临时变量进行下游查找遍历do{ //至少进行一次遍历,普适第一枚敌方炮弹temp_disflyboo->y += 1; //将每一枚敌方炮弹纵坐标减一temp_disflyboo = temp_disflyboo->next; //指向下游节点} while (temp_disflyboo != NULL); //遍历至最后一枚敌方炮弹//依照当前敌方飞机链接新炮弹DisFlyBoo* next_disflyboo = (DisFlyBoo*)malloc(sizeof(DisFlyBoo)); //开辟指针型递进敌方飞机炮弹内存next_disflyboo->x = disfly->x + 2; //通过当前敌方飞机横坐标位置定位敌方炮弹横坐标位置next_disflyboo->y = disfly->y + 1; //通过当前敌方飞机纵坐标位置定位敌方炮弹纵坐标位置next_disflyboo->next = disflyboo; //将炮弹首部控制在前端disflyboo = next_disflyboo;//将敌方炮弹全部重绘temp_disflyboo = disflyboo; //通过临时变量进行下游查找遍历do{ //至少进行一次遍历,普适第一枚敌方炮弹DrawDisFlyBoo(temp_disflyboo->x, temp_disflyboo->y); //绘制敌方炮弹temp_disflyboo = temp_disflyboo->next; //指向下游节点} while (temp_disflyboo != NULL); //遍历至最后一枚敌方炮弹//判断敌方炮弹是否超出画布if (i > 5){ //避免敌方初始炮弹无二阶next指向temp_disflyboo = disflyboo; //通过临时变量进行下游查找遍历while (temp_disflyboo->next->next != NULL) //查找至炮弹第后三个,避免无法指定释放内存炮弹上游指向为空temp_disflyboo = temp_disflyboo->next; //指向下游节点if (temp_disflyboo->next->y >= Wall_y - 1){ //当敌方飞机炮弹末端纵坐标小于墙面时CleanDisFlyBoo(temp_disflyboo->next->x, temp_disflyboo->next->y); //清除敌方飞机炮弹free(temp_disflyboo->next); //释放敌方飞机炮弹末端内存空间temp_disflyboo->next = NULL; //使被释放空间上游节点指向为空}}
}void DisFlyMove(){MoveDisFlyRander(); //调用随机函数生成运动随机数if (!(disfly->x > Wall_x - 5 && disflymoveRander.moveRander > 0) && !(disfly->x < 5 && disflymoveRander.moveRander < 0)){//控股敌方飞机运动至墙面边界时无法持续滑动CleanDisFly(); //将原有敌方飞机清除disfly->x += disflymoveRander.moveRander; //向指定随机方向进行运动DrawDisFly(); //重新绘制敌方飞机}
}void score(){if ((XXscore != XXscore_now)||(i<=(i_now+3))){ //当飞机的得分更新或显示次数小于三次时Cursor(0, Wall_y - i + i_now); //将光标指向墙面左下角并向上递减输出printf("%d !!! %d !!! %d", XXscore, XXscore, XXscore); //输出当前得分}
}void isFlyBoo(){DisFlyBoo* temp_disflyboo = (DisFlyBoo*)malloc(sizeof(DisFlyBoo)); //开辟指针型临时敌方飞机炮弹内存temp_disflyboo = disflyboo; //通过临时变量进行下游遍历查找do{if ((temp_disflyboo->x >= fly->x) && (temp_disflyboo->x <= fly->x + 6) && (temp_disflyboo->y == fly->y - 1)) //当敌方飞机炮弹位于己方飞机平面坐标时OverFly(); //执行结束己方飞机生命函数temp_disflyboo = temp_disflyboo->next; //指向下游节点} while (temp_disflyboo != NULL); //遍历至最后一枚敌方炮弹}void isDisFlyBoo(){FlyBoo* temp_flyboo = (FlyBoo*)malloc(sizeof(FlyBoo)); //开辟指针型临时己方飞机炮弹内存temp_flyboo = flyboo; //通过临时变量进行下游遍历查找do{if ((temp_flyboo->x >= disfly->x) && (temp_flyboo->x <= disfly->x + 6) && (temp_flyboo->y == disfly->y + 1)) //当己方飞机炮弹位于敌方飞机平面坐标时OverDisFly(); //执行结束敌方飞机生命函数temp_flyboo = temp_flyboo->next; //指向下游节点} while (temp_flyboo != NULL); //遍历至最后一枚己方炮弹
}void isUpFly(){//待创建
}void isUpDisFly(){//待创建
}void OverDisFly(){ CleanDisFly(); //清除敌方飞机ProductDisFlyRander(); //生成敌方飞机待生成位置随机函数disfly->x = disflyRander.disflyRander_x + 2; //指定敌方飞机所在横坐标disfly->y = 2; //指定敌方飞机所在纵坐标DrawDisFly(); //绘制敌方飞机XXscore += XXadd; //更新当前得分i_now = i; //更新当前循环计数器XXscore_now = XXscore; //更新当前分数计数器}void Draw(){system("mode con cols=132 lines=42"); //改变DOS大小copy(); //绘制商标信息system("pause"); //使用户按任意键继续system("cls"); //清屏,防止欠覆盖留白DrawWall(); //绘制墙体//初始化己方飞机fly->x = Wall_x / 2; //依照墙体指定己方飞机横坐标fly->y = Wall_y - 1; //依照墙体指定己方飞机纵坐标DrawFly(); //绘制己方飞机//初始化敌方飞机ProductDisFlyRander(); //生成敌方飞机待生成位置随机函数disfly->x = disflyRander.disflyRander_x + 2; //依照随机数指定敌方飞机横坐标disfly->y = 2; //依照随机数指定敌方飞机纵坐标DrawDisFly(); //绘制敌方飞机//绘制己方飞机炮弹disflyRander.disflybig = 6; //指定敌方飞机初始大小flyboo->x = fly->x + 2; //依照当前己方飞机横坐标指定己方飞机炮弹横坐标flyboo->y = fly->y - 1; //依照当前己方飞机纵坐标指定己方飞机炮弹纵坐标flyboo->next = NULL; //将初始飞机炮弹下游指向位置赋值为空DrawFlyBoo(); //绘制己方飞机炮弹//绘制敌方飞机炮弹disflyboo->x = disfly->x + 2; //依照当前敌方飞机横坐标指定敌方飞机炮弹横坐标disflyboo->y = disfly->y + 1; //依照当前敌方飞机纵坐标指定敌方飞机炮弹纵坐标disflyboo->next = NULL; //将初始飞机炮弹下游指向位置赋值为空DrawDisFlyBoo(); //绘制敌方飞机炮弹
}void runGame(){while (1){ //进行游戏循环isFlyBoo();isDisFlyBoo();ReDrawFly();ReDrawDisFly();ReDrawFlyBoo();ReDrawDisFlyBoo();DisFlyMove();isUpFly();isUpDisFly();score();Sleep(SleepTime);}
}void OverFly(){Sleep(600); //给予失败证据提示system("cls"); //清屏for (int i = 0; i <= 500; i++) //进行失败效果制作printf("Game Over! "); //输出游戏失败system("pause"); //等待用户按任意键退出游戏exit(0); //结束游戏关闭程序
}int main(){Draw(); //进行初始化绘制runGame(); //进行游戏运行
}
C语言飞机大战小游戏(2万字!完整精讲解版+源代码)相关推荐
- C语言—飞机大战小游戏
哈工大经典C语言大作业-飞机大战小游戏,源码如下,已经通过编译获得评分19+ (满分20)当时还是太菜了呜呜呜. 可以给大家参考一下,好像本来是加了音乐的,但是你们可能没有对应的音乐MP3文件,所以如 ...
- C语言飞机大战小游戏
说明 此设计可以作为C语言课程设计,主要用的是easyx图形库: 在VS2019成功运行,注释比较全面,对没有C语言基础的小白也很友好: 若有些地方还可以完善,请指正. 设计游戏的思路主要从以下几个当 ...
- html+javascript实现的网页版飞机大战小游戏源码
html+javascript实现的网页版飞机大战小游戏源码 完整代码下载地址: html+javascript实现的网页版飞机大战小游戏源码 index.html <!DOCTYPE html ...
- 基于Java语言在窗体上实现飞机大战小游戏
全套资料下载地址:https://download.csdn.net/download/sheziqiong/85594271 项目介绍 飞机大战:用 Java 语言在窗体上实现飞机大战小游戏,运行程 ...
- 用C语言实现飞机大战小游戏
我的个人博客:谋仁·Blog 该项目已上传至GitHub:点击跳转 文章目录 摘要 运行环境 整体功能思维导图 效果预览 具体功能的实现 图形界面:EasyX EasyX图形库简介 EasyX图形库的 ...
- 华为官方解析开源鸿蒙 OpenHarmony 3.1关键特性画布,教你如何完成飞机大战小游戏
华为技术有限公司的江英杰为大家揭晓了关于开源鸿蒙 OpenHarmony 3.1 Beta 版中的一个关键特性,也就是 ArkUI 开发框架中的 canvas 画布. 据介绍,canvas 是 Ark ...
- canvas绘制“飞机大战”小游戏,真香
canvas是ArkUI开发框架里的画布组件,常用于自定义绘制图形.因为其轻量.灵活.高效等优点,被广泛应用于UI界面开发中. 本期,我们将为大家介绍canvas组件的使用. 目录 一.canvas介 ...
- 【python】飞机大战小游戏练习
飞机大战小游戏练习 一.前提准备 二.制作步骤 1.库的导入与初始化 2.窗口操作 3.键盘按键监听相关操作 4.添加游戏背景 5.加载玩家飞机 6.获取玩家飞机矩阵 三.完整代码编写 游戏背景类编写 ...
- python 飞机大战小游戏
飞机大战小游戏,这里需要下载pygame模块 这是需要的素材,需要的自取: 上代码: import time import pygame from pygame.locals import *#检测事 ...
- 点击list view中一行内容可以在combox中显示_java版飞机大战小游戏详细教程(零基础小白也可以分分钟学会!)...
一:游戏展示 飞机大战小游戏我们都玩过,通过移动飞机来打敌机,这里给大家展示一下游戏成果:呜呜呜由于gif只能上传5M大小,所以就不能给大家展示操作了,如果大家有兴趣可以自己自己做出来再玩哟. 这里面 ...
最新文章
- VS中使用OpenCV构建应用程序
- 解决python读取json格式数据后提取object不存在报错KeyError
- window.external的使用
- 高性能 Windows Socket 服务端与客户端组件(HP-Socket v1.0.1 源代码及测试用例下载)...
- HashSet、TreeSet、LinkedHashSet的区别
- 网线RJ45接口排线示意图(做网线备用)
- Tolua使用笔记(上)
- go chan 类型用法
- 新元宇宙每周连载《地球人奇游天球记》第十五回土星种菜
- 转使用chrome命令行:disable-web-security 实现浏览器跨域
- 快速给图片加水印的方法
- Context-Free Grammar及形状规则集
- QT常用控件——QComboBox控件
- Shell 脚本小试牛刀(5) -- 超便捷脚本之高速ssh 登录其它主机
- 天猫精灵实现误无醒词推送断网负载播报
- 告别慢SQL,如何去写一手好SQL ?
- android卸载按钮不能用了,不用ROOT 干掉Android里无法卸载的APP
- 母亲节倒计时,选礼物救急指南
- 界面设计——东方快车安装界面
- [GO项目]开源免费在线客服系统-真正免费开源-GOFLY0.3.3发布-极简强大Go语言开发网页客服...