看了知乎上的一个C语言做的打飞机游戏(控制台)​​https://zhuanlan.zhihu.com/p/24798125​

决定自己做一个C++版的。

先说一下原来游戏的思路。 

首先主函数: 先初始化,然后再一个循环里不断地

显示-->更新与用户无关数据-->用户输入、根据输入更新。

显示是通过一个二维数组canvas (画布)来实现的,通过一个二层循环来在画布上进行绘制(输出字符)

字符的形状代表是 飞机或子弹或者空气。

更新与用户无关数据是按照一个规律:敌机往下飞,子弹往上飞,这样更新的。

根据输入更新            是根据用户输入的'a' 'd'或空格 来设置自己的位置和发射子弹。


 

int main()
{
startup(); // 数据初始化
while (1) // 游戏循环执行
{
show(); // 显示画面
updateWithoutInput(); // 与用户输入无关的更新
updateWithInput(); // 与用户输入有关的更新
}
return 0;
}

下面具体地操作。

 

那么既然要用C++,飞机就可以做成一个基类了。

然后从飞机 派生出两个类 一个是自己,一个是敌机。

自己和敌机有什么不同? 在这里为了简化,敌机不发射子弹,只是简单地往下移动。 自己是可以发射子弹的。

class Plane
{
private:
int x;
int y;
int MoveSpeed;
public:
Plane() :x(0), y(0) {};
Plane(int x, int y) :x(x), y(y) {}
~Plane(){}
int getX() { return x; }
int getY() { return y; }
int getMoveSpeed(){ return MoveSpeed; }
void setX(int x) { this->x =x; }
void setY(int y) { this->y = y; }
void setMoveSpeed(int speed){ MoveSpeed = speed; }
};

class MyPlane : public Plane
{
private:
int BulletWidth;

public:
int getBulletWidth() { return BulletWidth; }
void setBulletWidth(int width) { this->BulletWidth = width; }

};
class EnemyPlane : public Plane
{

};

 

除了飞机,其他的基本根据原来的改写,因为图像的显示主要依靠画布,所以如果画布不改动的话,其余的基本改变不大。

改写时为了方便,我将原来的长函数分解成短函数,看起来更容易。

 

最后的代码:

 

main.cpp

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include"plane.h"
#include"updateFunction.h"

const int High = 15;// 游戏画面尺寸
const int Width = 25;
const int EnemyNum = 5;// 敌机个数

// 全局变量
MyPlane myPlane; // 飞机
EnemyPlane enemyPlane[EnemyNum]; // 敌机
int canvas[High+1][Width+1] = { 0 }; // 二维数组存储游戏画布中对应的元素
// 0为空格,1为飞机*,2为子弹|,3为敌机@
int score; // 得分

//光标移动到(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);
}

void startup() // 数据初始化
{
//下面的两行用于隐藏光标,防止乱闪
CONSOLE_CURSOR_INFO cursor_info = { 1,0 };
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);

//设自己置飞机位置
startupMyPlane();
//设置敌机位置
startupEnemyPlane();
score = 0;
}

void startupMyPlane()
{
myPlane.setX(High - 1);
myPlane.setY(Width - 2);
myPlane.setBulletWidth(0);
}
void startupEnemyPlane()
{
for (int k = 0; k < EnemyNum; k++)
{
enemyPlane[k].setX(rand() % 2);
enemyPlane[k].setY(rand() % Width);
enemyPlane[k].setMoveSpeed(20);
}
}

// 显示画面
void show()
{
gotoxy(0, 0); // 光标移动到原点位置,以下重画清屏
for (int i = 0; i < High; i++)
{
for (int j = 0; j < Width; j++)
{
if (canvas[i][j] == 0)
printf(" "); // 输出空格
else if (canvas[i][j] == 1)
printf("*"); // 输出飞机*
else if (canvas[i][j] == 2)
printf("|"); // 输出子弹|
else if (canvas[i][j] == 3)
printf("@"); // 输出飞机@
}
printf("\n");
}
printf("得分:%d\n", score);
Sleep(20);
}

// 与用户输入无关的更新
void updateWithoutInput()
{ //更新子弹位置
for (int i = 0; i < High; i++) {
for (int j = 0; j < Width; j++) {
if (canvas[i][j] == 2) {
updateBullet(i, j);
}
}
}
static int speed = 0;
if (speed < enemyPlane[0].getMoveSpeed())
speed++;
updatePlane(speed );
}


