坦克膽戰

#include<iostream>
#include<stdlib.h>
#include<tchar.h>
#include<Windows.h>
#include<time.h>
#include<conio.h>
using namespace std;

HANDLE Mutex = CreateMutex(NULL, FALSE, NULL);//互斥對象

int GameOver = 0;
int level = 0;
int map[23][23];
//坦克種類,Normal爲玩家坦克
#define Normal 0
#define Red 1
#define Blue 2
#define Green 3
//方向的宏定義
#define Up 0
#define Down 1
#define Left 2
#define Right 3
//地圖標記的宏定義
#define Empty 0
#define Player 1
#define PlayerBullet 2
#define EnemyBullet 3
#define Enemy 4

int Kill;
int KillRed;
int KillGreen;
int EnemyExist;

void SetPos(int i, int j)//設定光標位置
{
    COORD pos = { i, j };
    HANDLE Out = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(Out, pos);
}

void HideCurSor(void)//隱藏光標
{
    CONSOLE_CURSOR_INFO info = { 1, 0 };
    HANDLE Out = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorInfo(Out, &info);
}

int sharp[4][12] =
{
    { 0, 1, 1, 0, 1, 1, 1, 2, 2, 0, 2, 2 },
    { 0, 0, 0, 2, 1, 0, 1, 1, 1, 2, 2, 1 },
    { 0, 1, 0, 2, 1, 0, 1, 1, 2, 1, 2, 2 },
    { 0, 0, 0, 1, 1, 1, 1, 2, 2, 0, 2, 1 },
};//此數組用來保存坦克各個方向的形狀信息

DWORD WINAPI Bulletfly(LPVOID lpParameter);//子彈函數申明
void Updata();//更新界面信息函數申明

class Tank//坦克類
{
private:
    int Direction;//方向
    int hotpoint[2];//活動點
    int Speed;//速度
    int FirePower;//火力
public:
    Tank(int dir, int hot1, int hot2, int typ, int spe, int firepow)//構造函數
    {
        Direction = dir;
        hotpoint[0] = hot1;
        hotpoint[1] = hot2;
        Type = typ;
        Speed = spe;
        FirePower = firepow;
    }
    int Type;//坦克的種類(詳見宏定義)
    int ID;//坦克在MAP中的標記(詳見宏定義)
    int FireEnable;//是否可以開火
    int Life;//生命值
    void Running();//運行函數
    int Judge(int x, int y, int ID);//判斷是否可以繪製坦克
    void DrawTank();//重繪坦克
    void Redraw();//擦除坦克
    int GetSpeed()//獲取速度
    {
        return Speed;
    }
    int GetFire()//獲取火力
    {
        return FirePower;
    }
    int GetDirection()//獲取方向
    {
        return Direction;
    }
    int GetHotX()//獲取活動點座標
    {
        return hotpoint[0];
    }
    int GetHotY()
    {
        return hotpoint[1];
    }
    void IncreaseFire()//火力+
    {
        FirePower++;
    }
    void IncreaseSpeed()//速度+
    {
        Speed++;
    }
    void ChangeDirection(int newD)//改變方向
    {
        Direction = newD;
    }
    void ChangePos(int x, int y)//改變活動點
    {
        hotpoint[0] = x;
        hotpoint[1] = y;
    }
};

Tank player(Right, 0, 0, Normal, 1, 1);//玩家
Tank enemy(Left, 20, 0, Red, 1, 1);//敵人

void Tank::DrawTank()//繪製坦克
{
    int i;
    int nx, ny;
    if (Type == Red)
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
    else if (Type == Blue)
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);
    else if (Type == Green)
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
    else if (Type == Normal)
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    for (i = 0; i<6; i++)
    {
        nx = hotpoint[0] + sharp[Direction][i * 2];
        ny = hotpoint[1] + sharp[Direction][i * 2 + 1];
        SetPos((ny + 1) * 2, nx + 1);//利用sharp數組相對於點x,y繪製形狀
        map[nx][ny] = ID;
        cout << "■";
    }
}

