当前位置:   article > 正文

程序设计 C语言飞机大战

c语言飞机大战

作业要求:

1.游戏当中出现多类型敌人
2.游戏中能进行存档和读档
3.玩家控制的飞机由多字符组成
4.游戏过程中没有出现BUG 
5.游戏显示制作者信息
6.游戏当中带有BGM
7.其他个性化设定

成效:

代码:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<conio.h>
  4. #include<windows.h>
  5. #include<mmsystem.h> // 导入声音头文件
  6. #pragma comment(lib,"Winmm.lib") // 导入声音头文件库
  7. #define High 20 // 游戏画面尺寸
  8. #define Width 30
  9. #define EnemyNum 5 // 敌机个数
  10. #define BossNum 2 // Boss机个数
  11. int flag; // 飞机状态
  12. int color(int c); // 更改文字颜色
  13. void explation(); // 游戏提示
  14. void show(); // 显示游戏界面
  15. void endgame(); // 游戏结束
  16. void startup(); // 数据初始化
  17. void FileRead(); // 读档
  18. // 全局变量
  19. int position_x, position_y; // 飞机位置
  20. struct enemy{
  21. int x;
  22. int y;
  23. int life;
  24. }Boss[BossNum], enemy[EnemyNum]; // 敌机位置
  25. int canvas[High][Width] = {0}; // 二维数组存储游戏画布中对应的元素
  26. // 0为空格,1为飞机8,2为子弹o,3为敌机0 , 4为Boss敌机A
  27. int score; // 得分
  28. int number; // 销毁敌机数
  29. int BulletWidth; // 子弹宽度
  30. int EnemyMoveSpeed; // 敌机移动速度
  31. // 光标移动到(x,y)位置
  32. void gotoxy(int x, int y)
  33. {
  34. HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  35. COORD pos;
  36. pos.X = x;
  37. pos.Y = y;
  38. SetConsoleCursorPosition(handle, pos);
  39. }
  40. // 更改文字颜色
  41. int color(int c)
  42. {
  43. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);
  44. return 0;
  45. }
  46. // 隐藏光标
  47. void HideCursor()
  48. {
  49. CONSOLE_CURSOR_INFO cursor_info = {1,0};
  50. SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
  51. }
  52. // 开始界面
  53. void welcometogame()
  54. {
  55. int n, i, j = 1;
  56. system("cls");
  57. color(15);
  58. gotoxy(33, 1);
  59. printf("飞机大战 Plane War");
  60. color(56);
  61. for (i = 3; i <= 26; i++) // 输出上下边框
  62. {
  63. for (j = 6; j <= 80; j++) // 输出左右边框
  64. {
  65. gotoxy(j, i);
  66. if (i == 3 || i == 26)
  67. printf(" ");
  68. else if (j == 6 || j == 80)
  69. printf(" ");
  70. }
  71. }
  72. color(14);
  73. gotoxy(38, 6);
  74. printf("基本操作\n");
  75. gotoxy(19, 8);
  76. printf("空格:发射子弹 W:前进 A:左移 D:右移 S:后退\n");
  77. gotoxy(34, 11);
  78. printf("1.开始游戏(play)");
  79. gotoxy(34, 13);
  80. printf("2.游戏规则(rule)");
  81. gotoxy(34, 15);
  82. printf("3.读取存档(read)");
  83. gotoxy(34, 17);
  84. printf("4.退出游戏(quit)");
  85. color(15);
  86. gotoxy(14, 24);
  87. printf("游戏制作人:XXX 学号:XXXXXXXXX 联系方式:XXXXXXXXXXX");
  88. color(14);
  89. gotoxy(33, 20);
  90. printf("请选择 1 2 3 4: ");
  91. color(14);
  92. scanf("%d", &n); // 输入选项
  93. switch (n)
  94. {
  95. case 1:
  96. flag = 1;
  97. system("cls");
  98. break;
  99. case 2:
  100. explation(); // 游戏规则
  101. break;
  102. case 3:
  103. system("cls"); // 读档
  104. break;
  105. case 4:
  106. gotoxy(30, 28);
  107. exit(0); // 退出游戏
  108. break;
  109. default:
  110. color(9);
  111. gotoxy(33, 22);
  112. printf("请输入1-4之间的数");
  113. _getch(); // 输入任意键
  114. system("cls"); // 清屏
  115. welcometogame();
  116. }
  117. }
  118. // 游戏规则
  119. void explation()
  120. {
  121. int i, j = 1;
  122. system("cls");
  123. color(15);
  124. gotoxy(30, 1);
  125. printf("游戏规则 Rules of game");
  126. color(56);
  127. for (i = 3; i <= 26; i++) // 输出上下边框
  128. {
  129. for (j = 6; j <= 80; j++) // 输出左右边框
  130. {
  131. gotoxy(j, i);
  132. if (i == 3 || i == 26)
  133. printf(" ");
  134. else if (j == 6 || j == 80)
  135. printf(" ");
  136. }
  137. }
  138. color(14);
  139. gotoxy(10, 6);
  140. printf("1. W,A,S,D 分别是控制飞机的移动,空格发射子弹");
  141. gotoxy(10, 9);
  142. printf("2. O是普通敌机(需一发子弹),A是Boss敌机(需两发子弹)");
  143. gotoxy(10, 12);
  144. printf("3. 击败普通敌机可获得1分,击败Boss敌机可获得2分");
  145. gotoxy(10, 15);
  146. printf("4. 敌机进入下边界减1分");
  147. gotoxy(10, 18);
  148. printf("5. 飞机碰到敌机会坠落");
  149. gotoxy(10, 21);
  150. printf("6. 按Z存档,按P暂停游戏");
  151. color(15);
  152. gotoxy(25, 23);
  153. printf("/*****按任意键返回主页面*****/");
  154. _getch(); // 按任意键返回主界面
  155. system("cls");
  156. welcometogame();
  157. }
  158. // 数据初始化
  159. void startup()
  160. {
  161. mciSendString("open D:\\plane\\game.mp3 alias bkmusic ",NULL,0,NULL); // 打开背景音乐
  162. mciSendString("play bkmusic",NULL,0,NULL); // 循环播放
  163. position_x = High / 2;
  164. position_y = Width / 2;
  165. canvas[position_x][position_y] = 3;
  166. canvas[position_x + 1][position_y - 1] = 3;
  167. canvas[position_x + 1][position_y] = 3;
  168. canvas[position_x + 1][position_y + 1] = 3;
  169. int k;
  170. for (k = 0; k < EnemyNum; k++)
  171. {
  172. enemy[k].x = rand() % 2;
  173. enemy[k].y = rand() % Width;
  174. canvas[enemy[k].x][enemy[k].y] = 3;
  175. }
  176. for (k = 0; k < BossNum; k++)
  177. {
  178. Boss[k].x = rand() % 2;
  179. Boss[k].y = rand() % Width;
  180. canvas[Boss[k].x][Boss[k].y] = 4;
  181. Boss[k].life = 2;
  182. }
  183. int score = 0; // 成绩
  184. int number = 0; // 销毁敌机数
  185. BulletWidth = 0;
  186. EnemyMoveSpeed = 30;
  187. HideCursor(); // 光标
  188. }
  189. // 存档代码
  190. void FileWrite()
  191. {
  192. FILE *fp; // 文件指针
  193. fp = fopen("D:\\game.data", "w"); // 打开文件 "w": write写入文件
  194. int i, j;
  195. for (i = 0; i < EnemyNum; i++)
  196. {
  197. fwrite(&enemy[i], sizeof(struct enemy), 1, fp);
  198. }
  199. for (j = 0; j < BossNum; j++)
  200. {
  201. fwrite(&Boss[j], sizeof(struct enemy), 1, fp);
  202. }
  203. fwrite(&position_x, sizeof(int), 1, fp);
  204. fwrite(&position_y, sizeof(int), 1, fp);
  205. fwrite(&score, sizeof(int), 1, fp);
  206. fwrite(&number, sizeof(int), 1, fp);
  207. fwrite(&BulletWidth, sizeof(int), 1, fp);
  208. fwrite(&EnemyMoveSpeed, sizeof(int), 1, fp);
  209. fclose(fp); // 关闭文件
  210. printf("\n保存成功\n");
  211. }
  212. // 读档代码
  213. void FileRead()
  214. {
  215. FILE *fp; // 文件指针
  216. fp = fopen("D:\\game.data", "r"); // 打开文件 "r": read读取文件
  217. mciSendString("open D:\\plane\\game.mp3 alias bkmusic ",NULL,0,NULL); // 打开背景音乐
  218. mciSendString("play bkmusic",NULL,0,NULL); // 循环播放
  219. if(fp == NULL)
  220. startup();
  221. else
  222. {
  223. int i, j;
  224. for (i = 0; i < EnemyNum; i++)
  225. {
  226. fread(&enemy[i], sizeof(struct enemy), 1, fp);
  227. }
  228. for (j = 0; j < BossNum; j++)
  229. {
  230. fread(&Boss[j], sizeof(struct enemy), 1, fp);
  231. }
  232. fread(&position_x, sizeof(int), 1, fp);
  233. fread(&position_y, sizeof(int), 1, fp);
  234. fread(&score, sizeof(int), 1, fp);
  235. fread(&number, sizeof(int), 1, fp);
  236. fread(&BulletWidth, sizeof(int), 1, fp);
  237. fread(&EnemyMoveSpeed, sizeof(int), 1, fp);
  238. }
  239. fclose(fp); // 关闭文件
  240. canvas[position_x][position_y] = 1;
  241. canvas[position_x + 1][position_y - 1] = 1;
  242. canvas[position_x + 1][position_y] = 1;
  243. canvas[position_x + 1][position_y + 1] = 1;
  244. int k;
  245. for (k = 0; k < EnemyNum; k++)
  246. {
  247. canvas[enemy[k].x][enemy[k].y] = 3;
  248. }
  249. for (k = 0; k < BossNum; k++)
  250. {
  251. canvas[Boss[k].x][Boss[k].y] = 4;
  252. Boss[k].life = 2;
  253. }
  254. HideCursor();
  255. }
  256. // 显示画面
  257. void show()
  258. {
  259. color(112);
  260. gotoxy(0, 0); // 光标移动到原点位置,以下重画清屏
  261. int i, j;
  262. for (i = 0; i < High; i++)
  263. {
  264. for (j = 0; j < Width; j++)
  265. {
  266. if ((j == Width - 1) || (i == High - 1) || (j == 0) || (i == 0))
  267. printf("#"); // 打印边界#
  268. else if (canvas[i][j] == 1)
  269. printf("8"); // 输出飞机8
  270. else if (canvas[i][j] == 2)
  271. printf("o"); // 输出子弹o
  272. else if (canvas[i][j] == 3)
  273. printf("O"); // 输出敌机O
  274. else if (canvas[i][j] == 4)
  275. printf("A"); // 输出Boss敌机A
  276. else
  277. printf(" ");
  278. }
  279. printf("\n");
  280. }
  281. color(14);
  282. printf("\n");
  283. printf("游戏得分: %d\n", score);
  284. printf("销毁敌机: %d\n\n", number);
  285. Sleep(20);
  286. }
  287. // 与用户输入无关的更新
  288. void updateWithoutInput()
  289. {
  290. int i, j, k;
  291. for (i = 0; i < High; i++)
  292. {
  293. for (j = 0; j < Width; j++)
  294. {
  295. if (canvas[i][j] == 2)
  296. {
  297. for (k = 0; k < EnemyNum; k++)
  298. {
  299. if ((i == enemy[k].x) && (j == enemy[k].y)) // 子弹击中敌机
  300. {
  301. mciSendString("close gemusic",NULL,0,NULL); // 先把前面一次的音乐关闭
  302. mciSendString("open D:\\plane\\gotEnemy.mp3 alias gemusic ",NULL,0,NULL); // 打开音乐
  303. mciSendString("play gemusic",NULL,0,NULL); // 仅播放一次
  304. score++; // 分数加1
  305. number++; // 销毁敌机数加1
  306. if (number % 6 == 0 && EnemyMoveSpeed > 3) // 达到一定积分后,敌机变快
  307. EnemyMoveSpeed--;
  308. if (number % 12 == 0) // 达到一定积分后,子弹变厉害
  309. BulletWidth++;
  310. canvas[enemy[k].x][enemy[k].y] = 0; // 残影问题
  311. enemy[k].x = rand() % 2; // 产生新的敌机
  312. enemy[k].y = rand() % Width;
  313. canvas[enemy[k].x][enemy[k].y] = 3;
  314. canvas[i][j] = 0; // 子弹消失
  315. }
  316. }
  317. for (k = 0; k < BossNum; k++)
  318. {
  319. if ((i == Boss[k].x) && (j == Boss[k].y)) // 子弹击中Boss敌机
  320. {
  321. mciSendString("close gemusic",NULL,0,NULL); // 先把前面一次的音乐关闭
  322. mciSendString("open D:\\plane\\gotEnemy.mp3 alias gemusic ",NULL,0,NULL); // 打开音乐
  323. mciSendString("play gemusic",NULL,0,NULL); // 仅播放一次
  324. Boss[k].life--; // Boss敌机生命值减1
  325. if (Boss[k].life == 0)
  326. {
  327. canvas[Boss[k].x][Boss[k].y] = 0; // 残影问题
  328. Boss[k].x = rand() % 2; // 产生新Boss敌机
  329. Boss[k].y = rand() % Width;
  330. canvas[Boss[k].x][Boss[k].y] = 4;
  331. canvas[i][j] = 0; // 子弹消失
  332. Boss[k].life = 2;
  333. score++;score++; // 分数加2
  334. number++; // 销毁敌机数加1
  335. }
  336. }
  337. }
  338. // 子弹向上移动
  339. canvas[i][j] = 0;
  340. if (i > 0)
  341. canvas[i - 1][j] = 2;
  342. }
  343. }
  344. }
  345. static int speed = 0;
  346. if (speed < EnemyMoveSpeed)
  347. speed++;
  348. for (k = 0; k < EnemyNum; k++)
  349. {
  350. // 敌机撞到我机
  351. if ((position_x == enemy[k].x) && (position_y == enemy[k].y) || (position_x + 1 == enemy[k].x) && (position_y - 1 == enemy[k].y) || (position_x + 1 == enemy[k].x) && (position_y + 1 == enemy[k].y) || (position_x + 2 == enemy[k].x) && (position_y + 1 == enemy[k].y) || (position_x + 2 == enemy[k].x) && (position_y - 1 == enemy[k].y))
  352. {
  353. mciSendString("close bkmusic",NULL,0,NULL); // 先把前面一次的音乐关闭
  354. mciSendString("open D:\\plane\\explode.mp3 alias exmusic",NULL,0,NULL); // 打开音乐
  355. mciSendString("play exmusic",NULL,0,NULL); // 仅播放一次
  356. color(11);
  357. printf("\n游戏结束!\n");
  358. Sleep(3000);
  359. system("pause");
  360. exit(0);
  361. }
  362. // 敌机跑出显示屏幕
  363. if (enemy[k].x > High)
  364. {
  365. canvas[enemy[k].x][enemy[k].y] = 0;
  366. enemy[k].x = rand() % 2; // 产生新的敌机
  367. enemy[k].y = rand() % Width;
  368. canvas[enemy[k].x][enemy[k].y] = 3;
  369. score--; // 减分
  370. }
  371. if (speed == EnemyMoveSpeed)
  372. {
  373. // 敌机下落
  374. for (k = 0; k < EnemyNum; k++)
  375. {
  376. canvas[enemy[k].x][enemy[k].y] = 0;
  377. enemy[k].x++;
  378. speed = 0;
  379. canvas[enemy[k].x][enemy[k].y] = 3;
  380. }
  381. // Boss敌机下落
  382. for (k = 0; k < BossNum; k++)
  383. {
  384. canvas[Boss[k].x][Boss[k].y] = 0;
  385. Boss[k].x++;
  386. speed = 0;
  387. canvas[Boss[k].x][Boss[k].y] = 4;
  388. }
  389. }
  390. }
  391. for (k = 0; k < BossNum; k++)
  392. {
  393. // Boss敌机撞到我机
  394. if ((position_x == Boss[k].x) && (position_y == Boss[k].y) || (position_x + 1 == Boss[k].x) && (position_y - 1 == Boss[k].y) || (position_x + 1 == Boss[k].x) && (position_y + 1 == Boss[k].y) || (position_x + 2 == Boss[k].x) && (position_y + 1 == Boss[k].y) || (position_x + 2 == Boss[k].x) && (position_y - 1 == Boss[k].y))
  395. {
  396. mciSendString("close exmusic",NULL,0,NULL); // 先把前面一次的音乐关闭
  397. mciSendString("open D:\\plane\\explode.mp3 alias exmusic",NULL,0,NULL); // 打开音乐
  398. mciSendString("play exmusic",NULL,0,NULL); // 仅播放一次
  399. color(11);
  400. printf("\n游戏结束!\n");
  401. Sleep(3000);
  402. system("pause");
  403. exit(0);
  404. }
  405. // Boss敌机跑出显示屏幕
  406. if (Boss[k].x > High)
  407. {
  408. canvas[Boss[k].x][Boss[k].y] = 0;
  409. Boss[k].x = rand() % 2; // 产生新的Boss敌机
  410. Boss[k].y = rand() % Width;
  411. canvas[Boss[k].x][Boss[k].y] = 4;
  412. score--; // 减分
  413. }
  414. }
  415. }
  416. // 与用户输入有关的更新
  417. void updateWithInput()
  418. {
  419. char input;
  420. if (_kbhit()) // 判断是否有输入
  421. {
  422. input = _getch(); // 根据用户的不同输入来移动,不必输入回车
  423. if (input == 'a'&& position_y > 1 || input == 'A')
  424. {
  425. canvas[position_x][position_y] = 0;
  426. canvas[position_x + 1][position_y - 1] = 0;
  427. canvas[position_x + 1][position_y] = 0;
  428. canvas[position_x + 1][position_y + 1] = 0;
  429. position_y--; // 位置左移
  430. canvas[position_x][position_y] = 1;
  431. canvas[position_x + 1][position_y - 1] = 1;
  432. canvas[position_x + 1][position_y] = 1;
  433. canvas[position_x + 1][position_y + 1] = 1;
  434. }
  435. else if (input == 'd' && position_y < Width - 2 || input == 'D')
  436. {
  437. canvas[position_x][position_y] = 0;
  438. canvas[position_x + 1][position_y - 1] = 0;
  439. canvas[position_x + 1][position_y] = 0;
  440. canvas[position_x + 1][position_y + 1] = 0;
  441. position_y++; // 位置右移
  442. canvas[position_x][position_y] = 1;
  443. canvas[position_x + 1][position_y - 1] = 1;
  444. canvas[position_x + 1][position_y] = 1;
  445. canvas[position_x + 1][position_y + 1] = 1;
  446. }
  447. else if (input == 'w'&& position_x > 1 || input == 'W')
  448. {
  449. canvas[position_x][position_y] = 0;
  450. canvas[position_x + 1][position_y - 1] = 0;
  451. canvas[position_x + 1][position_y] = 0;
  452. canvas[position_x + 1][position_y + 1] = 0;
  453. position_x--; // 位置上移
  454. canvas[position_x][position_y] = 1;
  455. canvas[position_x + 1][position_y - 1] = 1;
  456. canvas[position_x + 1][position_y] = 1;
  457. canvas[position_x + 1][position_y + 1] = 1;
  458. }
  459. else if (input == 's'&& position_x < High - 3 || input == 'S')
  460. {
  461. canvas[position_x][position_y] = 0;
  462. canvas[position_x + 1][position_y - 1] = 0;
  463. canvas[position_x + 1][position_y] = 0;
  464. canvas[position_x + 1][position_y + 1] = 0;
  465. position_x++; // 位置下移
  466. canvas[position_x][position_y] = 1;
  467. canvas[position_x + 1][position_y - 1] = 1;
  468. canvas[position_x + 1][position_y] = 1;
  469. canvas[position_x + 1][position_y + 1] = 1;
  470. }
  471. else if (input == ' ') // 发射子弹
  472. {
  473. int left = position_y - BulletWidth;
  474. int right = position_y + BulletWidth;
  475. if (left < 0)
  476. left = 0;
  477. if (right > Width - 1)
  478. right = Width - 1;
  479. int k;
  480. for (k = left; k <= right; k++) // 发射闪弹
  481. canvas[position_x - 1][k] = 2; // 发射子弹的初始位置在飞机的正上方
  482. }
  483. else if (input == 'P' || input == 'p') // 按P暂停游戏
  484. system("pause");
  485. else if (input == 'Z' || input == 'z') // 按Z存档
  486. {
  487. FileWrite();
  488. system("pause");
  489. exit(0);
  490. }
  491. }
  492. }
  493. int main()
  494. {
  495. welcometogame();
  496. if (flag == 1)
  497. startup(); // 数据初始化
  498. else
  499. FileRead(); // 数据初始化
  500. while (1) // 游戏循环执行
  501. {
  502. show(); // 显示画面
  503. updateWithoutInput(); // 与用户输入无关的更新
  504. updateWithInput(); // 与用户输入有关的更新
  505. }
  506. return 0;
  507. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/358912
推荐阅读
相关标签
  

闽ICP备14008679号