C++實現(xiàn)飛機大戰(zhàn)游戲
本文實例為大家分享了C++實現(xiàn)飛機大戰(zhàn)游戲的具體代碼,供大家參考,具體內(nèi)容如下
代碼是單線程執(zhí)行,無界面,(博主下一步學習QT之后融入)還有待改進。
先放張界面圖:
話不多說 上代碼(注釋很清楚,不懂可和博主交流)
main.cpp:
#include<iostream> #include<ctime> #include<string> #include"game.h" using namespace std; int main() { ?? ?srand((unsigned int)time(NULL));//隨機時間種子 ?? ?HideCursor();//隱藏光標 ?? ?Game game; ?? ?int a=drawMenu(); ?? ?if (a == 2) ?? ?{ ?? ??? ?game.rank = 20; ?? ?} ?? ?system("cls"); ?? ?drawPlaying(); ?? ?game.Playing(); }
game.h:
#pragma once #include<iostream> #include<Windows.h>//定義控制臺應用程序的入口點 using namespace std; //定義敵人結(jié)構(gòu) 其中最后面Frame代表結(jié)構(gòu)體類型 若不加typedef代表定義的結(jié)構(gòu)體變量 typedef struct Frame { ?? ?COORD position[2]; ?? ?// ?COORD 是Windows API中定義的一種結(jié)構(gòu),表示一個字符在控制臺屏幕上的坐標。 ?? ?// 其定義為: ?? ?// typedef struct _COORD { ?? ?// ? ? ? ? SHORT X;? ?? ?// ? ? ? ? SHORT Y; ?? ?// ? ? ? } COORD; ?? ?int flag; }Frame; class Game { public: ?? ?COORD position[10]; ?? ?COORD bullet[10];//子彈坐標 ?? ?Frame enemy[8];//敵人數(shù)量 ?? ?int score; ?? ?int rank;//級別,難度 ?? ?int rankf;//等級標志 ?? ?string title; ?? ?int flag_rank;//等級標志 ?? ?//構(gòu)造函數(shù) ?? ?Game(); ?? ?//初始化所有 ?//設定位置 ?? ?void initPlane(); ?? ?void initBullet(); ?? ?void initEnemy(); ?? ?//填充所有 ?--畫出形狀和消失的形狀 ?? ?void drawPlane(); ?? ?void drawPlaneToNull(); ?? ?void drawBullet(); ?? ?void drawBulletToNull(); ?? ?void drawEnemy(); ?? ?void drawEnemyToNull(); ?? ?//執(zhí)行某一個操作 ?? ?void Playing();//游戲主循環(huán) ?? ?void planeMove(char x);//飛機移動 ?? ?void judgePlane();//判斷飛機是否與敵機重疊 ?? ?void GameOver();//游戲失敗 ?? ?void Pause();// 該成員函數(shù)用來使得游戲暫停 ?? ?void Shoot();//發(fā)射子彈 ?? ?void bulletMove();//子彈移動 ?? ?void drawThisBulletToNull(COORD c);//畫出失效子彈 ?? ?void judgeEnemy();//判斷子彈是否擊中敵機 ?? ?void drawThisEnemyToNull(Frame f);?? ?//擊敗的敵機清空 ?? ?void enemyMove();//敵機移動 ?? ?void printScore();//輸出分數(shù) }; //主菜單 int drawMenu(); //隱藏光標 void HideCursor(); void SetPos(int i, int j);//設置光標 COORD random(COORD a, COORD b);//產(chǎn)生隨機敵機位置 void drawFrame(COORD a, COORD ?b, char row, char col);//畫出敵機 //把第y行,[x1, x2) 之間的坐標填充為 ch void drawRow(int y, int x1, int x2, char ch); //把第x列,[y1, y2] 之間的坐標填充為 ch void drawCol(int x, int y1, int y2, char ch); // 繪制游戲界面 void drawPlaying(); void drawFrame(Frame frame, char row, char col);//畫墜毀后的戰(zhàn)機 // 該函數(shù)用來判斷戰(zhàn)機的某一部分是否與敵機有接觸 bool ?judgeCoordInFrame(Frame frame, COORD spot); void drawRow(COORD a, COORD b, char ch);
game.cpp:
#include"game.h" #include<Windows.h> #include<conio.h> Game::Game() { ?? ?// 調(diào)用類成員函數(shù)來進行初始化 ?? ?initPlane(); ?? ?initBullet(); ?? ?initEnemy(); ?? ?// 初始化四個int型數(shù)據(jù)成員,采用賦值的方式進行初始化 ?? ?// string類型的數(shù)據(jù)成員title沒有進行初始化,因為: ?? ?// string本身就是一個標準庫類類型,它的類定義中設置了默認構(gòu)造函數(shù), ?? ?// 這些默認構(gòu)造函數(shù)會將對象初始化為合理的默認狀態(tài), ?? ?// ?string的默認構(gòu)造函數(shù)會產(chǎn)生空字符串,相當于"" 。 ?? ?this->score = 0; ?? ?rank = 25; ?? ?rankf = 25; ?? ?flag_rank = 0; } void Game::initPlane() { ?? ?COORD centren; ?? ?centren.X = 39; ?? ?centren.Y = 22; ?? ?position[0].X = position[5].X = position[7].X = position[9].X = centren.X; ?? ?position[1].X = centren.X - 2; ?? ?position[2].X = position[6].X = centren.X - 1; ?? ?position[3].X = position[8].X = centren.X + 1; ?? ?position[4].X = centren.X + 2; ?? ?for (int i = 0; i <= 4; i++) ?? ?{ ?? ??? ?position[i].Y = centren.Y; ?? ?} ?? ?for (int i = 6; i <= 8; i++) ?? ?{ ?? ??? ?position[i].Y = centren.Y + 1; ?? ?} ?? ?position[5].Y = centren.Y - 1; ?? ?position[9].Y = centren.Y - 2; ?? ??? ? ?? ?// 這個函數(shù)體類的代碼其實就是為了初始化戰(zhàn)機的十個部分的位置,戰(zhàn)機的組成如下所示: ?? ?? ?// ? ? ? ? ? ? ? ? ? | ? ? ? 5? ?? ?//?? ??? ??? ??? ? ? ? | ? ? ? 9 ? ? ?? ?//?? ??? ??? ??? ? ? ***** ? 12034 ?? ?//?? ??? ??? ??? ? ? ?*** ? ? 678 ?? ?// ? 第一排5個0的坐標依次對應了position[1]position[2]position[0]position[3]position[4] ?? ?// ? 第二排三個0的坐標依次對應了position[6]position[7]position[8] ?? ?// ? 兩排0上面的兩|的坐標從上往下依次對應了position[5]position[9] } void Game::drawPlane() { ?? ?for (int i = 0; i < 9; i++) ?? ?{ ?? ??? ?SetPos(position[i].X,position[i].Y); ?? ??? ?if (i != 5) ?? ??? ?{ ?? ??? ??? ?cout << "*"; ?? ??? ?} ?? ??? ?else if (i == 5) ?? ??? ?{ ?? ??? ??? ?cout << "|"; ?? ??? ?} ?? ?} } // 這個成員函數(shù)通過將戰(zhàn)機的每個坐標處輸出" "來代替"0"和"|", // 來達到將戰(zhàn)機消除的目的。 void Game::drawPlaneToNull() { ?? ?for (int i = 0; i < 9; i++) ?? ?{ ?? ??? ?SetPos(position[i].X, position[i].Y); ?? ??? ?cout << " "; ?? ?} } // 該成員函數(shù)用來初始化子彈, // 即將每個子彈的Y坐標初始化為30(bullet[i].Y = 30)來表示子彈處于失效狀態(tài) void Game::initBullet() { ?? ?for (int i = 0; i < 10; i++) ?? ?{ ?? ??? ?bullet[i].Y = 30; ?? ?}?? ? } // 該成員函數(shù)用來畫出子彈 // 首先檢查每顆子彈的有效性,如果子彈有效,則定位到該子彈的坐標處,輸出 "^",表示該子彈, // 如果子彈是無效的,則不繪制 void Game::drawBullet() { ?? ?for (int i = 0; i < 10; i++) ?? ?{ ?? ??? ?if (bullet[i].Y != 30) ?? ??? ?{ ?? ??? ??? ?SetPos(bullet[i].X,bullet[i].Y); ?? ??? ??? ?cout << "^"; ?? ??? ?} ?? ?} } //子彈失效 void Game::drawBulletToNull() { ?? ?for (int i = 0; i < 10; i++) ?? ??? ?if (bullet[i].Y != 30) ?? ??? ?{ ?? ??? ??? ?SetPos(bullet[i].X, bullet[i].Y + 1); ?? ??? ??? ?cout << " "; ?? ??? ?} } // 這個函數(shù)用來初始敵機的位置, // 屏幕當中只能同時存在八架敵機, // 且每架敵機用如下結(jié)構(gòu)體Frame來表示,如下所示: // ? ? typedef struct Frame // ? ? ? ?{ //?? ? ? ? ?COORD position[2]; // ? ? ??? ?int flag; // ? ? ? ?}Frame; COORD random(COORD a, COORD b) { ?? ?int x = rand() % (a.X - b.X) + a.X; ?? ?int y = rand() % (a.Y - b.Y) + a.Y; ?? ?COORD c = { x,y }; ?? ?return c; } void Game::initEnemy() { ?? ?COORD a = { 1, 1 }; ?? ?COORD b = { 45, 15 }; ?? ?for (int i = 0; i < 8; i++) ?? ?{ ?? ??? ?enemy[i].position[0] = random(a, b); ?? ??? ?// ?random(a, b)是調(diào)用了一個重載的函數(shù),它表示在坐標a、b之間的矩形框 ?? ??? ?// ?內(nèi)隨機生成一個坐標值,并將該坐標值作為敵機的左上角的坐標。 ?? ??? ?// enemy[i].position[0]中是一個Frame結(jié)構(gòu)體類型的變量,存放了敵機i的左上角的坐標。 ?? ??? ?enemy[i].position[1].X = enemy[i].position[0].X + 3; ?? ??? ?enemy[i].position[1].Y = enemy[i].position[0].Y + 2; ?? ??? ?// enemy[i].position[1]也中是一個Frame結(jié)構(gòu)體類型的變量,存放了敵機i的右下角的坐標。 ?? ?} } // 接下來要根據(jù)敵機的左上角坐標和右下角坐標畫出敵機, // 顯然,敵機的外形如下所示: // ? -- // ?| ?| // ? -- void Game::drawEnemy() { ?? ?for (int i = 0; i < 8; i++) ?? ?{ ?? ??? ?drawFrame(enemy[i].position[0], enemy[i].position[1], '-', '|'); ?? ?}?? ? } // 將敵機消除,通過輸出空白的方式 void Game::drawEnemyToNull() { ?? ?for (int i = 0; i < 8; i++) ?? ?{ ?? ??? ?drawFrame(enemy[i].position[0], enemy[i].position[1], ' ', ' '); ?? ?} } //隱藏光標 void HideCursor() { ?? ?CONSOLE_CURSOR_INFO cursor_info = { 1,0 };//第二個值0表示隱藏光標 ?? ?SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); } void SetPos(int i, int j)//設置坐標點位(光標) { ?? ?HANDLE hout; ?? ?COORD coord; ?? ?coord.X = i; ?? ?coord.Y = j; ?? ?hout = GetStdHandle(STD_OUTPUT_HANDLE); ?? ?SetConsoleCursorPosition(hout, coord); } //左上角坐標、右下角坐標、用row填充行、用col填充列 void drawFrame(COORD a, COORD ?b, char row, char col) { ?? ?drawRow(a.Y, a.X + 1, b.X - 1, row); ?? ?drawRow(b.Y, a.X + 1, b.X - 1, row); ?? ?drawCol(a.X, a.Y + 1, b.Y - 1, col); ?? ?drawCol(b.X, a.Y + 1, b.Y - 1, col); } //把第y行,[x1, x2) 之間的坐標填充為 ch void drawRow(int y, int x1, int x2, char ch) { ?? ?SetPos(x1, y); ?? ?for (int i = 0; i <= (x2 - x1); i++) ?? ?{ ?? ??? ?cout << ch; ?? ?} } //把第x列,[y1, y2] 之間的坐標填充為 ch void drawCol(int x, int y1, int y2, char ch) { ?? ?int y = y1; ?? ?while (y != y2 + 1) ?? ?{ ?? ??? ?SetPos(x, y); ?? ??? ?cout << ch; ?? ??? ?y++; ?? ?} } //主菜單繪制 int drawMenu() { ?? ?SetPos(30,1); ?? ?cout << "飛 機 大 戰(zhàn)"; ?? ?drawRow(3, 0, 79, '-'); ?? ?drawRow(5, 0, 79, '-'); ?? ?SetPos(28, 4); ?? ?cout << "w 和 s選擇,k確定"; ?? ?int j = 11; ?? ?SetPos(12, j); ?? ?cout << ">>"; ?? ?SetPos(15, 11); ?? ?cout << "1. 簡單的敵人"; ?? ?SetPos(15, 13); ?? ?cout << "2. 冷酷的敵人"; ?? ?drawRow(20, 0, 79, '-'); ?? ?SetPos(47, 11); ?? ?cout << "簡單的敵人:"; ?? ?SetPos(47, 13); ?? ?cout << "簡單敵人有著較慢的移動速度。"; ?? ?SetPos(30, 21); ?? ?cout << "copy right@風兮木蕭"; ?? ?drawRow(22, 0, 79, '-'); ?? ?while (true) ?? ?{ ?? ??? ?if (_kbhit()) ?? ??? ?{ ?? ??? ??? ?char x = _getch(); ?? ??? ??? ?switch (x) ?? ??? ??? ?{ ?? ??? ??? ?case'w': ?? ??? ??? ?{ ?? ??? ??? ??? ?if (j == 13) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?SetPos(12, j); ?? ??? ??? ??? ??? ?cout << " ?"; ?? ??? ??? ??? ??? ?j = 11; ?? ??? ??? ??? ??? ?SetPos(12, j); ?? ??? ??? ??? ??? ?cout << ">>"; ?? ??? ??? ??? ??? ?SetPos(51, 13); ?? ??? ??? ??? ??? ?cout << " "; ?? ??? ??? ??? ??? ?SetPos(47, 11); ?? ??? ??? ??? ??? ?cout << "簡單的敵人:"; ?? ??? ??? ??? ??? ?SetPos(51, 13); ?? ??? ??? ??? ??? ?cout << "簡單敵人有著較慢的移動速度,比較容易對付"; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?break; ?? ??? ??? ?} ?? ??? ??? ?case's': ?? ??? ??? ?{ ?? ??? ??? ??? ?if (j == 11) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?SetPos(12, j); ?? ??? ??? ??? ??? ?cout << " "; ?? ??? ??? ??? ??? ?j = 13; ?? ??? ??? ??? ??? ?SetPos(12, j); ?? ??? ??? ??? ??? ?cout << ">>"; ?? ??? ??? ??? ??? ?SetPos(51, 13); ?? ??? ??? ??? ??? ?cout << " ? ? ? ? ? ? ? ? ? "; ?? ??? ??? ??? ??? ?SetPos(47, 11); ?? ??? ??? ??? ??? ?cout << "冷酷的敵人:"; ?? ??? ??? ??? ??? ?SetPos(51, 13); ?? ??? ??? ??? ??? ?cout << "冷酷的敵人移動速度較快,難對付喲。"; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?break; ?? ??? ??? ?} ?? ??? ??? ?case 'k': ?? ??? ??? ?{ ?? ??? ??? ??? ? ?? ??? ??? ??? ?if (j == 11)//源代碼為8? ?? ??? ??? ??? ??? ?return 1; ?? ??? ??? ??? ?else ?? ??? ??? ??? ??? ?return 2; ?? ??? ??? ?} ?? ??? ??? ?} ?? ??? ?} ?? ?} ?? ?return 0; } void drawFrame(int x1, int y1, int x2, int y2, char row, char col) { ?? ?COORD a = { x1, y1 }; ?? ?COORD b = { x2, y2 }; ?? ?drawFrame(a, b, row, col); } // 繪制游戲界面 void drawPlaying() { ?? ?drawFrame(0, 0, 48, 24, '=', '|');//?? ?draw map frame主界面 ?? ?drawFrame(49, 0, 79, 4, '-', '|');//?? ?draw output frame 狀態(tài)界面 ?? ?drawFrame(49, 4, 79, 9, '-', '|');//?? ?draw score frame 分數(shù)界面 ?? ?drawFrame(49, 9, 79, 20, '-', '|');//?? ?draw operate frame 操作界面 ?? ?drawFrame(49, 20, 79, 24, '-', '|');//?? ?draw other message frame 提示界面 ?? ?SetPos(52, 6); ?? ?cout << "得分:"; ?? ?SetPos(52, 7); ?? ?cout << "稱號:"; ?? ?SetPos(52, 11); ?? ?cout << "操作方式:"; ?? ?SetPos(52, 13); ?? ?cout << " ?a,s,d,w:控制戰(zhàn)機移動。"; ?? ?SetPos(52, 15); ?? ?cout << " ?p:暫停游戲。"; ?? ?SetPos(52, 17); ?? ?cout << " ?e:退出游戲。"; ?? ?SetPos(52, 22); ?? ?cout << " 游戲雖好玩,不要貪多哦 "; } // 該成員函數(shù)用過響應戰(zhàn)機的一個動作 // a,s,w,d,來控制戰(zhàn)機的移動 void Game::planeMove(char x) { ?? ?if (x == 'a') ?? ?{ ?? ??? ?if (position[1].X != 1) ?? ??? ?{ ?? ??? ??? ?for (int i = 0; i <= 9; i++) ?? ??? ??? ?{ ?? ??? ??? ??? ?position[i].X -= 2; ?? ??? ??? ?} ?? ??? ?} ?? ?} ?? ?// 如果玩家按下 'a' 鍵,說明玩家想讓戰(zhàn)機往左移動一個距離(2個單位), ?? ?// 首先檢測,戰(zhàn)機的最左側(cè)的位置坐標(即position[1].X)有沒有達到左邊界, ?? ?// 如果到達了邊界,那就不做出移動;如果沒有達到邊界,則將戰(zhàn)機10個部分的X值減小2。 ?? ?if (x == 's') ?? ?{ ?? ??? ?if (position[7].Y != 23) ?? ??? ?{ ?? ??? ??? ?for (int i = 0; i <= 9; i++) ?? ??? ??? ?{ ?? ??? ??? ??? ?position[i].Y += 1; ?? ??? ??? ?} ?? ??? ?} ?? ?}?? ??? ? ?? ?// 如果玩家按下 's' 鍵,說明玩家想讓戰(zhàn)機往下移動一個距離(1個單位), ?? ?// 首先檢測,戰(zhàn)機的最底部的位置坐標(即position[6].Y或者position[7].Y或者position[8].Y)有沒有達到下邊界, ?? ?// ?如果到達了邊界,那就不做出移動;如果沒有達到邊界,則將戰(zhàn)機10個部分的Y值增加1。 ?? ?if (x == 'd' && (position[4].X != 47)) ?? ?{ ?? ??? ?for (int i = 0; i <= 9; i++) ?? ??? ?{ ?? ??? ??? ?position[i].X += 2; ?? ??? ?}?? ? ?? ?}?? ??? ? ?? ?// 如果玩家按下 'd' 鍵,說明玩家想讓戰(zhàn)機往右移動一個距離(2個單位), ?? ?// 首先檢測,戰(zhàn)機的最右側(cè)的位置坐標(即position[4].X)有沒有達到右邊界, ?? ?// ?如果到達了邊界,那就不做出移動;如果沒有達到邊界,則將戰(zhàn)機10個部分的X值增加2。 ?? ?if (x == 'w'&&(position[5].Y != 3)) ?? ?{ ?? ??? ?for (int i = 0; i <= 9; i++) ?? ??? ?{ ?? ??? ??? ?position[i].Y -= 1; ?? ??? ?} ?? ?} ?? ?// 如果玩家按下'w'鍵,說明玩家想讓戰(zhàn)機往上移動一個距離(1個單位), ?? ?// 首先檢測,戰(zhàn)機的最頂部的位置坐標(即position[5].Y)有沒有達到上邊界, ?? ?// ?如果到達了邊界,那就不做出移動;如果沒有達到邊界,則將戰(zhàn)機10個部分的Y值減少1。 } // 該函數(shù)用來判斷戰(zhàn)機的某一部分是否與敵機有接觸 // 如果與敵機有接觸在判斷為墜毀 bool ?judgeCoordInFrame(Frame frame, COORD spot) { ?? ?if ((spot.X >= frame.position[0].X) && (spot.X <= frame.position[1].X) && (spot.Y >= frame.position[0].Y) && (spot.Y <= frame.position[1].Y)) ?? ?{ ?? ??? ?return true; ?? ?} ?? ?return false; } void drawFrame(Frame frame, char row, char col) { ?? ?COORD a = frame.position[0]; ?? ?COORD b = frame.position[1]; ?? ?drawFrame(a, b, row, col); } //游戲結(jié)束 void Game::GameOver() { ?? ?system("cls"); ?? ?COORD p1 = { 28,9 }; ?? ?COORD p2 = { 53,15 }; ?? ?drawFrame(p1, p2, '=', '|'); ?? ?SetPos(36, 12); ?? ?string str = "Game Over!"; ?? ?for (int i = 0; i < str.size(); i++) ?? ?{ ?? ??? ?Sleep(80); ?? ??? ?cout << str[i]; ?? ?} ?? ?Sleep(1000); ?? ?system("cls"); ?? ?drawFrame(p1, p2, '=', '|'); ?? ?SetPos(31, 11); ?? ?cout << "擊落敵機:" << score / 5 << " 架"; ?? ?SetPos(31, 12); ?? ?cout << "得 分:" << score; ?? ?SetPos(31, 13); ?? ?cout << "獲得稱號:" << title; ?? ?SetPos(30, 18); ?? ?Sleep(1000); ?? ?cout << "繼續(xù)? 是(y)| 否(n)"; as://goto 語句標簽 直接跳轉(zhuǎn)至此 ?? ?char x = _getch(); ?? ?if (x == 'n') ?? ?{ ?? ??? ?exit(0); ?? ?} ?? ?else if (x == 'y') ?? ?{ ?? ??? ?system("cls"); ?? ??? ?Game game; ?? ??? ?int a = drawMenu(); ? ? ? // 繪制游戲開始界面主菜單 ?? ??? ?if (a == 2) ?? ??? ??? ?game.rank = 20; ?? ??? ?system("cls"); ?? ??? ?drawPlaying(); ? ? ? ? ? // 繪制游戲界面框架 ?? ??? ?game.Playing(); ?? ?} ?? ?else? ?? ??? ?goto as; } // 該成員函數(shù)用來判斷戰(zhàn)機是否墜毀, // 依次判斷每架敵機與戰(zhàn)機的每個部分是否有接觸, // 如果有接觸,則表示戰(zhàn)機墜毀 void Game::judgePlane() { ?? ?for (int i = 0; i < 8; i++) ?? ?{ ?? ??? ?for (int j = 0; j < 9; j++) ?? ??? ??? ?// 此處的實參position[j]是指戰(zhàn)機的10個部分的COORD坐標, ?? ??? ??? ?// 類中的成員函數(shù)可以訪問數(shù)據(jù)成員變量。 ?? ??? ??? ?// 此處也可以寫成this-> position[j],因為 ?? ??? ??? ?// 成員函數(shù)具有一個附加的隱含形參,即指向該類對象的一個指針, ?? ??? ??? ?// 這個隱含形參命名為this,與調(diào)用成員函數(shù)的對象綁定在一起。 ?? ??? ??? ?// 成員函數(shù)不能定義this形參,而是由編譯器隱含地定義。 ?? ??? ??? ?// 成員函數(shù)的函數(shù)體可以顯式使用this指針,但不是必須這么做。 ?? ??? ??? ?if (judgeCoordInFrame(enemy[i], position[j])) ?? ??? ??? ?{ ?? ??? ??? ??? ?SetPos(62, 1); ?? ??? ??? ??? ?cout << "墜毀"; ?? ??? ??? ??? ?drawFrame(enemy[i], '+', '+'); ?? ??? ??? ??? ?// 將與戰(zhàn)機相撞的敵機的形狀繪制為: ?? ??? ??? ??? ?// ? ?++ ?? ??? ??? ??? ?// ? + ?+ ?? ??? ??? ??? ?// ? ?++ ?? ??? ??? ??? ?Sleep(1000); ?? ??? ??? ??? ?GameOver(); ?? ??? ??? ??? ?break; ?? ??? ??? ?} ?? ?} } // 該成員函數(shù)用來使得游戲暫停 void Game::Pause() { ?? ?SetPos(61, 2); ?? ?cout << " ? ? ? ? "; ?? ?SetPos(61, 2); ?? ?cout << "暫停中..."; ?? ?// 當出現(xiàn)"暫停中..."的提示以后,程序不停的接收按下的按鍵, ?? ?// 當按下'p'鍵以后,說明要退出暫停狀態(tài),此時需要清除"暫停中..."的提示 ?? ?// 通過輸出空白 " ? ? ? ? "來將其覆蓋,達到效果 ?? ?char c = _getch(); ?? ?while (c != 'p') ?? ?{ ?? ??? ?c = _getch(); ?? ?} ?? ?SetPos(61, 2); ?? ?cout << " ? ? ? ? "; } // 這個成員函數(shù)用來響應一次射擊操作, // 也就是,當游戲中的時候,玩家按下"k"鍵,就執(zhí)行該函數(shù)。 // 由于子彈是由COORD bullet[10]定義的,因此同一時刻,界面內(nèi)只能有10顆子彈同時出現(xiàn)。 // 如果界面內(nèi)不夠10顆子彈,按下"k"鍵后戰(zhàn)機應該發(fā)射出一顆子彈, // 于是,依次遍歷10顆子彈,當遇到第一顆失效的子彈后, // 立即將該子彈賦予新的坐標(戰(zhàn)機的炮口,也就是(position[5].X,position[5].Y - 1)), // 讓其激活。然后退出for循環(huán),函數(shù)執(zhí)行完畢。 void Game::Shoot() { ?? ?for (int i = 0; i < 10; i++) ?? ?{? ?? ??? ?if (bullet[i].Y == 30) ?? ??? ?{ ?? ??? ??? ?bullet[i].X = position[5].X; ?? ??? ??? ?bullet[i].Y = position[5].Y - 1; ?? ??? ??? ?break; ?? ??? ?} ?? ?} } void Game::drawThisBulletToNull(COORD c) { ?? ?SetPos(c.X,c.Y); ?? ?cout << " "; } // 此成員函數(shù)用來響應一次子彈的運動 // 每次子彈運動,屏幕子彈的坐標都會出現(xiàn)變化,即 // 先判斷子彈是否有效(即判斷語句if (bullet[i].Y != 30)), // 若子彈有效,將該子彈的Y坐標減少1,X坐標不變, // 檢測子彈坐標更改之后是否達到上邊界,如果達到上邊界,則將該子彈從屏幕上擦除, // 同時,將該子彈置為失效狀態(tài),即 bullet[i].Y = 30。 void Game::bulletMove() { ?? ?for (int i = 0; i < 10; i++) ?? ?{ ?? ??? ?if (bullet[i].Y != 30) ?? ??? ?{ ?? ??? ??? ?bullet[i].Y -= 1; ?? ??? ??? ?if (bullet[i].Y == 1) ?? ??? ??? ?{ ?? ??? ??? ??? ?COORD pos = { bullet[i].X, bullet[i].Y + 1 }; ?? ??? ??? ??? ?drawThisBulletToNull(pos); ?? ??? ??? ??? ?bullet[i].Y = 30; ?? ??? ??? ?} ?? ??? ?} ?? ?} } //擊敗的敵機清空 void Game::drawThisEnemyToNull(Frame f) { ?? ?drawFrame(f, ' ', ' '); } // 該成員函數(shù)依次遍歷每一架敵機, // 將每一架敵機依次與每一顆子彈進行檢測, // 判斷敵機是否與子彈有接觸,如果有接觸,則表示擊中敵機, // 此時將敵機和子彈擦除,然后在界面頂部的位置處隨機生成一架敵機 void Game::judgeEnemy() { ?? ?for (int i = 0; i < 8; i++) ?? ?{ ?? ??? ?for (int j = 0; j < 10; j++) ?? ??? ?{ ?? ??? ??? ?if (judgeCoordInFrame(enemy[i], bullet[j])) ?? ??? ??? ?{ ?? ??? ??? ??? ?score += 5; ?? ??? ??? ??? ?drawThisEnemyToNull(enemy[i]); ?? ??? ??? ??? ?COORD a = { 1, 1 }; ?? ??? ??? ??? ?COORD b = { 45, 3 }; ?? ??? ??? ??? ?enemy[i].position[0] = random(a, b); ?? ??? ??? ??? ?enemy[i].position[1].X = enemy[i].position[0].X + 3; ?? ??? ??? ??? ?enemy[i].position[1].Y = enemy[i].position[0].Y + 2; ?? ??? ??? ??? ?drawThisBulletToNull(bullet[j]); ?? ??? ??? ??? ?bullet[j].Y = 30; ?? ??? ??? ?} ?? ??? ?} ?? ?} } // 該成員函數(shù)用來響應一次敵機的移動 // 界面上必須同時出現(xiàn)八架敵機,因此, // 如果有某架敵機運動到下邊界處,則重置該敵機的坐標 void Game::enemyMove() { ?? ?for (int i = 0; i < 8; i++) ?? ?{ ?? ??? ?for (int j = 0; j < 2; j++) ?? ??? ??? ?enemy[i].position[j].Y++; ?? ??? ?// 我們將每架敵機的左上角和右下角坐標的Y值增加1, ?? ??? ?// 表示該敵機向下走了一個距離 ?? ??? ? ?? ??? ?// 檢測向下走一個距離后的敵機的右下角坐標的Y值是否達到24, ?? ??? ?// 如果達到,代表敵機已經(jīng)運動到下邊界了, ?? ??? ?// 此時需要隨機重置該敵機的坐標 ?? ??? ?if (enemy[i].position[1].Y==24) ?? ??? ?{ ?? ??? ??? ?COORD a = { 1, 1 }; ?? ??? ??? ?COORD b = { 45, 3 }; ?? ??? ??? ?enemy[i].position[0] = random(a, b); ?? ??? ??? ?enemy[i].position[1].X = enemy[i].position[0].X + 3; ?? ??? ??? ?enemy[i].position[1].Y = enemy[i].position[0].Y + 2; ?? ??? ?} ?? ?} } void Game::printScore() { ?? ?if (score <= 120) ?? ?{ ?? ??? ?flag_rank = 1; ?? ?} ?? ?else if (score > 120 && score <= 360) ?? ?{ ?? ??? ?flag_rank = 2; ?? ?} ?? ?else if (score > 360 && score <= 480) ?? ?{ ?? ??? ?flag_rank = 3; ?? ?} ?? ?else if (score > 480) ?? ?{ ?? ??? ?flag_rank = 4; ?? ?} ?? ?SetPos(60, 6); ?? ?cout << score; ?? ?SetPos(60, 7); ?? ?if (flag_rank == 1) ?? ?{ ?? ??? ?title = "初級飛行員"; ?? ?} ?? ?else if (flag_rank == 2) ?? ?{ ?? ??? ?title = "中級飛行員"; ?? ?} ?? ?else if (flag_rank == 3) ?? ?{ ?? ??? ?title = "高級飛行員"; ?? ?} ?? ?else if (flag_rank == 4) ?? ?{ ?? ??? ?title = "王牌飛行員"; ?? ?} ?? ?cout << title; } // 這個成員函數(shù)是游戲的主循環(huán)函數(shù), // 定義了整個游戲過程。 void Game::Playing() { ?? ?drawEnemy(); ?? ?drawPlane(); ?? ?int flag_bullet = 0; ?? ?int flag_enemy = 0; ?? ?while (true) ?? ?{ ?? ??? ?Sleep(20); ?? ??? ?// 函數(shù)名:kbhit()(VC++6.0下為_kbhit()) ?? ??? ?// 功能及返回值: 檢查當前是否有鍵盤輸入,若有則返回一個非0值,否則返回0 ?? ??? ?// 用法:int kbhit(void); ?? ??? ?// 包含頭文件: include <conio.h> ?? ??? ?// kbhit()在執(zhí)行時,檢測是否有按鍵按下,有按下返回非0值,沒有按下則返回0,是非阻塞函數(shù); ?? ??? ?// 不同于getch()的在執(zhí)行時, 檢測按下什么鍵, 如果不按鍵該函數(shù)不返回,也就不進行下一步操作,是阻塞函數(shù)。 ?? ??? ?if (_kbhit()) ?? ??? ?{ ?? ??? ??? ?char x = _getch(); ?? ??? ??? ?// getch()是編程中所用的函數(shù),這個函數(shù)是一個不回顯函數(shù), ?? ??? ??? ?// 當用戶按下某個字符時,函數(shù)自動讀取,無需按回車 ?? ??? ??? ?// getch()并非標準C中的函數(shù),不存在C語言中。 ?? ??? ??? ?// 所在頭文件是conio.h,而不是stdio.h。 ?? ??? ??? ?// 用ch = getch(); 會等待你按下任意鍵之后,把該鍵字符所對應的ASCII碼賦給ch, 再執(zhí)行下面的語句。 ?? ??? ??? ?if ('a' == x || 's' == x || 'd' == x || 'w' == x) ?? ??? ??? ?{ ?? ??? ??? ??? ?drawPlaneToNull(); ? ? // 將戰(zhàn)機先擦除 ?? ??? ??? ??? ?planeMove(x); ? ? ? ? ?// 根據(jù)所輸入的操作符,對戰(zhàn)機的坐標進行更改 ?? ??? ??? ??? ?drawPlane(); ? ? ? ? ? // 訪問類中的數(shù)據(jù)成員——戰(zhàn)機的坐標,在新的坐標處重新繪制戰(zhàn)機 ?? ??? ??? ??? ?judgePlane(); ? ? ? ? ?// 判斷戰(zhàn)機是否有墜毀 ?? ??? ??? ?} ?? ??? ??? ?// ?在某一循環(huán)當中,如果檢測到有'p'鍵按下, ?? ??? ??? ?// 首先在右側(cè)游戲界面輸出"暫停中...",然后陷入while()循環(huán)一直等待'p'鍵再次按下, ?? ??? ??? ?// 如果'p'鍵沒有按下,就一直處在while()循環(huán)內(nèi),因此不能執(zhí)行后面的程序,起到暫停的效果。 ?? ??? ??? ?else if ('p' == x) ?? ??? ??? ?{ ?? ??? ??? ??? ?Pause(); ?? ??? ??? ?} ?? ??? ??? ?// 如果是檢測到'k'鍵按下,則運行Shoot()函數(shù), ?? ??? ??? ?else if ('k' == x) ?? ??? ??? ?{ ?? ??? ??? ??? ?Shoot(); ?? ??? ??? ?} ?? ??? ??? ?// 如果是檢測到'k'鍵按下,則運行GameOver()函數(shù), ?? ??? ??? ?// GameOver()函數(shù)執(zhí)行完畢后,執(zhí)行break;語句跳出while循環(huán)(注意不是if (_kbhit()))。 ?? ??? ??? ?// break語句用于結(jié)束最近的while、do while、for或switch語句,并將程序的執(zhí)行權(quán)傳遞給緊接在 ?? ??? ??? ?// 被終止語句之后的語句。 ?? ??? ??? ?else if ('e' == x) ?? ??? ??? ?{ ?? ??? ??? ??? ?//CloseHandle(MFUN) ?? ??? ??? ??? ?GameOver(); ?? ??? ??? ??? ?break; ?? ??? ??? ?} ?? ??? ?} ?? ??? ?// 接下來處理子彈 ?? ??? ?// 判斷子彈狀態(tài)的程序一直在運行 ?? ??? ?if (flag_bullet == 0) ?? ??? ?{ ?? ??? ??? ?bulletMove(); ? ? ? ? ? // 更新界面上有效子彈的坐標 ?? ??? ??? ?drawBulletToNull(); ? ? // 將處于舊坐標的子彈擦除 ?? ??? ??? ?drawBullet(); ? ? ? ? ? // 繪制出新坐標上的子彈 ?? ??? ??? ?judgeEnemy(); ? ? ? ? ?// 判斷敵機是否被子彈擊中 ?? ??? ?} ?? ??? ?flag_bullet++; ?? ??? ?if (flag_bullet==1) ?? ??? ?{ ?? ??? ??? ?flag_bullet = 0; ?? ??? ?} ?? ??? ?// ?接下來處理敵機 ?? ??? ?if (flag_enemy==0) ?? ??? ?{ ?? ??? ??? ?drawEnemyToNull(); ? ? // 將所有的敵機都擦除 ?? ??? ??? ?enemyMove(); ? ? ? ? ? // ?更新敵機的坐標 ?? ??? ??? ?drawEnemy(); ? ? ? ? ? // 繪制出處于新坐標上的敵機 ?? ??? ??? ?judgePlane(); ? ? ? ? ?// 判斷敵機是否與戰(zhàn)機接觸 ?? ??? ?} ?? ??? ?flag_enemy++; ?? ??? ?if (flag_enemy >= rank) ?? ??? ?{ ?? ??? ??? ?flag_enemy = 0; ?? ??? ?} ?? ??? ?/* 輸出得分 */ ?? ??? ?printScore(); ?? ?} }
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Cocos2d-x UI開發(fā)之CCControlColourPicker控件類使用實例
這篇文章主要介紹了Cocos2d-x UI開發(fā)之CCControlColourPicker控件類使用實例,本文代碼中包含大量注釋來講解CCControlColourPicker控件類的使用,需要的朋友可以參考下2014-09-09C/C++?Qt?TreeWidget?單層樹形組件應用小結(jié)
TreeWidget?目錄樹組件,該組件適用于創(chuàng)建和管理目錄樹結(jié)構(gòu),在開發(fā)中我們經(jīng)常會把它當作一個升級版的ListView組件使用,本文將通過TreeWidget實現(xiàn)多字段顯示,并增加一個自定義菜單,通過在指定記錄上右鍵可彈出該菜單并對指定記錄進行操作2021-11-11詳解VisualS tudio Code開發(fā)Arm嵌入式Linux應用
本文介紹如何在 Visual Studio Code 中使用 Yocto Project 生成的 Linux SDK,并針對 Arm 處理器進行 C/C++ 應用交叉編譯和調(diào)試,感興趣的朋友跟隨小編一起看看吧2021-04-04數(shù)據(jù)結(jié)構(gòu) 雙向鏈表的創(chuàng)建和讀取詳解及實例代碼
這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu) 雙向鏈表的創(chuàng)建和讀取詳解及實例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03C++線性表深度解析之動態(tài)數(shù)組與單鏈表和棧及隊列的實現(xiàn)
這篇文章主要為大家詳細介紹了C++實現(xiàn)動態(tài)數(shù)組、單鏈表、棧、隊列,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-05-05