飞机大战C++

Posted two_orion

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了飞机大战C++相关的知识,希望对你有一定的参考价值。

为期两周的实训结束了,写一篇飞机大战纪念一下,因为之前对于编程可能也没有太深入系统的学习,这个实训应该标志着编程学习的由浅入深,也代表着我们学习正式开始。(所以说之前一年我们学了点什么。。。)
在拿到我们最后的要求时我其实还是有些犹豫,毕竟之前刚做过链表,写起贪吃蛇来相比飞机大战可能会比较容易,但后来又想到老师会给我们一些提示,于是我理所当然的飘了。。。。认为写出来的飞机大战应该会是这样的:
但是在提示给出来之后是这样的:
。。。。。。。。。。。
只能说菜给的太多了,喝成了这个样子

话不多说,还是脚踏实地一步一步写的好。

一、游戏要求:

按照一定的规则排列的“*”模拟玩家飞机,向下移动的“@”符号表示敌机,由下至上间断显示的“|”模拟子弹,界面下方显示飞机的生命值,的分情况等等。
每当玩家飞机撞上敌机生命值减1,程序自动生成另一架位置随机的飞机继续游戏,直到生命值为0游戏结束。
通过wasd键控制飞机移动,通过空格键发射激光子弹,要求:采用多文件结构实现。

二、实验设计

程序应该主要涉及到两个模块,分别为主模块mainfighter 和子模块fighter,子模块主要包含初始化功能函数init(),绘制游戏界面函数drawpitcure(),电脑操作子界面与敌机函数pcoperate(),玩家控制飞机函数operatefighter()。
主模块只有mainfighter这一个文件,以下为框架:

void main(){
init();
while(1);{
drawpicture();
pcoperate();
operatefighter();
}
system("pause");
}

相应的功能在具体的函数中实现。

三 函数调用思路

绘制游戏界面函数drawpicture()
外层循环变量x控制行输出,内层循环变量y控目列输出,内层循环语句不断判断当前坐标与玩家飞机、敌机、激光束子弹位置是否重叠,前坐标值(x,y)为(fighter. x, fighter. y)时向屏幕输出玩家飞机“*”,当前坐标值为(enemyenemy_ y)时向屏幕输出敌机“@”,当前坐标值为(bullet x, bullet y)时向屏幕输出激光子弹否则输出空格,从而实现了在屏幕上看到玩家飞机、敌机、激光束子弹的效果。

此时实现的游戏界面上的玩家飞机、敌机、激光子弹等是静止的,要想实现动态效需要不断改变玩家飞机、敌机、激光東子弹坐标值实现动态效果。

3)电脑操作子弹与敌机函数pcOperate0

pcOperate()函数相对简单,调用flatBaullet)函数实现激光束子弹向上漂浮效果,调用enemyfighter()实现敌机移动,被击落后随机生成敌机的视觉效果等。
eneyfighter(函数实现敌机移动、被击落后随机生成放机的视觉效果等)
4控制飞机operateFighter()

该西数主要实现玩家飞机移动、发射激光束子弹,通过按W5. 2小建控朝元家飞机上下左右移动,通过按下空格键发射激光子弹。

判断当前按键改变相应坐标值实现飞机移动、发射激光束子弹功能。当按下”键时表示向.上移动,玩家飞机纵向坐标减1横向坐标不变,即fighter X–;当按下“d”键时表不向右移动,玩家飞机横向坐标加1纵向坐标不变,即fighter y++。当按下空格键时表示发射激光束子弹,则在飞机正上方生成子弹,即将激光束子弹坐标值为(ighter_ x- 1, fighter y)。
五、编码实现
将游戏画面尺寸、玩家飞机位置、激光束子弹位置、敌机位置等定义为全局变量:

//全局变量
int height,width;//游戏画面尺寸
int fighter_x,fighter_y;//飞机位置
int bullet_x,bullet_y;//子弹位置
int enemy_x;enemy_y;//敌机位置
string difficulty//难度设置显示条

init 函数要实现对上述全局变量赋值的功能,一般将玩家飞机显示在画面中间的位置,敌机显示在第一行,飞机坐标(fighter_x,fighter_y)设置为(height/2,width/2),敌机坐标为(enemy_x,enemy_y),设置为(0,rand()%(width-5)+2)。
drawpicture函数实现
通过双层函数循环控制光标移动,当坐标值(x,y)满足特定的条件时向屏幕输出玩家飞机,敌机,光束子弹。

