C語言|控制檯小遊戲|打飛機(基礎功能版)

開飛機打飛機

初學C語言總覺得不能做些什麼好玩的,這個小遊戲只需 “一點點” (千真萬確)C語言知識就能完成!
總計不到200行的非空白代碼(沒有強行壓縮行數)

在這裏插入圖片描述

操作說明:

  1. WSAD 控制 上 、下、左、右 方向,空格 攻擊
  2. 每擊中一架敵機增加1分,界面下方顯示實時分數
  3. 撞到敵機後顯示 game over! 2.5秒(時間可更改)

  • 子彈連發
  • 移動的同時發射子彈
  • 飛機撞上敵機結束遊戲
  • 可通過更改相關變量的值來調節敵機飛行速度、敵機密度、敵機刷新速度等
  • 相比與上一個極度簡陋版,功能基本完善

  • 畫面顯示:遊戲畫面信息存入二維數組:數組下標映射遊戲中位置座標,數組元素的值(0,1,2,3…)分別表示遊戲場景中不同的對象(空白處,飛機,子彈,敵機…),遍歷數組根據不同的值輸出遊戲畫面。每次輸出前將光標調至首行首列處,覆蓋之前的輸出畫面,達到刷新遊戲畫面的效果。
  • 飛機移動:監測遊戲按鍵是否按下來修改相應數據。
  • 敵機移動:對敵機豎直座標進行自增運算,達到不斷移動的效果。
  • 碰撞消失:(飛機、敵機、子彈)每次移動先判斷下個位置是否會相撞。

所需C語言知識真的不多,感興趣的C程序員朋友來複刻吧!

以下是詳細註釋的完整源代碼:

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <windows.h>

#define  high 25   //畫布高
#define width 60   //畫布寬
#define  border -1    //邊界
#define   blank  0    //空白
#define   plane  1    //飛機
#define  bullet  2    //子彈
#define   enemy  3    //敵機
#define destroy  4    //摧毀標記

int canvas[high + 2][width + 2];  //遊戲場景的高和寬
int pos_h, pos_w;   //飛機位置
int enemynum;    //敵機數量
int interval; //同個計次來模擬時間間隔
int itv_move; //敵機移動的時間間隔
int itv_new; //敵機刷新的時間間隔
int score;  //分數
int IsOver;  //判斷遊戲是否結束

void Startup();   //遊戲數值初始化
void Show();    //遊戲界面輸出
void UpdateInput();     //因輸入導致的遊戲狀態更新
void UpdateNormal();    //與輸入無關的遊戲狀態更新
void HideCursor();		//隱藏光標
void gotoxy(int x, int y);		//回調光標		

