為期兩周的實訓結束了,寫一篇飛機大戰紀念一下,因為之前對于編程可能也沒有太深入系統的學習,這個實訓應該標志著編程學習的由淺入深,也代表著我們學習正式開始,(所以說之前一年我們學了點什么,,,)
在拿到我們最后的要求時我其實還是有些猶豫,畢竟之前剛做過鏈表,寫起貪吃蛇來相比飛機大戰可能會比較容易,但后來又想到老師會給我們一些提示,于是我理所當然的飄了,,,,認為寫出來的飛機大戰應該會是這樣的:
但是在提示給出來之后是這樣的:
,,,,,,,,,,,
只能說菜給的太多了,喝成了這個樣子

話不多說,還是腳踏實地一步一步寫的好,
一、游戲要求:
按照一定的規則排列的“*”模擬玩家飛機,向下移動的“@”符號表示敵機,由下至上間斷顯示的“|”模擬子彈,界面下方顯示飛機的生命值,的分情況等等,
每當玩家飛機撞上敵機生命值減1,程式自動生成另一架位置隨機的飛機繼續游戲,直到生命值為0游戲結束,
通過wasd鍵控制飛機移動,通過空格鍵發射激光子彈,要求:采用多檔案結構實作,
二、實驗設計
程式應該主要涉及到兩個模塊,分別為主模塊mainfighter 和子模塊fighter,子模塊主要包含初始化功能函式init(),繪制游戲界面函式drawpitcure(),電腦操作子界面與敵機函式pcoperate(),玩家控制飛機函式operatefighter(),
主模塊只有mainfighter這一個檔案,以下為框架:
void main(){
init();
while(1);{
drawpicture();
pcoperate();
operatefighter();
}
system("pause");
}
相應的功能在具體的函式中實作,
三 函式呼叫思路
繪制游戲界面函式drawpicture()
外層回圈變數x控制行輸出,內層回圈變數y控目列輸出,內層回圈陳述句不斷判斷當前坐標與玩家飛機、敵機、激光束子彈位置是否重疊,前坐標值(x,y)為(fighter. x, fighter. y)時向螢屏輸出玩家飛機“*”,當前坐標值為(enemyenemy_ y)時向螢屏輸出敵機“@”,當前坐標值為(bullet x, bullet y)時向螢屏輸出激光子彈否則輸出空格,從而實作了在螢屏上看到玩家飛機、敵機、激光束子彈的效果,
此時實作的游戲界面上的玩家飛機、敵機、激光子彈等是靜止的,要想實作動態效需要不斷改變玩家飛機、敵機、激光東子彈坐標值實作動態效果,
3)電腦操作子彈與敵機函式pcOperate0
pcOperate()函式相對簡單,呼叫flatBaullet)函式實作激光束子彈向上漂浮效果,呼叫enemyfighter()實作敵機移動,被擊落后隨機生成敵機的視覺效果等,
eneyfighter(函式實作敵機移動、被擊落后隨機生成放機的視覺效果等)
4控制飛機operateFighter()
該西數主要實作玩家飛機移動、發射激光束子彈,通過按W5. 2小建控朝元家飛機上下左右移動,通過按下空格鍵發射激光子彈,
判斷當前按鍵改變相應坐標值實作飛機移動、發射激光束子彈功能,當按下”鍵時表示向.上移動,玩家飛機縱向坐標減1橫向坐標不變,即fighter X–;當按下“d”鍵時表不向右移動,玩家飛機橫向坐標加1縱向坐標不變,即fighter y++,當按下空格鍵時表示發射激光束子彈,則在飛機正上方生成子彈,即將激光束子彈坐標值為(ighter_ x- 1, fighter y),
五、編碼實作
將游戲畫面尺寸、玩家飛機位置、激光束子彈位置、敵機位置等定義為全域變數:
//全域變數
int height,width;//游戲畫面尺寸
int fighter_x,fighter_y;//飛機位置
int bullet_x,bullet_y;//子彈位置
int enemy_x;enemy_y;//敵機位置
string difficulty//難度設定顯示條
init 函式要實作對上述全域變數賦值的功能,一般將玩家飛機顯示在畫面中間的位置,敵機顯示在第一行,飛機坐標(fighter_x,fighter_y)設定為(height/2,width/2),敵機坐標為(enemy_x,enemy_y),設定為(0,rand()%(width-5)+2),
drawpicture函式實作
通過雙層函式回圈控制游標移動,當坐標值(x,y)滿足特定的條件時向螢屏輸出玩家飛機,敵機,光束子彈,
cout << setfill('#') << setw(width + 6) << "#" << endl;
for (int x = 0; x < height; x++)
{//外層回圈
for (int y = 0; y < width + 1; y++)
{
if (y == 0)
cout << "#";//設定左邊界
else if (y == width)
{//設定右邊界
if (x == fighter_x)
cout << "#";
else if (x == fighter_x + 1)
cout << setfill(' ') << "#";
else if (x == fighter_x + 2)
cout << setfill(' ') << "#";
else cout << setfill(' ') << setw(6) << "#";
}
else if ((x == fighter_x) && (y == fighter_y))
cout << setfill(' ') << setw(6) << "* ";
else if ((x == fighter_x + 1) && (y == fighter_y))
cout << setfill('*') << setw(6) << " ";
else if ((x == fighter_x + 2) && (y == fighter_y))
cout << setfill(' ') << setw(6) << "* * ";//輸出飛機
else if ((x == bullet_x) && (y == bullet_y))
cout << "|";//輸出子彈
else if (x == enemy_x && y == enemy_y)
cout << "@";//輸出敵機位置
else cout << " ";
}
cout << endl;
}
cout << setfill('#') << setw(width + 6) << "#" << endl;
cout << "難度:" << difficulty << endl;
cout << "生命:" << fighter << endl;
cout << "得分:" << score << endl;
operatefighter編碼實作
呼叫floatbullet 函式處理子彈移動,呼叫enemyfighter函式實作生成敵機、移動等等,
bullet_x–實作子彈移動
要想設定難度層次,就要設法控制敵機向下移動的速度,因此設定靜態變數speed,每執行幾次,敵機就移動一次,
static int speed = 10;
difficulty = "簡單";
if (score > 5) {
speed++;
difficulty = "普通";
}
if (score > 15) {
speed++;
difficulty = "困難";
}
if (speed < 10) {
speed += 2;
}
else {
enemy_x++;
speed = 0;
最后,是擊中敵機,在enemyfighter中增加判斷,當子彈和敵機位置相同時就擊中敵機,并增加變數score記錄得分,擊中敵機后+1;敵機被擊中后會消失,然后在隨機位置出現
if((bullet_x==enemy_x)&&(bullet_y==enemy_y))//子彈擊中敵機
{
score++;
enemy_x=-1;
enemy_y=rand()%(width-5)+2;
bullet_x=-2;//子彈無效
思路大致如下,但是在操作程序中,由于飛機體型較大,在擊中敵機程序中無法準確被擊毀,此外還存在著敵機在移動程序的瞬間子彈擊中敵機無效的情況,因此更改判斷條件,使得飛機任何位置碰到敵機都會被擊毀;子彈能夠準確的擊毀敵機,
if (((bullet_x == enemy_x) && (bullet_y == enemy_y)) || ((bullet_x + 1 == enemy_x) &&
(bullet_y == enemy_y)) || ((bullet_x - 1 == enemy_x) && (bullet_y == enemy_y)))
{
score++;
enemy_x = -1;//產生新的飛機
enemy_y = rand() % (width - 5) + 3;//rand()函式生成亂數,但因為一般生成的亂數較大,因此做取余操作使其能在規定的寬度內生成
bullet_x = -2;//子彈無效
}
if ((enemy_x == fighter_x) && ((enemy_y == fighter_y) ||
(enemy_y == fighter_y + 1) || (enemy_y == fighter_y + 3) ||
(enemy_y == fighter_y + 4)) || ((enemy_x == fighter_x) &&
(enemy_y == fighter_y + 2)))
{
fighter--;
fighter_x = rand() % (height - 5) + 2;
fighter_y = rand() % (width - 5) + 2;
enemy_x = -1;
enemy_y = rand() % width;
lose();
}
if (enemy_x > height) {//如果敵機飛出螢屏則重新生成一架
score--;
enemy_x = -1;
enemy_y = rand() % width;
lose();
}
目前螢屏的閃爍嚴重,還存在游標,因此需要一個函式實作清屏效果,這里直接呼叫了windows.庫函式來實作
void zeroXy(int x, int y) {//實作函式清屏
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle, pos);
}
void hidecursor() {//隱藏游標
CONSOLE_CURSOR_INFO consor_info = { 1,0 };//第二個值為0隱藏游標
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consor_info);
}
最后就是要時刻判斷游戲的輸贏情況,當生命值為0時或者得分小于0時則游戲失敗,再定義一個函式來實作
void lose() {
if (fighter < 0 || score < 0) {
cout << endl;
cout << "**********************你輸了!*********************" << endl;
system("pause");
exit(0);
}
}
至此飛機大戰全部內容就完成了,生成代碼如下(包含一個頭檔案,一個子模塊和一個主模塊)
//fighter.h檔案
#ifndef _fighter_h
#define _fighter_h
void drawPicture();
void init();
void OperateFighter();
void pcOperate();
void floatBullet();
void enemyFighter();
void zeroXy(int x, int y);
void hidecursor();
void lose();
#endif
//fighter.cpp檔案
#include<iostream>
#include<conio.h>
#include<Windows.h>
#include<iomanip>
#include"fighter.h"
using namespace std;
int height = 20;
long width = 30;//定義游戲界面長和寬
int fighter_x, fighter_y;
int bullet_x, bullet_y;
int enemy_x, enemy_y;
int score;
int fighter;
string difficulty;
void drawPicture() {//x控制行輸出,y控制列輸出
zeroXy(0, 0);
cout << setfill('#') << setw(width + 6) << "#" << endl;
for (int x = 0; x < height; x++)
{
for (int y = 0; y < width + 1; y++)
{
if (y == 0)
cout << "#";
else if (y == width)
{
if (x == fighter_x)
cout << "#";
else if (x == fighter_x + 1)
cout << setfill(' ') << "#";
else if (x == fighter_x + 2)
cout << setfill(' ') << "#";
else cout << setfill(' ') << setw(6) << "#";
}
else if ((x == fighter_x) && (y == fighter_y))
cout << setfill(' ') << setw(6) << "* ";
else if ((x == fighter_x + 1) && (y == fighter_y))
cout << setfill('*') << setw(6) << " ";
else if ((x == fighter_x + 2) && (y == fighter_y))
cout << setfill(' ') << setw(6) << "* * ";
else if ((x == bullet_x) && (y == bullet_y))
cout << "|";
else if (x == enemy_x && y == enemy_y)
cout << "@";
else cout << " ";
}
cout << endl;
}
cout << setfill('#') << setw(width + 6) << "#" << endl;
cout << "難度:" << difficulty << endl;
cout << "生命:" << fighter << endl;
cout << "得分:" << score << endl;
}
void init() {
fighter_x = height / 2;//定義飛機的位置
fighter_y = width / 2;
enemy_x = 0;
enemy_y = fighter_y; //隨機定義敵機位置
bullet_x = -2;//定義子彈位置
bullet_y = fighter_y;
score = 0;//得分數
fighter = 3;//飛機生命數
hidecursor();
}
void OperateFighter() {
char input;
if (_kbhit()) {//檢查是否是否有鍵盤輸入,有回傳非0,無則回傳0
input = _getch();//根據用戶不同的輸入來移動
if (input == 'a') {
if (fighter_y > 1)
fighter_y--;//位置左移
}
else if (input == 'd') {
if (fighter_y < width - 1)
fighter_y++;//位置右移
}
else if (input == 'w') {
if (fighter_x > 0)
fighter_x--;//位置上移
}
else if (input == 's') {
if (fighter_x < height)
fighter_x++;//位置下移
}
if (input == ' ') {
bullet_x = fighter_x - 1;
bullet_y = fighter_y + 2;
}
}
}
void pcOperate() {//呼叫函式模擬人操作飛機戰斗
floatBullet();//呼叫floatBullet函式控制子彈移動
enemyFighter();//控制敵機移動速度
}
void floatBullet() {//控制子彈移動
if (bullet_x > -1)//判斷子彈是否在螢屏內
bullet_x--;//子彈上移
}
void enemyFighter() {
//用來控制敵機向下移動的速度,每隔十次回圈就移動一次敵機
static int speed = 0;
difficulty = "簡單";
if (score > 5) {
speed++;
difficulty = "普通";
}
if (score > 15) {
speed++;
difficulty = "困難";
}
if (speed < 10) {
speed += 2;
}
else {
enemy_x++;
speed = 0;
}
//擊中敵機后增加判斷,并增加變數score記錄游戲得分,敵機被擊中后會先消失,然后重新在隨機位置出現,
if (((bullet_x == enemy_x) && (bullet_y == enemy_y)) || ((bullet_x + 1 == enemy_x) &&
(bullet_y == enemy_y)) || ((bullet_x - 1 == enemy_x) && (bullet_y == enemy_y)))
{
score++;
enemy_x = -1;//產生新的飛機
enemy_y = rand() % (width - 5) + 3;//rand()函式生成亂數,但因為一般生成的亂數較大,因此做取余操作使其能在規定的寬度內生成
bullet_x = -2;//子彈無效
}
if ((enemy_x == fighter_x) && ((enemy_y == fighter_y) ||
(enemy_y == fighter_y + 1) || (enemy_y == fighter_y + 3) ||
(enemy_y == fighter_y + 4)) || ((enemy_x == fighter_x) &&
(enemy_y == fighter_y + 2)))
{
fighter--;
fighter_x = rand() % (height - 5) + 2;
fighter_y = rand() % (width - 5) + 2;
enemy_x = -1;
enemy_y = rand() % width;
lose();
}
if (enemy_x > height) {//如果敵機飛出螢屏則重新生成一架
score--;
enemy_x = -1;
enemy_y = rand() % width;
lose();
}
}
void zeroXy(int x, int y) {//實作函式清屏
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle, pos);
}
void hidecursor() {//隱藏游標
CONSOLE_CURSOR_INFO consor_info = { 1,0 };//第二個值為0隱藏游標
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consor_info);
}
void lose() {
if (fighter < 0 || score < 0) {
cout << endl;
cout << "**********************你輸了!*********************" << endl;
system("pause");
exit(0);
}
}
//mainfighter檔案
#include<iostream>
#include<conio.h>
#include<Windows.h>
#include<iomanip>
#include"fighter.h"
using namespace std;
int main() {
init();
while (1) {
drawPicture();
pcOperate();
OperateFighter();
}
system("pause");
}
運行截圖如下:
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/301369.html
標籤:其他
