本文实例为大家分享了C语言实现飞机大战的具体代码,供大家参考,具体内容如下
作业要求:
1.游戏当中出现多类型敌人
2.游戏中能进行存档和读档
3.玩家控制的飞机由多字符组成
4.游戏过程中没有出现BUG
5.游戏显示制作者信息
6.游戏当中带有BGM
7.其他个性化设定
成效:
代码:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<windows.h>
#include<mmsystem.h> // 导入声音头文件
#pragma comment(lib,"Winmm.lib") // 导入声音头文件库
#define High 20 // 游戏画面尺寸
#define Width 30
#define EnemyNum 5 // 敌机个数
#define BossNum 2 // Boss机个数
int flag; // 飞机状态
int color(int c); // 更改文字颜色
void explation(); // 游戏提示
void show(); // 显示游戏界面
void endgame(); // 游戏结束
void startup(); // 数据初始化
void FileRead(); // 读档
// 全局变量
int position_x, position_y; // 飞机位置
struct enemy{
int x;
int y;
int life;
}Boss[BossNum], enemy[EnemyNum]; // 敌机位置
int canvas[High][Width] = {0}; // 二维数组存储游戏画布中对应的元素
// 0为空格,1为飞机8,2为子弹o,3为敌机0 , 4为Boss敌机A
int score; // 得分
int number; // 销毁敌机数
int BulletWidth; // 子弹宽度
int EnemyMoveSpeed; // 敌机移动速度
// 光标移动到(x,y)位置
void gotoxy(int x, int y)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle, pos);
}
// 更改文字颜色
int color(int c)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);
return 0;
}
// 隐藏光标
void HideCursor()
{
CONSOLE_CURSOR_INFO cursor_info = {1,0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
// 开始界面
void welcometogame()
{
int n, i, j = 1;
system("cls");
color(15);
gotoxy(33, 1);
printf("飞机大战 Plane War");
color(56);
for (i = 3; i <= 26; i++) // 输出上下边框
{
for (j = 6; j <= 80; j++) // 输出左右边框
{
gotoxy(j, i);
if (i == 3 || i == 26)
printf(" ");
else if (j == 6 || j == 80)
printf(" ");
}
}
color(14);
gotoxy(38, 6);
printf("基本操作\n");
gotoxy(19, 8);
printf("空格:发射子弹 W:前进 A:左移 D:右移 S:后退\n");
gotoxy(34, 11);
printf("1.开始游戏(play)");
gotoxy(34, 13);
printf("2.游戏规则(rule)");
gotoxy(34, 15);
printf("3.读取存档(read)");
gotoxy(34, 17);
printf("4.退出游戏(quit)");
color(15);
gotoxy(22, 24);
printf("游戏制作人:李歆灵 学号:420240320 联系方式:13530656670");
color(14);
gotoxy(33, 20);
printf("请选择 1 2 3 4: ");
color(14);
scanf("%d", &n); // 输入选项
switch (n)
{
case 1:
flag = 1;
system("cls");
break;
case 2:
explation(); // 游戏规则
break;
case 3:
system("cls"); // 读档
break;
case 4:
gotoxy(30, 28);
exit(0); // 退出游戏
break;
default:
color(9);
gotoxy(33, 22);
printf("请输入1-4之间的数");
_getch(); // 输入任意键
system("cls"); // 清屏
welcometogame();
}
}
// 游戏规则
void explation()
{
int i, j = 1;
system("cls");
color(15);
gotoxy(30, 1);
printf("游戏规则 Rules of game");
color(56);
for (i = 3; i <= 26; i++) // 输出上下边框
{
for (j = 6; j <= 80; j++) // 输出左右边框
{
gotoxy(j, i);
if (i == 3 || i == 26)
printf(" ");
else if (j == 6 || j == 80)
printf(" ");
}
}
color(14);
gotoxy(10, 6);
printf("1. W,A,S,D 分别是控制飞机的移动,空格发射子弹");
gotoxy(10, 9);
printf("2. O是普通敌机(需一发子弹),A是Boss敌机(需两发子弹)");
gotoxy(10, 12);
printf("3. 击败普通敌机可获得1分,击败Boss敌机可获得2分");
gotoxy(10, 15);
printf("4. 敌机进入下边界减1分");
gotoxy(10, 18);
printf("5. 飞机碰到敌机会坠落");
gotoxy(10, 21);
printf("6. 按Z存档,按P暂停游戏");
color(15);
gotoxy(25, 23);
printf("/*****按任意键返回主页面*****/");
_getch(); // 按任意键返回主界面
system("cls");
welcometogame();
}
// 数据初始化
void startup()
{
mciSendString("open D:\\plane\\game.mp3 alias bkmusic ",NULL,0,NULL); // 打开背景音乐
mciSendString("play bkmusic",NULL,0,NULL); // 循环播放
position_x = High / 2;
position_y = Width / 2;
canvas[position_x][position_y] = 3;
canvas[position_x + 1][position_y - 1] = 3;
canvas[position_x + 1][position_y] = 3;
canvas[position_x + 1][position_y + 1] = 3;
int k;
for (k = 0; k < EnemyNum; k++)
{
enemy[k].x = rand() % 2;
enemy[k].y = rand() % Width;
canvas[enemy[k].x][enemy[k].y] = 3;
}
for (k = 0; k < BossNum; k++)
{
Boss[k].x = rand() % 2;
Boss[k].y = rand() % Width;
canvas[Boss[k].x][Boss[k].y] = 4;
Boss[k].life = 2;
}
int score = 0; // 成绩
int number = 0; // 销毁敌机数
BulletWidth = 0;
EnemyMoveSpeed = 30;
HideCursor(); // 光标
}
// 存档代码
void FileWrite()
{
FILE *fp; // 文件指针
fp = fopen("D:\\game.data", "w"); // 打开文件 "w": write写入文件
int i, j;
for (i = 0; i < EnemyNum; i++)
{
fwrite(&enemy[i], sizeof(struct enemy), 1, fp);
}
for (j = 0; j < BossNum; j++)
{
fwrite(&Boss[j], sizeof(struct enemy), 1, fp);
}
fwrite(&position_x, sizeof(int), 1, fp);
fwrite(&position_y, sizeof(int), 1, fp);
fwrite(&score, sizeof(int), 1, fp);
fwrite(&number, sizeof(int), 1, fp);
fwrite(&BulletWidth, sizeof(int), 1, fp);
fwrite(&EnemyMoveSpeed, sizeof(int), 1, fp);
fclose(fp); // 关闭文件
printf("\n保存成功\n");
}
// 读档代码
void FileRead()
{
FILE *fp; // 文件指针
fp = fopen("D:\\game.data", "r"); // 打开文件 "r": read读取文件
mciSendString("open D:\\plane\\game.mp3 alias bkmusic ",NULL,0,NULL); // 打开背景音乐
mciSendString("play bkmusic",NULL,0,NULL); // 循环播放
if(fp == NULL)
startup();
else
{
int i, j;
for (i = 0; i < EnemyNum; i++)
{
fread(&enemy[i], sizeof(struct enemy), 1, fp);
}
for (j = 0; j < BossNum; j++)
{
fread(&Boss[j], sizeof(struct enemy), 1, fp);
}
fread(&position_x, sizeof(int), 1, fp);
fread(&position_y, sizeof(int), 1, fp);
fread(&score, sizeof(int), 1, fp);
fread(&number, sizeof(int), 1, fp);
fread(&BulletWidth, sizeof(int), 1, fp);
fread(&EnemyMoveSpeed, sizeof(int), 1, fp);
}
fclose(fp); // 关闭文件
canvas[position_x][position_y] = 1;
canvas[position_x + 1][position_y - 1] = 1;
canvas[position_x + 1][position_y] = 1;
canvas[position_x + 1][position_y + 1] = 1;
int k;
for (k = 0; k < EnemyNum; k++)
{
canvas[enemy[k].x][enemy[k].y] = 3;
}
for (k = 0; k < BossNum; k++)
{
canvas[Boss[k].x][Boss[k].y] = 4;
Boss[k].life = 2;
}
HideCursor();
}
// 显示画面
void show()
{
color(112);
gotoxy(0, 0); // 光标移动到原点位置,以下重画清屏
int i, j;
for (i = 0; i < High; i++)
{
for (j = 0; j < Width; j++)
{
if ((j == Width - 1) || (i == High - 1) || (j == 0) || (i == 0))
printf("#"); // 打印边界#
else if (canvas[i][j] == 1)
printf("8"); // 输出飞机8
else if (canvas[i][j] == 2)
printf("o"); // 输出子弹o
else if (canvas[i][j] == 3)
printf("O"); // 输出敌机O
else if (canvas[i][j] == 4)
printf("A"); // 输出Boss敌机A
else
printf(" ");
}
printf("\n");
}
color(14);
printf("\n");
printf("游戏得分: %d\n", score);
printf("销毁敌机: %d\n\n", number);
Sleep(20);
}
// 与用户输入无关的更新
void updateWithoutInput()
{
int i, j, k;
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[k].x) && (j == enemy[k].y)) // 子弹击中敌机
{
mciSendString("close gemusic",NULL,0,NULL); // 先把前面一次的音乐关闭
mciSendString("open D:\\plane\\gotEnemy.mp3 alias gemusic ",NULL,0,NULL); // 打开音乐
mciSendString("play gemusic",NULL,0,NULL); // 仅播放一次
score++; // 分数加1
number++; // 销毁敌机数加1
if (number % 6 == 0 && EnemyMoveSpeed > 3) // 达到一定积分后,敌机变快
EnemyMoveSpeed--;
if (number % 12 == 0) // 达到一定积分后,子弹变厉害
BulletWidth++;
canvas[enemy[k].x][enemy[k].y] = 0; // 残影问题
enemy[k].x = rand() % 2; // 产生新的敌机
enemy[k].y = rand() % Width;
canvas[enemy[k].x][enemy[k].y] = 3;
canvas[i][j] = 0; // 子弹消失
}
}
for (k = 0; k < BossNum; k++)
{
if ((i == Boss[k].x) && (j == Boss[k].y)) // 子弹击中Boss敌机
{
mciSendString("close gemusic",NULL,0,NULL); // 先把前面一次的音乐关闭
mciSendString("open D:\\plane\\gotEnemy.mp3 alias gemusic ",NULL,0,NULL); // 打开音乐
mciSendString("play gemusic",NULL,0,NULL); // 仅播放一次
Boss[k].life--; // Boss敌机生命值减1
if (Boss[k].life == 0)
{
canvas[Boss[k].x][Boss[k].y] = 0; // 残影问题
Boss[k].x = rand() % 2; // 产生新Boss敌机
Boss[k].y = rand() % Width;
canvas[Boss[k].x][Boss[k].y] = 4;
canvas[i][j] = 0; // 子弹消失
Boss[k].life = 2;
score++;score++; // 分数加2
number++; // 销毁敌机数加1
}
}
}
// 子弹向上移动
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[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))
{
mciSendString("close bkmusic",NULL,0,NULL); // 先把前面一次的音乐关闭
mciSendString("open D:\\plane\\explode.mp3 alias exmusic",NULL,0,NULL); // 打开音乐
mciSendString("play exmusic",NULL,0,NULL); // 仅播放一次
color(11);
printf("\n游戏结束!\n");
Sleep(3000);
system("pause");
exit(0);
}
// 敌机跑出显示屏幕
if (enemy[k].x > High)
{
canvas[enemy[k].x][enemy[k].y] = 0;
enemy[k].x = rand() % 2; // 产生新的敌机
enemy[k].y = rand() % Width;
canvas[enemy[k].x][enemy[k].y] = 3;
score--; // 减分
}
if (speed == EnemyMoveSpeed)
{
// 敌机下落
for (k = 0; k < EnemyNum; k++)
{
canvas[enemy[k].x][enemy[k].y] = 0;
enemy[k].x++;
speed = 0;
canvas[enemy[k].x][enemy[k].y] = 3;
}
// Boss敌机下落
for (k = 0; k < BossNum; k++)
{
canvas[Boss[k].x][Boss[k].y] = 0;
Boss[k].x++;
speed = 0;
canvas[Boss[k].x][Boss[k].y] = 4;
}
}
}
for (k = 0; k < BossNum; k++)
{
// Boss敌机撞到我机
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))
{
mciSendString("close exmusic",NULL,0,NULL); // 先把前面一次的音乐关闭
mciSendString("open D:\\plane\\explode.mp3 alias exmusic",NULL,0,NULL); // 打开音乐
mciSendString("play exmusic",NULL,0,NULL); // 仅播放一次
color(11);
printf("\n游戏结束!\n");
Sleep(3000);
system("pause");
exit(0);
}
// Boss敌机跑出显示屏幕
if (Boss[k].x > High)
{
canvas[Boss[k].x][Boss[k].y] = 0;
Boss[k].x = rand() % 2; // 产生新的Boss敌机
Boss[k].y = rand() % Width;
canvas[Boss[k].x][Boss[k].y] = 4;
score--; // 减分
}
}
}
// 与用户输入有关的更新
void updateWithInput()
{
char input;
if (_kbhit()) // 判断是否有输入
{
input = _getch(); // 根据用户的不同输入来移动,不必输入回车
if (input == 'a'&& position_y > 1 || input == 'A')
{
canvas[position_x][position_y] = 0;
canvas[position_x + 1][position_y - 1] = 0;
canvas[position_x + 1][position_y] = 0;
canvas[position_x + 1][position_y + 1] = 0;
position_y--; // 位置左移
canvas[position_x][position_y] = 1;
canvas[position_x + 1][position_y - 1] = 1;
canvas[position_x + 1][position_y] = 1;
canvas[position_x + 1][position_y + 1] = 1;
}
else if (input == 'd' && position_y < Width - 2 || input == 'D')
{
canvas[position_x][position_y] = 0;
canvas[position_x + 1][position_y - 1] = 0;
canvas[position_x + 1][position_y] = 0;
canvas[position_x + 1][position_y + 1] = 0;
position_y++; // 位置右移
canvas[position_x][position_y] = 1;
canvas[position_x + 1][position_y - 1] = 1;
canvas[position_x + 1][position_y] = 1;
canvas[position_x + 1][position_y + 1] = 1;
}
else if (input == 'w'&& position_x > 1 || input == 'W')
{
canvas[position_x][position_y] = 0;
canvas[position_x + 1][position_y - 1] = 0;
canvas[position_x + 1][position_y] = 0;
canvas[position_x + 1][position_y + 1] = 0;
position_x--; // 位置上移
canvas[position_x][position_y] = 1;
canvas[position_x + 1][position_y - 1] = 1;
canvas[position_x + 1][position_y] = 1;
canvas[position_x + 1][position_y + 1] = 1;
}
else if (input == 's'&& position_x < High - 3 || input == 'S')
{
canvas[position_x][position_y] = 0;
canvas[position_x + 1][position_y - 1] = 0;
canvas[position_x + 1][position_y] = 0;
canvas[position_x + 1][position_y + 1] = 0;
position_x++; // 位置下移
canvas[position_x][position_y] = 1;
canvas[position_x + 1][position_y - 1] = 1;
canvas[position_x + 1][position_y] = 1;
canvas[position_x + 1][position_y + 1] = 1;
}
else if (input == ' ') // 发射子弹
{
int left = position_y - BulletWidth;
int right = position_y + BulletWidth;
if (left < 0)
left = 0;
if (right > Width - 1)
right = Width - 1;
int k;
for (k = left; k <= right; k++) // 发射闪弹
canvas[position_x - 1][k] = 2; // 发射子弹的初始位置在飞机的正上方
}
else if (input == 'P' || input == 'p') // 按P暂停游戏
system("pause");
else if (input == 'Z' || input == 'z') // 按Z存档
{
FileWrite();
system("pause");
exit(0);
}
}
}
int main()
{
welcometogame();
if (flag == 1)
startup(); // 数据初始化
else
FileRead(); // 数据初始化
while (1) // 游戏循环执行
{
show(); // 显示画面
updateWithoutInput(); // 与用户输入无关的更新
updateWithInput(); // 与用户输入有关的更新
}
return 0;
}