控制台飞机大战:飞机在底部左右移动,按空格开火,敌机从顶部下落,打中就得分。用二维字符画实现,纯标准 C。

1. 游戏世界:字符画

用 20×20 的字符画作为"屏幕":玩家飞机 ^,子弹 |,敌机 *。每帧清屏重绘:

#define W 20
#define H 20
char screen[H][W + 1];

void put(int y, int x, char ch) {
    if (y >= 0 && y < H && x >= 0 && x < W) screen[y][x] = ch;
}

void render(void) {
    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) printf("%c", screen[y][x]);
        printf("\n");
    }
}

2. 飞机、子弹与敌机

飞机用横坐标表示,子弹和敌机各一个数组(最多 20 个)。每步:子弹上移、敌机下移、检测碰撞:

int px = W / 2;                 // 玩家横坐标
int bullets[20], bcnt = 0;    // 子弹的 y 坐标(-1 表示空)
int enx[20], eny[20], ecnt = 0;

void update(void) {
    for (int i = 0; i < bcnt; i++) bullets[i]--;
    for (int i = 0; i < ecnt; i++) {
        eny[i]++;
        for (int j = 0; j < bcnt; j++)
            if (bullets[j] == eny[i] && j < 20) {
                // 命中:清除子弹和敌机
            }
    }
}

3. 完整代码

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

#define W 20
#define H 20
char screen[H][W + 1];
int px = W / 2;
int bullets[20], bcnt = 0;
int enx[20], eny[20], ecnt = 0;
int score = 0, lives = 3;

void put(int y, int x, char ch) {
    if (y >= 0 && y < H && x >= 0 && x < W) screen[y][x] = ch;
}

void render(void) {
    system("clear");   // Windows: system("cls")
    for (int y = 0; y < H; y++) {
        for (int x = 0; x < W; x++) printf("%c", screen[y][x]);
        printf("\n");
    }
    printf("得分 %d  生命 %d   a左 d右 空格开火 q退出\n", score, lives);
}

void spawn_enemy(void) {
    if (ecnt < 20 && (rand() % 3 == 0)) {
        enx[ecnt] = rand() % W;
        eny[ecnt] = 0;
        ecnt++;
    }
}

int main(void) {
    srand((unsigned)time(NULL));
    char key;
    while (lives > 0) {
        for (int y = 0; y < H; y++) {
            for (int x = 0; x < W; x++) screen[y][x] = ' ';
            screen[y][W] = '\0';
        }
        render();
        scanf(" %c", &key);
        if (key == 'q') break;
        if (key == 'a' && px > 0) px--;
        if (key == 'd' && px < W - 1) px++;
        if (key == ' ') { if (bcnt < 20) bullets[bcnt++] = H - 2; }

        for (int i = 0; i < bcnt; i++) bullets[i]--;
        spawn_enemy();
        for (int i = 0; i < ecnt; i++) eny[i]++;
        for (int i = 0; i < ecnt; i++)
            if (eny[i] >= H) { eny[i] = enx[i] = -1; lives--; }
        for (int i = 0; i < ecnt; i++) {
            for (int j = 0; j < bcnt; j++) {
                if (bullets[j] >= 0 && bullets[j] == eny[i] && enx[i] >= 0) {
                    score += 10;
                    bullets[j] = -1;
                    enx[i] = eny[i] = -1;
                    break;
                }
            }
        }
        // 碰撞:敌机到玩家行
        for (int i = 0; i < ecnt; i++)
            if (eny[i] == H - 1 && enx[i] == px) { enx[i] = eny[i] = -1; lives--; }

        put(H - 1, px, '^');
        for (int i = 0; i < bcnt; i++)
            if (bullets[i] >= 0) put(bullets[i], px + 0, '|');
        for (int i = 0; i < ecnt; i++)
            if (enx[i] >= 0 && eny[i] >= 0) put(eny[i], enx[i], '*');
    }
    printf("游戏结束,得分: %d\n", score);
    return 0;
}

4. 运行与常见问题

保存为 plane.c,编译运行。常见问题:①敌机叠在一起——生成时检查是否已有敌机占位;②子弹打不到敌机——子弹从 H-2 出发,敌机坐标要匹配;③子弹越界——坐标减到负数后不再绘制。

💡 改进方向:①敌机自动左右移动;②多种敌机类型;③双发/连发子弹;④爆炸动画;⑤关卡速度提升。