void Tank::Redraw()//擦除坦克,原理同上
{
    int i;
    int nx, ny;
    for (i = 0; i<6; i++)
    {
        nx = hotpoint[0] + sharp[Direction][i * 2];
        ny = hotpoint[1] + sharp[Direction][i * 2 + 1];
        map[nx][ny] = Empty;
        SetPos((ny + 1) * 2, nx + 1);
        cout << " ";
    }
}

int Tank::Judge(int x, int y, int dir)//判斷當前是否可以繪製坦克
{
    int i;
    int nx, ny;
    for (i = 0; i<6; i++)
    {
        nx = x + sharp[dir][i * 2];
        ny = y + sharp[dir][i * 2 + 1];
        if (nx<0 || nx >= 23 || ny<0 || ny >= 23 || map[nx][ny] != Empty)//不能繪製,返回1
            return 1;
    }
    return 0;
}


void Tank::Running()//坦克運行函數
{
    int newD;
    //坦克的運行
    while (1)
    {
        if (Life == 0)
        {
            EnemyExist = 0;//敵人不存在
            return;
        }
        if (GameOver == 1)
            return;
        if (FireEnable == 1 && GameOver == 0)//如果可以開火
        {
            WaitForSingleObject(Mutex, INFINITE);//線程擁有互斥對象
            FireEnable = 0;//設爲不可開火
            HANDLE bullet = CreateThread(NULL, 0, Bulletfly, &ID, 0, NULL);//創建子彈線程
            CloseHandle(bullet);
            ReleaseMutex(Mutex);//釋放互斥對象
            Sleep(100);
        }
        WaitForSingleObject(Mutex, INFINITE);//線程擁有互斥對象
        srand((int)time(0));
        newD = rand() % 4;

        if (newD == Up)//隨機出新的方向並重新繪製坦克
        {
            Redraw();
            if (Judge(hotpoint[0] - 1, hotpoint[1], newD) == 0)
            {
                hotpoint[0]--;
                Direction = newD;
            }
            else
            {
                if (Judge(hotpoint[0], hotpoint[1], newD) == 0)
                    Direction = newD;
            }
        }
        else if (newD == Down)
        {
            Redraw();
            if (Judge(hotpoint[0] + 1, hotpoint[1], newD) == 0)
            {
                hotpoint[0]++;
                Direction = newD;
            }
            else
            {
                if (Judge(hotpoint[0], hotpoint[1], newD) == 0)
                    Direction = newD;
            }
        }
        else if (newD == Left)
        {
            Redraw();
            if (Judge(hotpoint[0], hotpoint[1] - 1, newD) == 0)
            {
                hotpoint[1]--;
                Direction = newD;
            }
            else
            {
                if (Judge(hotpoint[0], hotpoint[1], newD) == 0)
                    Direction = newD;
            }
        }
        else if (newD == Right)
        {
            Redraw();
            if (Judge(hotpoint[0], hotpoint[1] + 1, newD) == 0)
            {
                hotpoint[1]++;
                Direction = newD;
            }
            else
            {
                if (Judge(hotpoint[0], hotpoint[1], newD) == 0)
                    Direction = newD;
            }
        }
        if (GameOver == 0 && Life != 0)
            DrawTank();
        ReleaseMutex(Mutex);//釋放互斥對象
        Sleep(500 - 80 * Speed);
    }
}

