開飛機打飛機
初學C語言總覺得不能做些什麼好玩的,這個小遊戲只需 “一點點” (千真萬確)C語言知識就能完成!
總計不到200行的非空白代碼(沒有強行壓縮行數)
操作說明:
W
、S
、A
、D
控制 上 、下、左、右 方向,空格
攻擊- 每擊中一架敵機增加1分,界面下方顯示實時分數
- 撞到敵機後顯示
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語言遊戲課程的基礎上總結改進完成的,細節解釋還請移步童老師的課程,這裏就不作拾人牙慧的贅述了。