首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

用 ncurses 打造貪食蛇遊戲:終端機 UI 程式設計入門實戰

     編輯:關於C語言

為什麼選 ncurses?

  • 跨平台:Linux、macOS、BSD、Windows (PDCurses/MinGW) 通用。
  • 無圖形介面依賴:純終端機 (SSH、Serial Console、Docker 容器) 即可運行。
  • 即時鍵盤輸入:nodelay()、keypad()、getch() 支援非阻塞、方向鍵、功能鍵。
  • 螢幕佈局控制:move()、addch()、addstr()、refresh()、clear() 精確控制游標與字元。
  • 色彩/屬性:start_color()、init_pair()、attron() 支援前景/背景色、粗體、底線。

核心資料結構


#define MAX_LEN 100
#define WIDTH 50
#define HEIGHT 20

typedef struct { int x, y; } Point;

typedef struct {
    Point body[MAX_LEN];
    int len;
    int dir; // 0=UP, 1=DOWN, 2=LEFT, 3=RIGHT
} Snake;

typedef struct {
    Point pos;
    bool exists;
} Food;

Snake snake;
Food food;
int score = 0;
int speed_us = 300000; // 300ms

ncurses 初始化與清理


void InitNcurses() {
    initscr();            // 初始化螢幕
    cbreak();             // 關閉行緩衝,字元即時可讀
    noecho();             // 不回顯輸入字元
    curs_set(0);          // 隱藏游標
    keypad(stdscr, TRUE); // 啟用功能鍵 (KEY_UP 等)
    nodelay(stdscr, TRUE); // getch() 非阻塞
    start_color();        // 啟用色彩
    init_pair(1, COLOR_GREEN, COLOR_BLACK);  // 蛇身
    init_pair(2, COLOR_RED, COLOR_BLACK);    // 食物
    init_pair(3, COLOR_YELLOW, COLOR_BLACK); // 牆壁/分數
}

void CleanupNcurses() {
    endwin(); // 恢復終端機狀態
}

繪圖函數


void DrawBorder() {
    attron(COLOR_PAIR(3));
    for (int x=0; x

遊戲邏輯核心


void InitGame() {
    snake.len = 3;
    snake.body[0] = (Point){WIDTH/2, HEIGHT/2};
    snake.body[1] = (Point){WIDTH/2-1, HEIGHT/2};
    snake.body[2] = (Point){WIDTH/2-2, HEIGHT/2};
    snake.dir = 3; // RIGHT
    score = 0;
    SpawnFood();
}

void SpawnFood() {
    do {
        food.pos.x = 1 + rand() % (WIDTH-2);
        food.pos.y = 1 + rand() % (HEIGHT-2);
        // 避免生成在蛇身上
        bool on_snake = false;
        for (int i=0; i= WIDTH-1 || next.y <= 0 || next.y >= HEIGHT-1)
        return true;
    // 撞自己
    for (int i=0; i0; i--)
        snake.body[i] = snake.body[i-1];
    snake.body[0] = next;

    // 吃食物
    if (food.exists && next.x == food.pos.x && next.y == food.pos.y) {
        food.exists = false;
        if (snake.len < MAX_LEN) snake.len++;
        score += 10;
        SpawnFood();
    }
}

void HandleInput() {
    int ch = getch();
    switch (ch) {
        case KEY_UP:    if (snake.dir != 1) snake.dir = 0; break;
        case KEY_DOWN:  if (snake.dir != 0) snake.dir = 1; break;
        case KEY_LEFT:  if (snake.dir != 3) snake.dir = 2; break;
        case KEY_RIGHT: if (snake.dir != 2) snake.dir = 3; break;
        case 'q': case 'Q': GameOver(); break;
    }
}

void GameOver() {
    nodelay(stdscr, FALSE); // 切回阻塞模式等待按鍵
    mvprintw(HEIGHT/2, WIDTH/2-5, "GAME OVER");
    mvprintw(HEIGHT/2+1, WIDTH/2-8, "Score: %d", score);
    mvprintw(HEIGHT/2+2, WIDTH/2-10, "Press any key to exit");
    refresh();
    getch();
    CleanupNcurses();
    exit(0);
}

主迴圈


int main() {
    srand(time(NULL));
    InitNcurses();
    InitGame();

    while (1) {
        HandleInput();
        UpdateSnake();
        RefreshAll();
        usleep(speed_us);
        // 可選:隨分數加速
        if (score > 100 && speed_us > 50000) speed_us -= 10000;
    }
    return 0; // 不會執行到
}

編譯與執行


# Linux (Debian/Ubuntu)
sudo apt-get install libncurses5-dev libncursesw5-dev
gcc -o snake snake.c -lncursesw -Wall -O2
./snake

# macOS
brew install ncurses
gcc -o snake snake.c -lncurses -Wall -O2

# Windows (MinGW + PDCurses)
# 下載 PDCurses,連結 pdcurses.lib
gcc -o snake.exe snake.c -lpdcurses -Wall -O2

進階擴充方向

功能實現要點
多關卡/地圖讀取文字檔地圖陣列,支援牆壁、傳送門、陷阱
障礙物/毒藥額外實體結構體,碰撞邏輯分類處理
高分榜持久化fopen 讀寫二進位/JSON,啟動時載入顯示
雙人對戰兩條蛇、分屏或同屏、獨立輸入處理 (WASD vs 方向鍵)
AI 自動遊玩BFS/A* 尋路至食物,避開自身與牆壁
色彩主題多組 init_pair,菜單切換
音效 (終端機蜂鳴器)beep() 或 printf("\a")

常見問題排查

現象原因解決
方向鍵無反應 / 亂碼未呼叫 keypad(stdscr, TRUE)初始化時啟用
畫面閃爍嚴重未用 clear() + refresh() 雙緩衝模式每幀完整重繪並單次 refresh
蛇身不顯示 / 位置錯誤座標系混淆 (x/y 對應 col/row)ncurses: mvaddch(row=y, col=x)
程式結束後終端機異常未呼叫 endwin()註冊 atexit(CleanupNcurses) 或信號處理
編譯找不到 ncurses.h未安裝開發套件apt install libncurses5-dev / brew install ncurses

結語

用 ncurses 寫貪食蛇,不僅能練習遊戲迴圈、狀態機、碰撞檢測、即時輸入,更能體會終端機 UI 程式設計的獨特魅力:無 GPU、無視窗系統、純字元也能跑出流暢互動體驗。這正是嵌入式裝置、伺服器管理工具、CLI 遊戲、TUI 框架 (如 ftxui, ratatui, textual) 的基石。建議以此為起點,嘗試實現 2048、Tetris、Roguelike 等更複雜的 TUI 專案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved