vs做網(wǎng)站通過e瀏覽器南寧百度seo軟件
??前言:
飛機大作戰(zhàn)游戲是一種非常受歡迎的射擊類游戲,玩家需要控制一架戰(zhàn)斗機在屏幕上移動,擊落敵機以獲得分數(shù)。本游戲使用C語言編寫,旨在幫助初學者了解游戲開發(fā)的基本概念和技巧。
在開始編寫代碼之前,我們需要先了解一下游戲的基本規(guī)則和功能:
-
游戲界面:游戲界面是一個矩形區(qū)域,玩家可以在這個區(qū)域內(nèi)控制戰(zhàn)斗機移動和射擊。
-
戰(zhàn)斗機:玩家控制的戰(zhàn)斗機可以在游戲界面內(nèi)自由移動,按下特定鍵可以發(fā)射子彈和開啟技能擊落敵機。
-
敵機:敵機會從屏幕的一側(cè)出現(xiàn),并沿著直線路徑向另一側(cè)移動。玩家需要擊落敵機以獲得分數(shù)。
-
分數(shù):玩家每擊落一架敵機,分數(shù)會增加。
-
游戲結(jié)束:當玩家飛機被敵機撞到到或者得分為0時,游戲結(jié)束。
接下來,我們將通過以下幾個步驟來實現(xiàn)這個游戲:
-
初始化游戲界面和戰(zhàn)斗機。
-
處理鍵盤輸入,實現(xiàn)戰(zhàn)斗機的移動和射擊。
-
生成敵機,并控制其移動。
-
檢測戰(zhàn)斗機與敵機之間的碰撞,更新分數(shù)和技能充能值。
-
判斷游戲是否結(jié)束。
通過學習這個游戲的開發(fā)過程,初學者將能夠掌握C語言編程的基本技巧。
1. 打印菜單:
void menu()
{printf("--------------飛機大作戰(zhàn)--------------\n");printf("| |\n");printf("| 1.開始游戲 |\n");printf("| 0.退出游戲 |\n");printf("| W/A/S/D移動 |\n");printf("| 空格射擊 E/R技能 |\n");printf("| |\n");printf("--------------------------------------\n");
}
int main()
{system("color b");int input = 0;menu();printf("請選擇:");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戲\n");break;default:printf("輸入有誤,請重新輸入:\n");break;}return 0;
}
2. 寫一個存放信息的數(shù)組
int arr[Col][Row] = { 0 };
3. 寫一個打印數(shù)組信息的函數(shù)
飛機大作戰(zhàn)的要素無非就是路、圍墻、玩家飛機、敵機、子彈這五個元素,要想在打印出這幾個元素,我們只需在寫一個函數(shù)在二維數(shù)組中存放這個五個元素的信息(用0-4代替),然后再寫一個打印信息的函數(shù)分別出二維數(shù)組中對應的信息。
void DisPlay(int arr[Col][Row])
{gotoxy(0, 0);for(int i=0;i<Col;i++){for (int j = 0; j < Row; j++){if (arr[i][j] == 0){printf(" ");}if (arr[i][j] == 1){printf("█");}if (arr[i][j] == 2){printf("*");}if (arr[i][j] == 3){printf("$");}if (arr[i][j] == 4){printf("|");}}printf("\n");}printf("得分:%d ", score);printf("EnemySleep=%d ", EnemySleep);printf("skill1(20)=%d ", skill1);printf("skill2(5)=%d ", skill2);Sleep(20);
}
4. 寫一個函數(shù)來初始化數(shù)組的信息
void InSet(int arr[Col][Row])
{//路--0//墻--1//玩家飛機--2//敵機--3//子彈--4
}
5. 初始化圍墻
數(shù)組最邊邊的位置我們都讓它等于1,這樣就可以把游戲界面圍起來了。
//墻--1
for (int i = 0; i < Col; i++)
{arr[i][0] = 1;arr[i][Row - 1] = 1;
}
for (int i = 0; i < Row; i++)
{arr[0][i] = 1;arr[Col - 1][i] = 1;
}
6. 初始化玩家飛機
玩家飛機剛開始應該出現(xiàn)在下側(cè)的中央位置,所以將這個位置的坐標對應的值初始化為2。
//玩家飛機--2
arr[PlayerPlane_y][PlayerPlane_x] = 2;
7. 玩家操作飛機
通過按下A/W/S/D鍵來控制飛機的移動,空格鍵來控制飛機發(fā)射子彈,要想實現(xiàn)這個功能我們需要用到getch()函數(shù),這個函數(shù)用于從標準輸入(通常是鍵盤)獲取一個字符,而不需要用戶按下回車鍵。這個函數(shù)在Windows操作系統(tǒng)下的
conio.h
頭文件中定義,而在Unix/Linux系統(tǒng)下,通常使用termios.h
和unistd.h
頭文件中的函數(shù)來實現(xiàn)類似的功能。
char ch = getch();
if (ch == 'w' && arr[PlayerPlane_y - 1][PlayerPlane_x] == 0)
{arr[PlayerPlane_y][PlayerPlane_x] = 0;PlayerPlane_y--;arr[PlayerPlane_y][PlayerPlane_x] = 2;
}
if (ch == 'a' && arr[PlayerPlane_y][PlayerPlane_x - 1] == 0)
{arr[PlayerPlane_y][PlayerPlane_x] = 0;PlayerPlane_x--;arr[PlayerPlane_y][PlayerPlane_x] = 2;
}
if (ch == 's' && arr[PlayerPlane_y + 1][PlayerPlane_x] == 0)
{arr[PlayerPlane_y][PlayerPlane_x] = 0;PlayerPlane_y++;arr[PlayerPlane_y][PlayerPlane_x] = 2;
}
if (ch == 'd' && arr[PlayerPlane_y][PlayerPlane_x + 1] == 0)
{arr[PlayerPlane_y][PlayerPlane_x] = 0;PlayerPlane_x++;arr[PlayerPlane_y][PlayerPlane_x] = 2;
}
if (ch == ' ')
{Bullet_y = PlayerPlane_y - 1;Bullet_x = PlayerPlane_x;arr[Bullet_y][Bullet_x] = 4;
}
}
8. 子彈上移
子彈上移一格就調(diào)用一次DisPlay函數(shù)打印內(nèi)容這樣就實現(xiàn)了子彈上移的效果,這時需要用到到我們的while循環(huán)來循環(huán)子彈上移的函數(shù)和打印的函數(shù),而子彈是由玩家按鍵產(chǎn)生的,所以這個while還需要循環(huán)上玩家操作飛機的函數(shù),但是getch()會讓while停止下來,玩家按鍵后才會繼續(xù),導致玩家按一次鍵盤按鍵,子彈才會上移一次,樣就子彈就出現(xiàn)不了的這連續(xù)上移的效果了,所以我們需要在玩家操作的函數(shù)加上if(_kbhit())的判斷語句函數(shù),它會判斷是否有按鍵按下來,如果沒有就不執(zhí)行g(shù)etch()函數(shù),繼續(xù)循環(huán)。
_kbhit()
是一個C語言中的函數(shù),用于檢測鍵盤是否有按鍵被按下。它通常在Windows操作系統(tǒng)下的conio.h
頭文件中定義。該函數(shù)不接受任何參數(shù),并返回一個整數(shù)值。如果鍵盤上有按鍵被按下,則返回非零值(通常是1),否則返回0。
while (1)
{//玩家操作PlayerPlay(arr);//打印棋盤DisPlay(arr);//子彈與敵機的操作BulletEnemy(arr);
}
在循環(huán)打印的時候它會框框打印根本就看不清游戲界面,所以在這里還需要使用到光標的知識?:
在C語言中,光標通常指的是控制臺或終端中的文本輸入位置指示器。它顯示了用戶當前輸入或輸出的位置。在編寫C程序時,有時需要對光標的顯示和位置進行控制,以便創(chuàng)建更復雜的用戶界面或處理特定的輸入輸出需求。
在Windows操作系統(tǒng)下,可以使用
conio.h
頭文件中提供的函數(shù)來控制光標。
因為它會在光標的位置輸出信息,所以我們在每次打印前將光標的位置置為(0,0)就可以了。
但是光標還會在那框框的閃,非常的礙眼,所以我們還需要使用函數(shù)將光標隱藏。
void HideCursor()
{CONSOLE_CURSOR_INFO cursor_info = { 1,0 }; //第二個值為0,表示隱藏光標SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
9. 初始化敵機
在這里我們需要隨機生成5架敵機出現(xiàn)在游戲界面上側(cè)1-3格的位置,所以需要使用一個大小為5的數(shù)組接受隨機數(shù)的值。
//敵機--3
for (int i = 0; i < Count; i++)
{Enemy_y[i] = rand() % 3 + 1;Enemy_x[i] = rand() % Row + 1;//防止敵機生成在圍墻上if (Enemy_x[i] >= Row - 1)Enemy_x[i] -= 2;arr[Enemy_y[i]][Enemy_x[i]] = 3;
}
10. 敵機的下移
如果敵機也像子彈一樣直接進去循環(huán)的話,那么敵機會移動得非常快,所以我們需要定義兩個全局變量sleep和EnemySleep來控制敵機的移動速度,例如給EnemySleep賦值一個20,然后sleep賦值一個0,隨后sleep在while循環(huán)中循環(huán)一次就加1,當sleep等于EnemySleep時我們才給敵機進行一次下移的操作,這樣就相當于while每循環(huán)20次,敵機才下移一次。
在敵機下的過程中我們可能無法打中敵機,而使敵機下降到了最下側(cè),這時就得讓敵機在觸碰到圍墻前一格消失,然后重新在上側(cè)生成新的敵機。
在敵機下移的過程中可能會碰到玩家的飛機,這時游戲就得結(jié)束了,然后告訴玩家游戲結(jié)束??刂朴螒蚪Y(jié)束需要用到system("pause")和exit()這兩個函數(shù)。
system("pause")
的作用是在Windows系統(tǒng)的命令行窗口中暫停程序的執(zhí)行,等待用戶按下任意鍵后繼續(xù)執(zhí)行。這通常用于調(diào)試程序時,以便查看程序運行過程中的輸出結(jié)果。
exit(0);
是C/C++語言中用于終止程序執(zhí)行的語句。其中,參數(shù)0表示程序正常退出,非零值表示程序異常退出。在程序執(zhí)行到該語句時,程序會立即停止運行,并返回給操作系統(tǒng)一個退出狀態(tài)碼。
//控制敵機的速度
if (sleep < EnemySleep)
{sleep++;
}
else if (sleep > EnemySleep)
{sleep = 0;
}
for (int i = 0; i < Count; i++)
{//敵機擊中玩家飛機的處理if (PlayerPlane_y == Enemy_y[i] && PlayerPlane_x == Enemy_x[i] || score < 0){printf(" /\\_/\\ \n");printf(" ( o.o ) \n");printf(" > ^ < \n");printf("游戲失敗!\n");printf("\a");system("pause");exit(0);}//敵機到達最底面的處理if (Enemy_y[i] >= Col - 2){score -= 100;arr[Enemy_y[i]][Enemy_x[i]] = 0;Enemy_y[i] = rand() % 3 + 1;Enemy_x[i] = rand() % Row + 1;if (Enemy_x[i] >= Row - 1)Enemy_x[i] -= 2;arr[Enemy_y[i]][Enemy_x[i]] = 3;}//敵機下移的處理if (sleep == EnemySleep){for (int j = 0; j < Count; j++){arr[Enemy_y[j]][Enemy_x[j]] = 0;sleep = 0;Enemy_y[j]++;arr[Enemy_y[j]][Enemy_x[j]] = 3;}}
}
?11. 游戲數(shù)值的設定
(1)敵機加速的分數(shù)閾值
- 當玩家得分達到?2000?分時,敵機的移動速度增加 2
- 當玩家得分再次增加?2000?分,即達到?4000?分時,敵機的移動速度再增加 2
- 以此類推,每當玩家得分增加?2000?分,敵機的速度增加 2。
(2)打爆一架敵機的得分
- 打爆一架普通敵機,玩家得到?100?分。
(3)一架敵機到底部消失的失分
- 如果一架敵機到達屏幕底部而未被擊落,玩家失去 100?分。
12. 游戲的優(yōu)化
為了使游戲更具可玩性,我們可以給玩家飛機加上一些技能,在這里的我設定了E/R是釋放技能的指令,這個加在玩家操作飛機的函數(shù)哪里就可以了,這兩個技能都是可發(fā)射范圍更廣的子彈,當然了這兩個技能也不是無限釋放的,是需要達到一定的值才能釋放的,這里我們可以設定一個變量來存放一個技能的充能值,打爆一架敵機就給充能值加1,當這個值達到的我們所規(guī)定的滿能值時才能接受釋放技能的指令。
//技能指令
if (ch == 'r')
{if (skill1 == 20){for (int i = 1; i < Row - 1; i++){skill1 = 0;Bullet_y = PlayerPlane_y - 1;Bullet_x = i;arr[Bullet_y][Bullet_x] = 4;}}
}
if (ch == 'e')
{int left = PlayerPlane_x - 3;int right = PlayerPlane_x + 3;if (skill2 == 5){for (int i = left; i < right; i++){if (i > 0 && i < Row - 1){skill2 = 0;Bullet_y = PlayerPlane_y - 1;Bullet_x = i;arr[Bullet_y][Bullet_x] = 4;}}}
}
源碼:?
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<Windows.h>
#include<time.h>
#define Count 5
#define Col 40//列
#define Row 40//行
//玩家飛機坐標
int PlayerPlane_y = Col - 2;
int PlayerPlane_x = Row / 2 - 1;
//子彈坐標
int Bullet_y;
int Bullet_x;
//敵機坐標
int Enemy_y[Count] = { 0 };
int Enemy_x[Count] = { 0 };
//敵機的移動速度
int EnemySleep = 20;
int sleep = 0;
//分數(shù)
int score = 0;
//技能充能
int skill1 = 20;
int skill2 = 5;
void menu()
{printf("--------------飛機大作戰(zhàn)--------------\n");printf("| |\n");printf("| 1.開始游戲 |\n");printf("| 0.退出游戲 |\n");printf("| W/A/S/D移動 |\n");printf("| 空格射擊 E/R技能 |\n");printf("| |\n");printf("--------------------------------------\n");
}//隱藏光標
void HideCursor()
{CONSOLE_CURSOR_INFO cursor_info = { 1,0 }; //第二個值為0,表示隱藏光標SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}// 光標移到(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 DisPlay(int arr[Col][Row])
{gotoxy(0, 0);for(int i=0;i<Col;i++){for (int j = 0; j < Row; j++){if (arr[i][j] == 0){printf(" ");}if (arr[i][j] == 1){printf("█");}if (arr[i][j] == 2){printf("*");}if (arr[i][j] == 3){printf("$");}if (arr[i][j] == 4){printf("|");}}printf("\n");}printf("得分:%d ", score);printf("EnemySleep=%d ", EnemySleep);printf("skill1(20)=%d ", skill1);printf("skill2(5)=%d ", skill2);Sleep(20);
}void InSet(int arr[Col][Row])
{srand(time(NULL));//路--0//墻--1for (int i = 0; i < Col; i++){arr[i][0] = 1;arr[i][Row - 1] = 1;}for (int i = 0; i < Row; i++){arr[0][i] = 1;arr[Col - 1][i] = 1;}//玩家飛機--2arr[PlayerPlane_y][PlayerPlane_x] = 2;//敵機--3for (int i = 0; i < Count; i++){Enemy_y[i] = rand() % 3 + 1;Enemy_x[i] = rand() % Row + 1;if (Enemy_x[i] >= Row - 1)Enemy_x[i] -= 2;arr[Enemy_y[i]][Enemy_x[i]] = 3;}//子彈--4
}
void PlayerPlay(int arr[Col][Row])
{if (_kbhit())//判斷是否有按鍵按下{char ch = getch();if (ch == 'w' && arr[PlayerPlane_y - 1][PlayerPlane_x] == 0){arr[PlayerPlane_y][PlayerPlane_x] = 0;PlayerPlane_y--;arr[PlayerPlane_y][PlayerPlane_x] = 2;}if (ch == 'a' && arr[PlayerPlane_y][PlayerPlane_x - 1] == 0){arr[PlayerPlane_y][PlayerPlane_x] = 0;PlayerPlane_x--;arr[PlayerPlane_y][PlayerPlane_x] = 2;}if (ch == 's' && arr[PlayerPlane_y + 1][PlayerPlane_x] == 0){arr[PlayerPlane_y][PlayerPlane_x] = 0;PlayerPlane_y++;arr[PlayerPlane_y][PlayerPlane_x] = 2;}if (ch == 'd' && arr[PlayerPlane_y][PlayerPlane_x + 1] == 0){arr[PlayerPlane_y][PlayerPlane_x] = 0;PlayerPlane_x++;arr[PlayerPlane_y][PlayerPlane_x] = 2;}if (ch == ' '){Bullet_y = PlayerPlane_y - 1;Bullet_x = PlayerPlane_x;arr[Bullet_y][Bullet_x] = 4;}if (ch == 'r'){if (skill1 == 20){for (int i = 1; i < Row - 1; i++){skill1 = 0;Bullet_y = PlayerPlane_y - 1;Bullet_x = i;arr[Bullet_y][Bullet_x] = 4;}}}if (ch == 'e'){int left = PlayerPlane_x - 3;int right = PlayerPlane_x + 3;if (skill2 == 5){for (int i = left; i < right; i++){if (i > 0 && i < Row - 1){skill2 = 0;Bullet_y = PlayerPlane_y - 1;Bullet_x = i;arr[Bullet_y][Bullet_x] = 4;}}}}}
}
void BulletEnemy(int arr[Col][Row])
{for (int i = 0; i < Col; i++){for (int j = 0; j < Row; j++){if (arr[i][j] == 4){for (int k = 0; k < Count; k++){//子彈擊中敵機的處理if (i == Enemy_y[k] && j == Enemy_x[k]){if (skill1 < 20){skill1++;}if (skill2 < 5){skill2++;}score += 100;arr[Enemy_y[k]][Enemy_x[k]] = 0;Enemy_y[k] = rand() % 3 + 1;Enemy_x[k] = rand() % Row + 1;if (Enemy_x[k] >= Row - 1)Enemy_x[k] -= 2;arr[Enemy_y[k]][Enemy_x[k]] = 3;//每2000分敵機加速if (score % 2000 == 0 && EnemySleep > 4){EnemySleep -= 2;}}}//子彈的移動if (arr[i][j] == 4){arr[i][j] = 0;if (i > 1){arr[i - 1][j] = 4;}}}}}//敵機的移動if (sleep < EnemySleep){sleep++;}else if (sleep > EnemySleep){sleep = 0;}for (int i = 0; i < Count; i++){if (PlayerPlane_y == Enemy_y[i] && PlayerPlane_x == Enemy_x[i] || score < 0){printf(" /\\_/\\ \n");//敵機擊中玩家飛機的處理printf(" ( o.o ) \n");printf(" > ^ < \n");printf("游戲失敗!\n");printf("\a");system("pause");exit(0);}//敵機到達最底面的處理if (Enemy_y[i] >= Col - 2){score -= 100;arr[Enemy_y[i]][Enemy_x[i]] = 0;Enemy_y[i] = rand() % 3 + 1;Enemy_x[i] = rand() % Row + 1;if (Enemy_x[i] >= Row - 1)Enemy_x[i] -= 2;arr[Enemy_y[i]][Enemy_x[i]] = 3;}//敵機下移的處理if (sleep == EnemySleep){for (int j = 0; j < Count; j++){arr[Enemy_y[j]][Enemy_x[j]] = 0;sleep = 0;Enemy_y[j]++;arr[Enemy_y[j]][Enemy_x[j]] = 3;}}}}void game()
{//設置一個存放信息的數(shù)組int arr[Col][Row] = { 0 };//隱藏光標HideCursor();//放置信息InSet(arr);//打印游戲界面DisPlay(arr);//玩家移動while (1){//玩家操作PlayerPlay(arr);//打印棋盤DisPlay(arr);//子彈與敵機的操作BulletEnemy(arr);}
}
int main()
{system("color b");int input = 0;menu();printf("請選擇:");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戲\n");break;default:printf("輸入有誤,請重新輸入:\n");break;}return 0;
}
最終效果
飛機大作戰(zhàn)