int main() {
	Startup();  //初始化
	while (IsOver) {   //遊戲循環
		UpdateInput();
		UpdateNormal();
		Show();
	}
	printf("\t\tgame over!\n");
	Sleep(2500);    //暫停遊戲結束界面(毫秒)
	system("pause");
	return 0;
}
void Startup() {  //遊戲數值初始化
	IsOver = 1;
	score = 0;  //初始化分數
	for (int i = 0; i < high + 2; i++) {      //初始化畫布
		for (int j = 0; j < width + 2; j++) {
			if (i == 0 || i == high + 1 ||
				j == 0 || j == width + 1) {
				canvas[i][j] = border;
			}
			else canvas[i][j] = blank;
		}
	}
	pos_h = high / 2;    //初始化飛機豎直座標
	pos_w = width / 2;     //初始化飛機水平座標
	canvas[pos_h][pos_w] = plane;  //初始化飛機位置
	enemynum = 3;       //敵機數量
	srand(time(NULL));
	interval = 4;      //初始化時間間隔計數
	itv_move = 5;      //初始化敵機移動時間間隔
	itv_new = 40;     //初始化敵機刷新時間間隔
}
void Show() {  //遊戲界面輸出
	HideCursor();   //隱藏光標
	gotoxy(1, 1);    //回調光標、刷新畫面
	for (int i = 0; i < high + 2; i++) {
		for (int j = 0; j < width + 2; j++) {
			if (canvas[i][j] == plane) { //當前位置爲飛機位置
				printf("*");
			}
			else if (canvas[i][j] == bullet) {  //當前位置爲子彈位置
				printf("|");
			}
			else if (canvas[i][j] == enemy) {  //當前位置爲敵機位置
				printf("@");
			}
			else if (canvas[i][j] == border) {  //當前位置爲邊界
				printf("#");
			}
			else if (canvas[i][j] == blank) {  //當前位置無物,且在邊界內
				printf(" ");
			}
			else if (canvas[i][j] == destroy) {  //當前位置無物,且在邊界內
				printf("x");
			}
		}
		printf("\n");
	}
	printf("\n得分:%d", score);
}
void UpdateInput() {  //因輸入導致的遊戲狀態更新
	char key_W = GetKeyState('W'),  //監測 W 鍵是否按下
		key_S = GetKeyState('S'),  //監測 S 鍵是否按下
		key_A = GetKeyState('A'),  //監測 A 鍵是否按下
		key_D = GetKeyState('D'),  //監測 D 鍵是否按下
		key_attack = GetKeyState(' ');  //監測 空格 鍵是否按下
	if (kbhit()) { //當有鍵按下時  //vc++6.0以上版本爲 _kbhit()
		if (key_W < 0) {  //當按下 W 鍵,上移
			if (pos_h > 1) {
				canvas[pos_h][pos_w] = blank;
				if (canvas[pos_h - 1][pos_w] == enemy) {  //下個位置是敵機,撞毀
					canvas[pos_h - 1][pos_w] = destroy;
					IsOver = 0;
				}
				else canvas[--pos_h][pos_w] = plane;
			}
		}
		if (key_S < 0) {  //當按下 S 鍵,下移
			if (pos_h < high) {
				canvas[pos_h][pos_w] = blank;
				if (canvas[pos_h + 1][pos_w] == enemy) {  //下個位置是敵機,撞毀
					canvas[pos_h + 1][pos_w] = destroy;
					IsOver = 0;
				}
				else canvas[++pos_h][pos_w] = plane;
			}
		}
		if (key_A < 0) {  //當按下 A 鍵,左移
			if (pos_w > 1) {
				canvas[pos_h][pos_w] = blank;
				if (canvas[pos_h][pos_w - 1] == enemy) {  //下個位置是敵機,撞毀
					canvas[pos_h][pos_w - 1] = destroy;
					IsOver = 0;
				}
				else canvas[pos_h][--pos_w] = plane;
			}
		}
		if (key_D < 0) {  //當按下 D 鍵,右移
			if (pos_w < width) {
				canvas[pos_h][pos_w] = blank;
				if (canvas[pos_h][pos_w + 1] == enemy) {  //下個位置是敵機,撞毀
					canvas[pos_h][pos_w + 1] = destroy;
					IsOver = 0;
				}
				else canvas[pos_h][++pos_w] = plane;
			}
		}
		if (key_attack < 0) {   //當按下空格鍵,發射子彈
			if (pos_h != 1)canvas[pos_h - 1][pos_w] = bullet;
		}
	}
}
void UpdateNormal() {  //與輸入無關的遊戲狀態更新
	int temp[high + 2][width + 2];  //用來判斷原位置的臨時數組
	for (int i = 1; i <= high; i++) {
		for (int j = 1; j <= width; j++) {
			temp[i][j] = canvas[i][j];
		}
	}
	for (int i = 1; i <= high; i++) {  //遍歷臨時數組,修改畫布
		for (int j = 1; j <= width; j++) {
			if (temp[i][j] == enemy && interval % itv_move == 0) { //當前位置爲敵機
				canvas[i][j] = blank;
				if (temp[i + 1][j] == bullet) {  //下面爲子彈,敵機被擊中
					canvas[i + 1][j] = blank;
					score++;
					printf("\a");  //擊中音效
				}
				else if (i < high) {
					canvas[i + 1][j] = enemy;
				}
				if (i + 1 == pos_h && j == pos_w) {  //下面爲飛機,玩家飛機被撞毀
					canvas[i + 1][j] = destroy;
					IsOver = 0;
				}
			}
			if (temp[i][j] == bullet) { //當前位置爲子彈
				canvas[i][j] = blank;
				if (temp[i - 1][j] == enemy) {  //下個位置是敵機,敵機被擊毀
					canvas[i - 1][j] = blank;
					score++;
					printf("\a");
				}
				else if (i > 1) {
					canvas[i - 1][j] = bullet;
				}
			}
		}
	}
	if (interval % itv_new == 0)  //剛好到時間間隔
		for (int i = 0; i < enemynum; i++) {   //新增敵機羣
			canvas[rand() % 2 + 1][rand() % width + 1] = enemy;
		}
	if (interval <= 100) {  //時間間隔計次
		interval++;
	}
	else {    //時間間隔計次清零
		interval = 0;
	}
}
void gotoxy(int x, int y) { //回調光標
	COORD pos;
	pos.X = x - 1;
	pos.Y = y - 1;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void HideCursor() { //隱藏光標函數
	CONSOLE_CURSOR_INFO cursor;
	cursor.bVisible = FALSE;
	cursor.dwSize = sizeof(cursor);
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorInfo(handle, &cursor);
}

以上內容是在觀看河海大學童晶老師的C語言遊戲課程的基礎上總結改進完成的,細節解釋還請移步童老師的課程,這裏就不作拾人牙慧的贅述了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章