亲宝软件园·资讯

展开

C++飞机大战

1coder. 人气:0

前几天看大佬写了个神经网络训练AI玩飞机大战,我想,凭我现有知识能不能也写一个飞机大战,就进行了尝试,成果如下。

#include<iostream>
#include<ctime>
#include<stdlib.h>
#include<windows.h>
using namespace std;
const int mapx = 40, mapy = 35, cost = 2, prise = 5;   //cost: cost of bullet,   prise: prise of killing a enemy.
class plane
{
    public:
        void start();
    private:
        void reset();
        void get_enemy(int &y);
        void print() const;
        void update_print();
        char map[mapx][mapy];/*      plane model:      /=|=\           */
        int plane_y, plane_x, score, cont;
};

到此我们设计了飞机的模型(我水平不够 整个游戏就用一个类了- -,这个类其实是整个游戏的类 不是飞机类)关于变量cont的说明我放在后面了 接下来我写了一个初始化函数,为类内变量初始化。

void plane::reset()
{
    for(int i = 0; i < mapx; i++)
    {
        for(int j = 0; j < mapy; j++)
        {
            if(!i || !j || j == mapy - 1)
            {
                map[i][j] = '#';
            }
            else
                map[i][j] = ' ';
        }
    }
    plane_x = mapx - 1;
    plane_y = mapy/2 - 2;
    score = cont = 0;
    map[plane_x][plane_y] = '/';
    map[plane_x][plane_y + 1] = map[plane_x][plane_y + 3] = '=';
    map[plane_x][plane_y + 2] = '|';
    map[plane_x][plane_y + 4] = '\\';
}

然后我利用时间参数的随机数得到敌机的位置,这里其实有个问题,因为时间是按一定顺序均匀变化的,我们如果直接用时间作随机数种子的话,敌机的出现会非常均匀,因此我引入了一个cont变量,用来打乱我们均匀的时间参数的个位数。具体使用见后文。

void plane::get_enemy(int &y) const
{
    srand(int(time(0)));
    int n = rand();
    if(cont%2)
        n -= cont;
    else
        n += cont;
    y = n % (mapy - 2) + 1;
}

这个函数就是随机生成敌机的位置,cont在此就起到打乱随机生成数的个位数的目的,每更新一次,cont++,为防止cont过大,我规定cont==10时,就将cont = 0,使其能在1到9变化,影响个位数。

void plane::print() const
{
    system("cls");
    for(int i = 0; i < mapx; i++)
    {
        for(int j = 0; j < mapy; j++)
        {
            cout<<map[i][j];
        }
        cout<<endl;
    }
    cout<<"Score : "<<score<<'.'<<endl<<"Pay "<<cost<<" scores to send '+' and get "<<prise<<" scores by killing enemies."<<endl;
}

这里是一个打印的函数,不赘述。

void plane::update_print()
{
    for(int i = 1; i < mapx; i++)
    {
        for(int j = 1; j < mapy - 1; j++)
        {
            if(map[i][j] == 'M')
            {
                if(i == mapx - 1)
                    map[i][j] = ' ';
                else if(map[i + 1][j] == '+')
                {
                    map[i][j] = map[i+1][j] = ' ';
                    score += prise;
                }
            }
            else if(map[i][j] == '+')
            {
                map[i][j] = ' ';
                if(i != 1)
                    map[i-1][j] = '+';
            }
        }
    }
    for(int i = mapx - 2; i > 0; i--)
    {
        for(int j = 1; j < mapy - 1; j++)
        {
            if(map[i][j] == 'M')
            {
                if(i != mapx - 1)
                    if(map[i+1][j] == '+')
                    {
                        map[i + 1][j] = ' ';
                        score += prise;
                    }
                    else
                        map[i + 1][j] = 'M';
                map[i][j] = ' ';
            }
        }
    }
    int enemy_y;
    get_enemy(enemy_y);
    if(map[1][enemy_y] == '+')
    {
        map[1][enemy_y] = ' ';
        score += prise;
    }
    else
        map[1][enemy_y] = 'M';
        
    for(int i = 0; i < 5; i++)
    {
        if(map[plane_x][plane_y + i] != 'M')
            map[plane_x][plane_y + i] = ' ';
    }
    bool jleft, jright, jup, jdown;
    jleft = jright = jup = jdown = false;

    if(GetAsyncKeyState(VK_LEFT) & 0x8000)
        if(plane_y != 1)
            jleft = true;
    if(GetAsyncKeyState(VK_RIGHT) & 0x8000)
        if(plane_y + 4 != mapy - 2)
            jright = true;
    if(GetAsyncKeyState(VK_UP) & 0x8000)
        if(plane_x != 1)
            jup = true;
    if(GetAsyncKeyState(VK_DOWN) & 0x8000)
        if(plane_x != mapx - 1)
            jdown = true;
    if(!(jleft && jright))
    {
        if(jleft)
            plane_y--;
        if(jright)
            plane_y++;
    }
    if(!(jup && jdown))
    {
        if(jup)
            plane_x--;
        if(jdown)
            plane_x++;
    }
    if(GetAsyncKeyState(VK_SPACE) & 0x8000)
        {
            score -= cost;
            if(map[plane_x - 1][plane_y + 2] == ' ')
                map[plane_x - 1][plane_y + 2] = '+';
            else if(map[plane_x - 1][plane_y + 2] == 'M')
            {
                map[plane_x - 1][plane_y + 2] = ' ';
                score += prise;
            }
        }

    if(map[plane_x][plane_y]=='M'||map[plane_x][plane_y+1]=='M'||
    map[plane_x][plane_y+2]=='M'||map[plane_x][plane_y+3]=='M'||map[plane_x][plane_y+4]=='M')
    {
        system("cls");
        for(int i = 0; i < mapx; i++)
        {
            cout<<"GAME OVER."<<endl;
        }
        cout<<"Your final scores are "<<score<<'.'<<endl;
        system("pause");
        exit(1);
    }
    map[plane_x][plane_y] = '/';
    map[plane_x][plane_y + 1] = map[plane_x][plane_y + 3] = '=';
    map[plane_x][plane_y + 2] = '|';
    map[plane_x][plane_y + 4] = '\\';
    cont++;
    if(cont == 10)
            cont = 0;
    print();
}

这个函数我其实感觉自己写的太大了,应该进一步分装,这确实是个不足之处。具体操作就是每轮对飞机的移动,还有子弹和敌机的前进以及判断子弹是否达到敌机和我们的飞机是否撞到敌机。其中我用到了windows.h文件中的GetAsyncKeyState函数,其参数为键盘某个键的VK值(可查表),返回一个16个位的数(因操作系统不同而不同,我的计算机是返回16位)。若该键在上次判断到此次判断之间被按下过,则0号位为1,反之为0;若该键正在被按下,则15号位为1,反之为0.将返回值与0x8000作“与&”操作,则第一位的数字决定了我们&操作的结果。因为XXXX XXXX XXXX XXXX & 1000 0000 0000 0000 == X000 0000 0000 0000.从而操控我们的飞机。

void plane::start()
{
    reset();
    while(1)
    {
        Sleep(50);
        update_print();
    }
}

开始函数,用以从类外部访问类内的private函数,并且组织起循环。
然后 用主函数运行即可。

int main()
{
    plane plane_game;
    plane_game.start();
    return 0;
}

效果如下:

加载全部内容

相关教程
猜你喜欢
用户评论