c/c++开发分享C++实现飞机大战游戏实例为大家分享了c++实现飞机大战游戏的具体代码,供大家参考,具体内容如下
代码是单线程执行,无界面,(博主下一步学习qt之后融入)还有待改进。
先放张界面图:
话不多说 上代码(注释很清楚,不懂可和博主交流)
main.cpp:
#include<iostream> #include<ctime> #include<string> #include"game.h" using namespace std; int main() { srand((unsigned int)time(null));//随机时间种子 hidecursor();//隐藏光标 game game; int a=drawmenu(); if (a == 2) { game.rank = 20; } system("cls"); drawplaying(); game.playing(); }
game.h:
#pragma once #include<iostream> #include<windows.h>//定义控制台应用程序的入口点 using namespace std; //定义敌人结构 其中最后面frame代表结构体类型 若不加typedef代表定义的结构体变量 typedef struct frame { coord position[2]; // coord 是windows api中定义的一种结构,表示一个字符在控制台屏幕上的坐标。 // 其定义为: // typedef struct _coord { // short x; // short y; // } coord; int flag; }frame; class game { public: coord position[10]; coord bullet[10];//子弹坐标 frame enemy[8];//敌人数量 int score; int rank;//级别,难度 int rankf;//等级标志 string title; int flag_rank;//等级标志 //构造函数 game(); //初始化所有 //设定位置 void initplane(); void initbullet(); void initenemy(); //填充所有 --画出形状和消失的形状 void drawplane(); void drawplanetonull(); void drawbullet(); void drawbullettonull(); void drawenemy(); void drawenemytonull(); //执行某一个操作 void playing();//游戏主循环 void planemove(char x);//飞机移动 void judgeplane();//判断飞机是否与敌机重叠 void gameover();//游戏失败 void pause();// 该成员函数用来使得游戏暂停 void shoot();//发射子弹 void bulletmove();//子弹移动 void drawthisbullettonull(coord c);//画出失效子弹 void judgeenemy();//判断子弹是否击中敌机 void drawthisenemytonull(frame f); //击败的敌机清空 void enemymove();//敌机移动 void printscore();//输出分数 }; //主菜单 int drawmenu(); //隐藏光标 void hidecursor(); void setpos(int i, int j);//设置光标 coord random(coord a, coord b);//产生随机敌机位置 void drawframe(coord a, coord b, char row, char col);//画出敌机 //把第y行,[x1, x2) 之间的坐标填充为 ch void drawrow(int y, int x1, int x2, char ch); //把第x列,[y1, y2] 之间的坐标填充为 ch void drawcol(int x, int y1, int y2, char ch); // 绘制游戏界面 void drawplaying(); void drawframe(frame frame, char row, char col);//画坠毁后的战机 // 该函数用来判断战机的某一部分是否与敌机有接触 bool judgecoordinframe(frame frame, coord spot); void drawrow(coord a, coord b, char ch);
game.cpp:
#include"game.h" #include<windows.h> #include<conio.h> game::game() { // 调用类成员函数来进行初始化 initplane(); initbullet(); initenemy(); // 初始化四个int型数据成员,采用赋值的方式进行初始化 // string类型的数据成员title没有进行初始化,因为: // string本身就是一个标准库类类型,它的类定义中设置了默认构造函数, // 这些默认构造函数会将对象初始化为合理的默认状态, // string的默认构造函数会产生空字符串,相当于"" 。 this->score = 0; rank = 25; rankf = 25; flag_rank = 0; } void game::initplane() { coord centren; centren.x = 39; centren.y = 22; position[0].x = position[5].x = position[7].x = position[9].x = centren.x; position[1].x = centren.x - 2; position[2].x = position[6].x = centren.x - 1; position[3].x = position[8].x = centren.x + 1; position[4].x = centren.x + 2; for (int i = 0; i <= 4; i++) { position[i].y = centren.y; } for (int i = 6; i <= 8; i++) { position[i].y = centren.y + 1; } position[5].y = centren.y - 1; position[9].y = centren.y - 2; // 这个函数体类的代码其实就是为了初始化战机的十个部分的位置,战机的组成如下所示: // | 5 // | 9 // ***** 12034 // *** 678 // 第一排5个0的坐标依次对应了position[1]position[2]position[0]position[3]position[4] // 第二排三个0的坐标依次对应了position[6]position[7]position[8] // 两排0上面的两|的坐标从上往下依次对应了position[5]position[9] } void game::drawplane() { for (int i = 0; i < 9; i++) { setpos(position[i].x,position[i].y); if (i != 5) { cout << "*"; } else if (i == 5) { cout << "|"; } } } // 这个成员函数通过将战机的每个坐标处输出" "来代替"0"和"|", // 来达到将战机消除的目的。 void game::drawplanetonull() { for (int i = 0; i < 9; i++) { setpos(position[i].x, position[i].y); cout << " "; } } // 该成员函数用来初始化子弹, // 即将每个子弹的y坐标初始化为30(bullet[i].y = 30)来表示子弹处于失效状态 void game::initbullet() { for (int i = 0; i < 10; i++) { bullet[i].y = 30; } } // 该成员函数用来画出子弹 // 首先检查每颗子弹的有效性,如果子弹有效,则定位到该子弹的坐标处,输出 "^",表示该子弹, // 如果子弹是无效的,则不绘制 void game::drawbullet() { for (int i = 0; i < 10; i++) { if (bullet[i].y != 30) { setpos(bullet[i].x,bullet[i].y); cout << "^"; } } } //子弹失效 void game::drawbullettonull() { for (int i = 0; i < 10; i++) if (bullet[i].y != 30) { setpos(bullet[i].x, bullet[i].y + 1); cout << " "; } } // 这个函数用来初始敌机的位置, // 屏幕当中只能同时存在八架敌机, // 且每架敌机用如下结构体frame来表示,如下所示: // typedef struct frame // { // coord position[2]; // int flag; // }frame; coord random(coord a, coord b) { int x = rand() % (a.x - b.x) + a.x; int y = rand() % (a.y - b.y) + a.y; coord c = { x,y }; return c; } void game::initenemy() { coord a = { 1, 1 }; coord b = { 45, 15 }; for (int i = 0; i < 8; i++) { enemy[i].position[0] = random(a, b); // random(a, b)是调用了一个重载的函数,它表示在坐标a、b之间的矩形框 // 内随机生成一个坐标值,并将该坐标值作为敌机的左上角的坐标。 // enemy[i].position[0]中是一个frame结构体类型的变量,存放了敌机i的左上角的坐标。 enemy[i].position[1].x = enemy[i].position[0].x + 3; enemy[i].position[1].y = enemy[i].position[0].y + 2; // enemy[i].position[1]也中是一个frame结构体类型的变量,存放了敌机i的右下角的坐标。 } } // 接下来要根据敌机的左上角坐标和右下角坐标画出敌机, // 显然,敌机的外形如下所示: // -- // | | // -- void game::drawenemy() { for (int i = 0; i < 8; i++) { drawframe(enemy[i].position[0], enemy[i].position[1], '-', '|'); } } // 将敌机消除,通过输出空白的方式 void game::drawenemytonull() { for (int i = 0; i < 8; i++) { drawframe(enemy[i].position[0], enemy[i].position[1], ' ', ' '); } } //隐藏光标 void hidecursor() { console_cursor_info cursor_info = { 1,0 };//第二个值0表示隐藏光标 setconsolecursorinfo(getstdhandle(std_output_handle), &cursor_info); } void setpos(int i, int j)//设置坐标点位(光标) { handle hout; coord coord; coord.x = i; coord.y = j; hout = getstdhandle(std_output_handle); setconsolecursorposition(hout, coord); } //左上角坐标、右下角坐标、用row填充行、用col填充列 void drawframe(coord a, coord b, char row, char col) { drawrow(a.y, a.x + 1, b.x - 1, row); drawrow(b.y, a.x + 1, b.x - 1, row); drawcol(a.x, a.y + 1, b.y - 1, col); drawcol(b.x, a.y + 1, b.y - 1, col); } //把第y行,[x1, x2) 之间的坐标填充为 ch void drawrow(int y, int x1, int x2, char ch) { setpos(x1, y); for (int i = 0; i <= (x2 - x1); i++) { cout << ch; } } //把第x列,[y1, y2] 之间的坐标填充为 ch void drawcol(int x, int y1, int y2, char ch) { int y = y1; while (y != y2 + 1) { setpos(x, y); cout << ch; y++; } } //主菜单绘制 int drawmenu() { setpos(30,1); cout << "飞 机 大 战"; drawrow(3, 0, 79, '-'); drawrow(5, 0, 79, '-'); setpos(28, 4); cout << "w 和 s选择,k确定"; int j = 11; setpos(12, j); cout << ">>"; setpos(15, 11); cout << "1. 简单的敌人"; setpos(15, 13); cout << "2. 冷酷的敌人"; drawrow(20, 0, 79, '-'); setpos(47, 11); cout << "简单的敌人:"; setpos(47, 13); cout << "简单敌人有着较慢的移动速度。"; setpos(30, 21); cout << "copy right@风兮木萧"; drawrow(22, 0, 79, '-'); while (true) { if (_kbhit()) { char x = _getch(); switch (x) { case'w': { if (j == 13) { setpos(12, j); cout << " "; j = 11; setpos(12, j); cout << ">>"; setpos(51, 13); cout << " "; setpos(47, 11); cout << "简单的敌人:"; setpos(51, 13); cout << "简单敌人有着较慢的移动速度,比较容易对付"; } break; } case's': { if (j == 11) { setpos(12, j); cout << " "; j = 13; setpos(12, j); cout << ">>"; setpos(51, 13); cout << " "; setpos(47, 11); cout << "冷酷的敌人:"; setpos(51, 13); cout << "冷酷的敌人移动速度较快,难对付哟。"; } break; } case 'k': { if (j == 11)//源代码为8? return 1; else return 2; } } } } return 0; } void drawframe(int x1, int y1, int x2, int y2, char row, char col) { coord a = { x1, y1 }; coord b = { x2, y2 }; drawframe(a, b, row, col); } // 绘制游戏界面 void drawplaying() { drawframe(0, 0, 48, 24, '=', '|');// draw map frame主界面 drawframe(49, 0, 79, 4, '-', '|');// draw output frame 状态界面 drawframe(49, 4, 79, 9, '-', '|');// draw score frame 分数界面 drawframe(49, 9, 79, 20, '-', '|');// draw operate frame 操作界面 drawframe(49, 20, 79, 24, '-', '|');// draw other message frame 提示界面 setpos(52, 6); cout << "得分:"; setpos(52, 7); cout << "称号:"; setpos(52, 11); cout << "操作方式:"; setpos(52, 13); cout << " a,s,d,w:控制战机移动。"; setpos(52, 15); cout << " p:暂停游戏。"; setpos(52, 17); cout << " e:退出游戏。"; setpos(52, 22); cout << " 游戏虽好玩,不要贪多哦 "; } // 该成员函数用过响应战机的一个动作 // a,s,w,d,来控制战机的移动 void game::planemove(char x) { if (x == 'a') { if (position[1].x != 1) { for (int i = 0; i <= 9; i++) { position[i].x -= 2; } } } // 如果玩家按下 'a' 键,说明玩家想让战机往左移动一个距离(2个单位), // 首先检测,战机的最左侧的位置坐标(即position[1].x)有没有达到左边界, // 如果到达了边界,那就不做出移动;如果没有达到边界,则将战机10个部分的x值减小2。 if (x == 's') { if (position[7].y != 23) { for (int i = 0; i <= 9; i++) { position[i].y += 1; } } } // 如果玩家按下 's' 键,说明玩家想让战机往下移动一个距离(1个单位), // 首先检测,战机的最底部的位置坐标(即position[6].y或者position[7].y或者position[8].y)有没有达到下边界, // 如果到达了边界,那就不做出移动;如果没有达到边界,则将战机10个部分的y值增加1。 if (x == 'd' && (position[4].x != 47)) { for (int i = 0; i <= 9; i++) { position[i].x += 2; } } // 如果玩家按下 'd' 键,说明玩家想让战机往右移动一个距离(2个单位), // 首先检测,战机的最右侧的位置坐标(即position[4].x)有没有达到右边界, // 如果到达了边界,那就不做出移动;如果没有达到边界,则将战机10个部分的x值增加2。 if (x == 'w'&&(position[5].y != 3)) { for (int i = 0; i <= 9; i++) { position[i].y -= 1; } } // 如果玩家按下'w'键,说明玩家想让战机往上移动一个距离(1个单位), // 首先检测,战机的最顶部的位置坐标(即position[5].y)有没有达到上边界, // 如果到达了边界,那就不做出移动;如果没有达到边界,则将战机10个部分的y值减少1。 } // 该函数用来判断战机的某一部分是否与敌机有接触 // 如果与敌机有接触在判断为坠毁 bool judgecoordinframe(frame frame, coord spot) { if ((spot.x >= frame.position[0].x) && (spot.x <= frame.position[1].x) && (spot.y >= frame.position[0].y) && (spot.y <= frame.position[1].y)) { return true; } return false; } void drawframe(frame frame, char row, char col) { coord a = frame.position[0]; coord b = frame.position[1]; drawframe(a, b, row, col); } //游戏结束 void game::gameover() { system("cls"); coord p1 = { 28,9 }; coord p2 = { 53,15 }; drawframe(p1, p2, '=', '|'); setpos(36, 12); string str = "game over!"; for (int i = 0; i < str.size(); i++) { sleep(80); cout << str[i]; } sleep(1000); system("cls"); drawframe(p1, p2, '=', '|'); setpos(31, 11); cout << "击落敌机:" << score / 5 << " 架"; setpos(31, 12); cout << "得 分:" << score; setpos(31, 13); cout << "获得称号:" << title; setpos(30, 18); sleep(1000); cout << "继续? 是(y)| 否(n)"; as://goto 语句标签 直接跳转至此 char x = _getch(); if (x == 'n') { exit(0); } else if (x == 'y') { system("cls"); game game; int a = drawmenu(); // 绘制游戏开始界面主菜单 if (a == 2) game.rank = 20; system("cls"); drawplaying(); // 绘制游戏界面框架 game.playing(); } else goto as; } // 该成员函数用来判断战机是否坠毁, // 依次判断每架敌机与战机的每个部分是否有接触, // 如果有接触,则表示战机坠毁 void game::judgeplane() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 9; j++) // 此处的实参position[j]是指战机的10个部分的coord坐标, // 类中的成员函数可以访问数据成员变量。 // 此处也可以写成this-> position[j],因为 // 成员函数具有一个附加的隐含形参,即指向该类对象的一个指针, // 这个隐含形参命名为this,与调用成员函数的对象绑定在一起。 // 成员函数不能定义this形参,而是由编译器隐含地定义。 // 成员函数的函数体可以显式使用this指针,但不是必须这么做。 if (judgecoordinframe(enemy[i], position[j])) { setpos(62, 1); cout << "坠毁"; drawframe(enemy[i], '+', '+'); // 将与战机相撞的敌机的形状绘制为: // ++ // + + // ++ sleep(1000); gameover(); break; } } } // 该成员函数用来使得游戏暂停 void game::pause() { setpos(61, 2); cout << " "; setpos(61, 2); cout << "暂停中..."; // 当出现"暂停中..."的提示以后,程序不停的接收按下的按键, // 当按下'p'键以后,说明要退出暂停状态,此时需要清除"暂停中..."的提示 // 通过输出空白 " "来将其覆盖,达到效果 char c = _getch(); while (c != 'p') { c = _getch(); } setpos(61, 2); cout << " "; } // 这个成员函数用来响应一次射击操作, // 也就是,当游戏中的时候,玩家按下"k"键,就执行该函数。 // 由于子弹是由coord bullet[10]定义的,因此同一时刻,界面内只能有10颗子弹同时出现。 // 如果界面内不够10颗子弹,按下"k"键后战机应该发射出一颗子弹, // 于是,依次遍历10颗子弹,当遇到第一颗失效的子弹后, // 立即将该子弹赋予新的坐标(战机的炮口,也就是(position[5].x,position[5].y - 1)), // 让其激活。然后退出for循环,函数执行完毕。 void game::shoot() { for (int i = 0; i < 10; i++) { if (bullet[i].y == 30) { bullet[i].x = position[5].x; bullet[i].y = position[5].y - 1; break; } } } void game::drawthisbullettonull(coord c) { setpos(c.x,c.y); cout << " "; } // 此成员函数用来响应一次子弹的运动 // 每次子弹运动,屏幕子弹的坐标都会出现变化,即 // 先判断子弹是否有效(即判断语句if (bullet[i].y != 30)), // 若子弹有效,将该子弹的y坐标减少1,x坐标不变, // 检测子弹坐标更改之后是否达到上边界,如果达到上边界,则将该子弹从屏幕上擦除, // 同时,将该子弹置为失效状态,即 bullet[i].y = 30。 void game::bulletmove() { for (int i = 0; i < 10; i++) { if (bullet[i].y != 30) { bullet[i].y -= 1; if (bullet[i].y == 1) { coord pos = { bullet[i].x, bullet[i].y + 1 }; drawthisbullettonull(pos); bullet[i].y = 30; } } } } //击败的敌机清空 void game::drawthisenemytonull(frame f) { drawframe(f, ' ', ' '); } // 该成员函数依次遍历每一架敌机, // 将每一架敌机依次与每一颗子弹进行检测, // 判断敌机是否与子弹有接触,如果有接触,则表示击中敌机, // 此时将敌机和子弹擦除,然后在界面顶部的位置处随机生成一架敌机 void game::judgeenemy() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 10; j++) { if (judgecoordinframe(enemy[i], bullet[j])) { score += 5; drawthisenemytonull(enemy[i]); coord a = { 1, 1 }; coord b = { 45, 3 }; enemy[i].position[0] = random(a, b); enemy[i].position[1].x = enemy[i].position[0].x + 3; enemy[i].position[1].y = enemy[i].position[0].y + 2; drawthisbullettonull(bullet[j]); bullet[j].y = 30; } } } } // 该成员函数用来响应一次敌机的移动 // 界面上必须同时出现八架敌机,因此, // 如果有某架敌机运动到下边界处,则重置该敌机的坐标 void game::enemymove() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 2; j++) enemy[i].position[j].y++; // 我们将每架敌机的左上角和右下角坐标的y值增加1, // 表示该敌机向下走了一个距离 // 检测向下走一个距离后的敌机的右下角坐标的y值是否达到24, // 如果达到,代表敌机已经运动到下边界了, // 此时需要随机重置该敌机的坐标 if (enemy[i].position[1].y==24) { coord a = { 1, 1 }; coord b = { 45, 3 }; enemy[i].position[0] = random(a, b); enemy[i].position[1].x = enemy[i].position[0].x + 3; enemy[i].position[1].y = enemy[i].position[0].y + 2; } } } void game::printscore() { if (score <= 120) { flag_rank = 1; } else if (score > 120 && score <= 360) { flag_rank = 2; } else if (score > 360 && score <= 480) { flag_rank = 3; } else if (score > 480) { flag_rank = 4; } setpos(60, 6); cout << score; setpos(60, 7); if (flag_rank == 1) { title = "初级飞行员"; } else if (flag_rank == 2) { title = "中级飞行员"; } else if (flag_rank == 3) { title = "高级飞行员"; } else if (flag_rank == 4) { title = "王牌飞行员"; } cout << title; } // 这个成员函数是游戏的主循环函数, // 定义了整个游戏过程。 void game::playing() { drawenemy(); drawplane(); int flag_bullet = 0; int flag_enemy = 0; while (true) { sleep(20); // 函数名:kbhit()(vc++6.0下为_kbhit()) // 功能及返回值: 检查当前是否有键盘输入,若有则返回一个非0值,否则返回0 // 用法:int kbhit(void); // 包含头文件: include <conio.h> // kbhit()在执行时,检测是否有按键按下,有按下返回非0值,没有按下则返回0,是非阻塞函数; // 不同于getch()的在执行时, 检测按下什么键, 如果不按键该函数不返回,也就不进行下一步操作,是阻塞函数。 if (_kbhit()) { char x = _getch(); // getch()是编程中所用的函数,这个函数是一个不回显函数, // 当用户按下某个字符时,函数自动读取,无需按回车 // getch()并非标准c中的函数,不存在c语言中。 // 所在头文件是conio.h,而不是stdio.h。 // 用ch = getch(); 会等待你按下任意键之后,把该键字符所对应的ascii码赋给ch, 再执行下面的语句。 if ('a' == x || 's' == x || 'd' == x || 'w' == x) { drawplanetonull(); // 将战机先擦除 planemove(x); // 根据所输入的操作符,对战机的坐标进行更改 drawplane(); // 访问类中的数据成员——战机的坐标,在新的坐标处重新绘制战机 judgeplane(); // 判断战机是否有坠毁 } // 在某一循环当中,如果检测到有'p'键按下, // 首先在右侧游戏界面输出"暂停中...",然后陷入while()循环一直等待'p'键再次按下, // 如果'p'键没有按下,就一直处在while()循环内,因此不能执行后面的程序,起到暂停的效果。 else if ('p' == x) { pause(); } // 如果是检测到'k'键按下,则运行shoot()函数, else if ('k' == x) { shoot(); } // 如果是检测到'k'键按下,则运行gameover()函数, // gameover()函数执行完毕后,执行break;语句跳出while循环(注意不是if (_kbhit()))。 // break语句用于结束最近的while、do while、for或switch语句,并将程序的执行权传递给紧接在 // 被终止语句之后的语句。 else if ('e' == x) { //closehandle(mfun) gameover(); break; } } // 接下来处理子弹 // 判断子弹状态的程序一直在运行 if (flag_bullet == 0) { bulletmove(); // 更新界面上有效子弹的坐标 drawbullettonull(); // 将处于旧坐标的子弹擦除 drawbullet(); // 绘制出新坐标上的子弹 judgeenemy(); // 判断敌机是否被子弹击中 } flag_bullet++; if (flag_bullet==1) { flag_bullet = 0; } // 接下来处理敌机 if (flag_enemy==0) { drawenemytonull(); // 将所有的敌机都擦除 enemymove(); // 更新敌机的坐标 drawenemy(); // 绘制出处于新坐标上的敌机 judgeplane(); // 判断敌机是否与战机接触 } flag_enemy++; if (flag_enemy >= rank) { flag_enemy = 0; } /* 输出得分 */ printscore(); } }
以上就是c/c++开发分享C++实现飞机大战游戏的全部内容,希望对大家的学习有所帮助,也希望大家多多支持<计算机技术网(www.ctvol.com)!!>。
需要了解更多c/c++开发分享C++实现飞机大战游戏,都可以关注C/C++技术分享栏目—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/1238059.html