void updateBullet(int i,int j)
{
for (int k = 0; k < EnemyNum; k++) {
if ((i == enemyPlane[k].getX()) && (j == enemyPlane[k].getY())) // 子弹击中敌机
{
score++; // 分数加1
if (score % 5 == 0 && enemyPlane[k].getMoveSpeed() > 3) // 达到一定积分后,敌机变快
enemyPlane[k].setMoveSpeed(enemyPlane[k].getMoveSpeed() - 1);
if (score % 5 == 0) // 达到一定积分后,子弹变厉害
myPlane.setBulletWidth(myPlane.getBulletWidth() + 1);
canvas[enemyPlane[k].getX()][enemyPlane[k].getY()] = 0;
enemyPlane[k].setX(rand() % 2); // 产生新的飞机
enemyPlane[k].setY(rand() % Width);
canvas[enemyPlane[k].getX()][enemyPlane[k].getY()] = 3;
canvas[i][j] = 0; // 子弹消失
}
}
// 子弹向上移动
canvas[i][j] = 0;
if (i > 0)
canvas[i - 1][j] = 2;
}
void updatePlane(int& speed )
{
for (int k = 0; k < EnemyNum; k++)
{
if ((myPlane.getX() == enemyPlane[k].getX()) && (myPlane.getY() == enemyPlane[k].getY())) // 敌机撞到我机
{
printf("失败!\n");
Sleep(3000);
system("pause");
exit(0);
}

if (enemyPlane[k].getX() > High) // 敌机跑出显示屏幕
{
canvas[enemyPlane[k].getX()][enemyPlane[k].getY()] = 0;
enemyPlane[k].setX(rand() % 2); // 产生新的飞机
enemyPlane[k].setY(rand() % Width);
canvas[enemyPlane[k].getX()][enemyPlane[k].getY()] = 3;
score--; // 减分
}

if (speed == enemyPlane[0].getMoveSpeed())
{
// 敌机下落
for (k = 0; k < EnemyNum; k++)
{
canvas[enemyPlane[k].getX()][enemyPlane[k].getY()] = 0;
enemyPlane[k].setX(enemyPlane[k].getX() + 1);
speed = 0;
canvas[enemyPlane[k].getX()][enemyPlane[k].getY()] = 3;
}
}
}
}

void updateWithInput() // 与用户输入有关的更新
{
char input;
if (_kbhit()) // 判断是否有输入
{
input = _getch(); // 根据用户的不同输入来移动,不必输入回车
if (input == 'a' && myPlane.getX() > 0)
{
canvas[myPlane.getX()][myPlane.getY()] = 0;
myPlane.setY(myPlane.getY()-1); // 位置左移
canvas[myPlane.getX()][myPlane.getY()] = 1;
}
else if (input == 'd' && myPlane.getY() < Width - 1)
{
canvas[myPlane.getX()][myPlane.getY()] = 0;
myPlane.setY(myPlane.getY() +1); // 位置右移
canvas[myPlane.getX()][myPlane.getY()] = 1;
}
else if (input == 'w')
{
canvas[myPlane.getX()][myPlane.getY()] = 0;
myPlane.setX(myPlane.getX() - 1);; // 位置上移
canvas[myPlane.getX()][myPlane.getY()] = 1;
}
else if (input == 's')
{
canvas[myPlane.getX()][myPlane.getY()] = 0;
myPlane.setX(myPlane.getX() +1);; // 位置上移
canvas[myPlane.getX()][myPlane.getY()] = 1;
}
else if (input == ' ') // 发射子弹
{
int left = myPlane.getY() - myPlane.getBulletWidth() ;
int right = myPlane.getY() + myPlane.getBulletWidth();
if (left < 0)
left = 0;
if (right > Width - 1)
right = Width - 1;
int k;
for (k = left; k <= right; k++) // 发射闪弹
canvas[myPlane.getX() - 1][k] = 2; // 发射子弹的初始位置在飞机的正上方
}
}
}

int main()
{
startup(); // 数据初始化
while (1) // 游戏循环执行
{
show(); // 显示画面
updateWithoutInput(); // 与用户输入无关的更新
updateWithInput(); // 与用户输入有关的更新
}
return 0;
}

updateFunction.h 

#pragma once
void startupMyPlane();
void startupEnemyPlane();
void updateBullet(int i, int j);
void updatePlane(int& speed);

plane.h 

#pragma once

class Plane
{
private:
int x;
int y;
int MoveSpeed;
public:
Plane() :x(0), y(0) {};
Plane(int x, int y) :x(x), y(y) {}
~Plane(){}
int getX() { return x; }
int getY() { return y; }
int getMoveSpeed(){ return MoveSpeed; }
void setX(int x) { this->x =x; }
void setY(int y) { this->y = y; }
void setMoveSpeed(int speed){ MoveSpeed = speed; }
int condition;
};


class MyPlane : public Plane
{
private:
int BulletWidth;

public:
MyPlane(){ Plane(); condition = 1; };
MyPlane(int x, int y) :Plane(x, y) { condition = 1; }
~MyPlane() {}
int getBulletWidth() { return BulletWidth; }
void setBulletWidth(int width) { this->BulletWidth = width; }

};
class EnemyPlane : public Plane
{
public:
static int num;
public:
EnemyPlane() { Plane(); condition = 3; };
EnemyPlane(int x, int y) : Plane(x, y) { condition = 3; }
~EnemyPlane() {}

};