/*********************子彈線程函數*******************/
DWORD WINAPI Bulletfly(LPVOID lpParameter)
{
    int *ID = (int *)lpParameter;//ID用來獲取發射子彈坦克的ID
    int Pos[2];//子彈活動點
    int direction;
    int Speed;
    int type;
    int hit = 0;//擊中標記
    int oldx, oldy;//舊活動點
    int flag = 0;//子彈是否有移動的標記
    if (*ID == Player)//如果是玩家坦克
    {
        type = PlayerBullet;
        direction = player.GetDirection();
        Speed = player.GetFire();
        Pos[0] = player.GetHotX();
        Pos[1] = player.GetHotY();
    }
    else if (*ID == Enemy)//如果是敵人坦克
    {
        type = EnemyBullet;
        direction = enemy.GetDirection();
        Speed = enemy.GetFire();
        Pos[0] = enemy.GetHotX();
        Pos[1] = enemy.GetHotY();
    }
    if (direction == Up)//根據坦克的位置和方向確定子彈的初始座標
    {
        Pos[0]--;
        Pos[1]++;
    }
    else if (direction == Down)
    {
        Pos[0] += 3;
        Pos[1]++;
    }
    else if (direction == Left)
    {
        Pos[0]++;
        Pos[1]--;
    }
    else if (direction == Right)
    {
        Pos[0]++;
        Pos[1] += 3;
    }
    //子彈的運行
    while (1)
    {
        WaitForSingleObject(Mutex, INFINITE);//這個不再註釋了。。。。。
        if (flag == 1 && hit != 1)//擦除原位置
        {
            map[oldx][oldy] = Empty;
            SetPos((oldy + 1) * 2, oldx + 1);
            cout << " ";
        }
        if (GameOver == 1)
            return 0;
        if (hit == 1 || Pos[0]<0 || Pos[0]>22 || Pos[1]<0 || Pos[1]>22)//如果擊中
        {
            ReleaseMutex(Mutex);
            Sleep(500);
            if (type == PlayerBullet)
                player.FireEnable = 1;
            else if (type = EnemyBullet)
                enemy.FireEnable = 1;
            break;
        }
        switch (map[Pos[0]][Pos[1]])//子彈經過的MAP的標記
        {

        case Empty://如果是空位置就繪製子彈
            map[Pos[0]][Pos[1]] = type;
            SetPos((Pos[1] + 1) * 2, Pos[0] + 1);
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
            cout << "■";
            break;
        case Player://如果是玩家位置
            if (type != PlayerBullet)
            {
                player.Life--;//生命減少
                if (player.Life <= 0)
                    GameOver = 1;
            }
            Updata();
            hit = 1;
            break;
        case Enemy://如果是敵人位置
            if (type != PlayerBullet)
                hit = 1;
            else
            {
                hit = 1;
                Kill++;
                if (Kill % 20 == 0 && player.Life<5)//擊殺數++
                    player.Life++;
                if (enemy.Type == Red)//如果擊殺紅坦克
                {
                    KillRed++;
                    if (KillRed % 10 == 0 && player.GetFire()<5)
                        player.IncreaseFire();
                }
                if (enemy.Type == Green)///如果擊殺綠坦克
                {
                    KillGreen++;
                    if (KillGreen % 10 == 0 && player.GetSpeed()<5)
                        player.IncreaseSpeed();
                }
                enemy.Redraw();//擦除敵人
                enemy.Life = 0;//敵人死亡
            }
            Updata();
            break;
        }
        oldx = Pos[0];
        oldy = Pos[1];
        if (direction == Up)//子彈移動
            Pos[0]--;
        else if (direction == Down)
            Pos[0]++;
        else if (direction == Left)
            Pos[1]--;
        else if (direction == Right)
            Pos[1]++;
        ReleaseMutex(Mutex);
        flag = 1;
        Sleep(60 - 10 * Speed);
    }
    return 0;
}


/*************************敵人線程函數***************************/
DWORD WINAPI TankRuning(LPVOID lpParameter)
{
    Sleep(400);
    int Pos;
    int Start[2];//敵人起始地址
    int typ;
    int fire;
    int spe;
    while (1)
    {
        if (GameOver == 1)
            return 0;
        srand((int)time(0));//隨機出敵人起始地址
        Pos = rand() % 4;
        if (Pos == 0)
        {
            Start[0] = 2;
            Start[0] = 2;
        }
        else if (Pos == 1)
        {
            Start[0] = 2;
            Start[1] = 18;
        }
        else if (Pos == 2)
        {
            Start[0] = 18;
            Start[1] = 2;
        }
        else if (Pos == 3)
        {
            Start[0] = 18;
            Start[1] = 18;
        }
        if (player.Judge(Start[0], Start[1], Down) == 0)
            break;
    }
    WaitForSingleObject(Mutex, INFINITE);
    srand((int)time(0));
    typ = rand() % 3 + 1;//隨機出敵人的種類
    if (typ == Blue)
    {
        spe = 1 + level;
        fire = 1 + level;
    }
    else if (typ == Red)
    {
        spe = 1 + level;
        fire = 3 + level;
    }
    else if (typ == Green)
    {
        spe = 3 + level;
        fire = 1 + level;
    }
    enemy = Tank(Down, Start[0], Start[1], typ, spe, fire);//重新生成敵人坦克
    enemy.ID = Enemy;
    enemy.Life = 1;
    enemy.FireEnable = 1;
    ReleaseMutex(Mutex);
    enemy.Running();
    return 0;
}