cout << setfill('#') << setw(width + 6) << "#" << endl;
	for (int x = 0; x < height; x++)
	{//外层循环
		for (int y = 0; y < width + 1; y++)
		{
			if (y == 0)
				cout << "#";//设置左边界

			else if (y == width)
			{//设置右边界
				if (x == fighter_x)
					cout << "#";
				else if (x == fighter_x + 1)
					cout << setfill(' ') << "#";
				else if (x == fighter_x + 2)
					cout << setfill(' ') << "#";
				else cout << setfill(' ') << setw(6) << "#";
			}

			else if ((x == fighter_x) && (y == fighter_y))
				cout << setfill(' ') << setw(6) << "*   ";
			else if ((x == fighter_x + 1) && (y == fighter_y))
				cout << setfill('*') << setw(6) << " ";
			else if ((x == fighter_x + 2) && (y == fighter_y))
				cout << setfill(' ') << setw(6) << "* *  ";//输出飞机
			else if ((x == bullet_x) && (y == bullet_y))
				cout << "|";//输出子弹
			else if (x == enemy_x && y == enemy_y)
				cout << "@";//输出敌机位置
			else cout << " ";
		}
		cout << endl;
	}
	cout << setfill('#') << setw(width + 6) << "#" << endl;
	cout << "难度:" << difficulty << endl;
	cout << "生命:" << fighter << endl;
	cout << "得分:" << score << endl;

operatefighter编码实现
调用floatbullet 函数处理子弹移动,调用enemyfighter函数实现生成敌机、移动等等。
bullet_x–实现子弹移动
要想设置难度层次,就要设法控制敌机向下移动的速度。因此设置静态变量speed,每执行几次,敌机就移动一次。

static int speed = 10;
difficulty = "简单";
	if (score > 5) {
		speed++;
		difficulty = "普通";
	}
	if (score > 15) {
		speed++;
		difficulty = "困难";
	}
	if (speed < 10) {
		speed += 2;
	}
	else {
		enemy_x++;
		speed = 0;

最后,是击中敌机。在enemyfighter中增加判断,当子弹和敌机位置相同时就击中敌机,并增加变量score记录得分,击中敌机后+1;敌机被击中后会消失,然后在随机位置出现

if((bullet_x==enemy_x)&&(bullet_y==enemy_y))//子弹击中敌机
{
score++;
enemy_x=-1;
enemy_y=rand()%(width-5)+2;
bullet_x=-2;//子弹无效

思路大致如下,但是在操作过程中,由于飞机体型较大,在击中敌机过程中无法准确被击毁,此外还存在着敌机在移动过程的瞬间子弹击中敌机无效的情况,因此更改判断条件,使得飞机任何位置碰到敌机都会被击毁;子弹能够准确的击毁敌机。

if (((bullet_x == enemy_x) && (bullet_y == enemy_y)) || ((bullet_x + 1 == enemy_x) &&
		(bullet_y == enemy_y)) || ((bullet_x - 1 == enemy_x) && (bullet_y == enemy_y)))
	{
		score++;
		enemy_x = -1;//产生新的飞机
		enemy_y = rand() % (width - 5) + 3;//rand()函数生成随机数,但因为一般生成的随机数较大,因此做取余操作使其能在规定的宽度内生成
		bullet_x = -2;//子弹无效
	}
	if ((enemy_x == fighter_x) && ((enemy_y == fighter_y) ||
		(enemy_y == fighter_y + 1) || (enemy_y == fighter_y + 3) ||
		(enemy_y == fighter_y + 4)) || ((enemy_x == fighter_x) &&
			(enemy_y == fighter_y + 2)))
	{
		fighter--;
		fighter_x = rand() % (height - 5) + 2;
		fighter_y = rand() % (width - 5) + 2;

		enemy_x = -1;
		enemy_y = rand() % width;
		lose();
	}
	if (enemy_x > height) {//如果敌机飞出屏幕则重新生成一架
		score--;
		enemy_x = -1;
		enemy_y = rand() % width;
		lose();
	}

目前屏幕的闪烁严重,还存在光标,因此需要一个函数实现清屏效果,这里直接调用了windows.库函数来实现

void zeroXy(int x, int y) {//实现函数清屏
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle, pos);

}
void hidecursor() {//隐藏光标
	CONSOLE_CURSOR_INFO consor_info = { 1,0 };//第二个值为0隐藏光标
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consor_info);
}

最后就是要时刻判断游戏的输赢情况,当生命值为0时或者得分小于0时则游戏失败,再定义一个函数来实现

void lose() {
	if (fighter < 0 || score < 0) {
		cout << endl;
		cout << "**********************你输了!*********************" << endl;
		system("pause");
		exit(0);
	}
}

至此飞机大战全部内容就完成了,生成代码如下(包含一个头文件,一个子模块和一个主模块)

//fighter.h文件
#ifndef _fighter_h
#define _fighter_h
void drawPicture();
void init();
void OperateFighter();
void pcOperate();
void floatBullet();
void enemyFighter();
void zeroXy(int x, int y);
void hidecursor();
void lose();
#endif