void Init()//初始化函數
{
    Kill = 0;
    KillRed = 0;
    KillGreen = 0;
    player = Tank(Left, 0, 0, Normal, 1, 1);
    enemy = Tank(Left, 0, 0, Red, 1, 1);
    player.Life = 2;
    player.FireEnable = 1;
    enemy.Life = 0;
    enemy.FireEnable = 1;
    player.ID = Player;
    enemy.ID = Enemy;
    EnemyExist = 0;
}

void Updata()//更新界面信息
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    int i;
    SetPos(53, 0);
    cout << "生命值:";
    SetPos(53, 1);
    for (i = 0; i<5; i++)
    {
        if (i<player.Life)
            cout << "■";
        else
            cout << " ";
    }
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
    SetPos(53, 3);
    cout << "移動速度:";
    SetPos(53, 4);
    for (i = 0; i<5; i++)
    {
        if (i<player.GetSpeed())
            cout << "■";
        else
            cout << " ";
    }
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
    SetPos(53, 5);
    cout << "火力:";
    SetPos(53, 6);
    for (i = 0; i<5; i++)
    {
        if (i<player.GetFire())
            cout << "■";
        else
            cout << " ";
    }
    SetPos(53, 8);
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    cout << "殺敵數:" << Kill;
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
    SetPos(53, 9);
    cout << "殺死紅坦克:" << KillRed;
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
    SetPos(53, 10);
    cout << "殺死綠坦克:" << KillGreen;

}
void DrawMap()//畫界面
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    system("cls");
    int i;
    for (i = 0; i<25; i++)
    {
        SetPos(i * 2, 0);
        cout << "■";
    }
    for (i = 1; i<25; i++)
    {
        SetPos(0, i);
        cout << "■";
        SetPos(24 * 2, i);
        cout << "■";
    }
    for (i = 0; i<25; i++)
    {
        SetPos(i * 2, 24);
        cout << "■";
    }

    Updata();

}

void Welcome()//歡迎界面
{
    int x;
    system("cls");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
    SetPos(10, 5);
    cout << "■■■■■■■■■■■■■■■■■■■■■■■■";
    SetPos(10, 6);
    cout << "■        坦克大戰控制檯版                    ■";
    SetPos(10, 7);
    cout << "■■■■■■■■■■■■■■■■■■■■■■■■";
    SetPos(10, 8);
    cout << "■       方向鍵移動,空格鍵射擊               ■";
    SetPos(10, 9);
    cout << "■       敵人分爲3種,藍色爲普通敵人          ■";
    SetPos(10, 10);
    cout << "■     紅色敵人高射速,綠色敵人高機動性       ■";
    SetPos(10, 11);
    cout << "■ 每殺死10個紅坦克,玩家射速提高(最高五級)  ■";
    SetPos(10, 12);
    cout << "■ 每殺死10個綠坦克,玩家移動性提高(最高五級)■";
    SetPos(10, 13);
    cout << "■   每殺死20個坦克,玩家生命+1(最高五格)   ■";
    SetPos(10, 14);
    cout << "■■■■■■■■■■■■■■■■■■■■■■■■";
    SetPos(10, 15);
    cout << "■       (想學習加我qq752632564)            ■";
    SetPos(10, 16);
    cout << "■           按1-3選擇難度                    ■";
    SetPos(10, 17);
    cout << "■■■■■■■■■■■■■■■■■■■■■■■■";
    while (1)
    {
        x = _getch();
        if (x <= '3'&&x >= '1')
            break;
    }
    level = x - '0' - 1;
}

int _tmain(int argc, TCHAR* argv[]) {
    Init();
    HideCurSor();
    Welcome();
    DrawMap();
    HANDLE temp;
    int newD;
    player.DrawTank();
    while (GameOver == 0)
    {
        if (GetAsyncKeyState(VK_UP))//按鍵上
        {
            WaitForSingleObject(Mutex, INFINITE);
            newD = Up;
            player.Redraw();
            if (player.Judge(player.GetHotX() - 1, player.GetHotY(), newD) == 0)//移動玩家坦克,原理和敵人函數一樣
            {
                player.ChangePos(player.GetHotX() - 1, player.GetHotY());
                player.ChangeDirection(newD);
            }
            else
            {
                if (player.Judge(player.GetHotX(), player.GetHotY(), newD) == 0)
                    player.ChangeDirection(newD);
            }
            if (GameOver == 0)
                player.DrawTank();
            ReleaseMutex(Mutex);
            Sleep(200 - player.GetSpeed() * 20);//按鍵延遲,決定玩家坦克的速度
        }
        else if (GetAsyncKeyState(VK_DOWN))//按鍵下,同上
        {
            WaitForSingleObject(Mutex, INFINITE);
            newD = Down;
            player.Redraw();
            if (player.Judge(player.GetHotX() + 1, player.GetHotY(), newD) == 0)
            {
                player.ChangePos(player.GetHotX() + 1, player.GetHotY());
                player.ChangeDirection(newD);
            }
            else
            {
                if (player.Judge(player.GetHotX(), player.GetHotY(), newD) == 0)
                    player.ChangeDirection(newD);
            }
            if (GameOver == 0)
                player.DrawTank();
            ReleaseMutex(Mutex);
            Sleep(200 - player.GetSpeed() * 20);
        }
        else if (GetAsyncKeyState(VK_RIGHT))//按鍵右,同上
        {
            WaitForSingleObject(Mutex, INFINITE);
            newD = Right;
            player.Redraw();
            if (player.Judge(player.GetHotX(), player.GetHotY() + 1, newD) == 0)
            {
                player.ChangePos(player.GetHotX(), player.GetHotY() + 1);
                player.ChangeDirection(newD);
            }
            else
            {
                if (player.Judge(player.GetHotX(), player.GetHotY(), newD) == 0)
                    player.ChangeDirection(newD);
            }
            if (GameOver == 0)
                player.DrawTank();
            ReleaseMutex(Mutex);
            Sleep(200 - player.GetSpeed() * 20);
        }
        else if (GetAsyncKeyState(VK_LEFT))//按鍵左,同上
        {
            WaitForSingleObject(Mutex, INFINITE);
            newD = Left;
            player.Redraw();
            if (player.Judge(player.GetHotX(), player.GetHotY() - 1, newD) == 0)
            {
                player.ChangePos(player.GetHotX(), player.GetHotY() - 1);
                player.ChangeDirection(newD);
            }
            else
            {
                if (player.Judge(player.GetHotX(), player.GetHotY(), newD) == 0)
                    player.ChangeDirection(newD);
            }
            if (GameOver == 0)
                player.DrawTank();
            ReleaseMutex(Mutex);
            Sleep(110 - player.GetSpeed() * 10);
        }
        else if (GetAsyncKeyState(VK_SPACE))//按鍵空格,發射子彈
        {
            WaitForSingleObject(Mutex, INFINITE);
            if (player.FireEnable == 1)//如果可以發射
            {
                HANDLE bullet = CreateThread(NULL, 0, Bulletfly, &(player.ID), 0, NULL);//創建玩家子彈進程
                CloseHandle(bullet);
                player.FireEnable = 0;
            }
            ReleaseMutex(Mutex);
        }

if (EnemyExist == 0 && GameOver == 0)//如果敵人不存在生成新敵人
        {
            WaitForSingleObject(Mutex, INFINITE);
            EnemyExist = 1;
            temp = CreateThread(NULL, 0, TankRuning, NULL, 0, NULL);//創建敵人線程
            CloseHandle(temp);
            ReleaseMutex(Mutex);
        }
    }
    system("cls");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);
    SetPos(20, 10);
    cout << "遊戲結束" << endl;
    SetPos(20, 11); 
    cout << "殺敵數:" << Kill;
    SetPos(20, 12);
    cout << "殺死紅坦克" << KillRed;
    SetPos(20, 13);
    cout << "殺死綠坦克" << KillGreen << endl;
    return 0;
}
發佈了47 篇原創文章 · 獲贊 24 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章