//fighter.cpp文件
#include<iostream>
#include<conio.h>
#include<Windows.h>
#include<iomanip>
#include"fighter.h"
using namespace std;

int height = 20;
long width = 30;//定义游戏界面长和宽
int fighter_x, fighter_y;
int bullet_x, bullet_y;
int enemy_x, enemy_y;
int score;
int fighter;
string difficulty;

void drawPicture() {//x控制行输出,y控制列输出
	zeroXy(0, 0);
	cout << setfill('#') << setw(width + 6) << "#" << endl;
	for (int x = 0; x < height; x++)
	{
		for (int y = 0; y < width + 1; y++)
		{
			if (y == 0)
				cout << "#";

			else if (y == width)
			{
				if (x == fighter_x)
					cout << "#";
				else if (x == fighter_x + 1)
					cout << setfill(' ') << "#";
				else if (x == fighter_x + 2)
					cout << setfill(' ') << "#";
				else cout << setfill(' ') << setw(6) << "#";
			}

			else if ((x == fighter_x) && (y == fighter_y))
				cout << setfill(' ') << setw(6) << "*   ";
			else if ((x == fighter_x + 1) && (y == fighter_y))
				cout << setfill('*') << setw(6) << " ";
			else if ((x == fighter_x + 2) && (y == fighter_y))
				cout << setfill(' ') << setw(6) << "* *  ";
			else if ((x == bullet_x) && (y == bullet_y))
				cout << "|";
			else if (x == enemy_x && y == enemy_y)
				cout << "@";
			else cout << " ";
		}
		cout << endl;
	}
	cout << setfill('#') << setw(width + 6) << "#" << endl;
	cout << "难度:" << difficulty << endl;
	cout << "生命:" << fighter << endl;
	cout << "得分:" << score << endl;
}

void init() {
	fighter_x = height / 2;//定义飞机的位置
	fighter_y = width / 2;

	enemy_x = 0;
	enemy_y = fighter_y;	//随机定义敌机位置

	bullet_x = -2;//定义子弹位置
	bullet_y = fighter_y;

	score = 0;//得分数
	fighter = 3;//飞机生命数

	hidecursor();
}
void OperateFighter() {
	char input;
	if (_kbhit()) {//检查是否是否有键盘输入,有返回非0,无则返回0
		input = _getch();//根据用户不同的输入来移动
		if (input == 'a') {
			if (fighter_y > 1)
				fighter_y--;//位置左移
		}
		else if (input == 'd') {
			if (fighter_y < width - 1)
				fighter_y++;//位置右移
		}
		else if (input == 'w') {
			if (fighter_x > 0)
				fighter_x--;//位置上移
		}
		else if (input == 's') {
			if (fighter_x < height)
				fighter_x++;//位置下移
		}
		if (input == ' ') {
			bullet_x = fighter_x - 1;
			bullet_y = fighter_y + 2;
		}
	}

}
void pcOperate() {//调用函数模拟人操作飞机战斗
	floatBullet();//调用floatBullet函数控制子弹移动
	enemyFighter();//控制敌机移动速度

}
void floatBullet() {//控制子弹移动
	if (bullet_x > -1)//判断子弹是否在屏幕内
		bullet_x--;//子弹上移
}
void enemyFighter() {
	//用来控制敌机向下移动的速度。每隔十次循环就移动一次敌机
	static int speed = 0;
	difficulty = "简单";
	if (score > 5) {
		speed++;
		difficulty = "普通";
	}
	if (score > 15) {
		speed++;
		difficulty = "困难";
	}
	if (speed < 10) {
		speed += 2;
	}
	else {
		enemy_x++;
		speed = 0;
	}

	//击中敌机后增加判断,并增加变量score记录游戏得分。敌机被击中后会先消失,然后重新在随机位置出现。
	if (((bullet_x == enemy_x) && (bullet_y == enemy_y)) || ((bullet_x + 1 == enemy_x) &&
		(bullet_y == enemy_y)) || ((bullet_x - 1 == enemy_x) && (bullet_y == enemy_y)))
	{
		score++;
		enemy_x = -1;//产生新的飞机
		enemy_y = rand() % (width - 5) + 3;//rand()函数生成随机数,但因为一般生成的随机数较大,因此做取余操作使其能在规定的宽度内生成
		bullet_x = -2;//子弹无效
	}
	if ((enemy_x == fighter_x) 基于C++ Qt的飞机大战

基于C++ Qt的飞机大战

基于C++ Qt的飞机大战

硬核教程,如何摆脱黑白框编程,1小时学会用c++做一个飞机大战

2022.3 C++植物大战僵尸项目总结

飞机大战原生代码版