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

C 語言實作跨平台終端機下雪動畫特效

     編輯:關於C語言

專案背景與目標

本專案實作一個在終端機中運行的下雪動畫,具備以下特色:

  • 跨平台支援:同時相容 GCC (Linux) 與 Visual Studio (Windows)
  • 動畫幀率:1 秒 40 幀(約 25ms/幀)
  • 雪花物理:具備 X/Y 軸速度,模擬自然飄落與左右擺動
  • 教學導向:適合作為 C 語言期末專題或圖形程式設計入門練習

下雪效果示意圖

核心架構設計

1. 跨平台抽象層

透過條件編譯處理平台差異:

#if defined(__GNUC__)
// Linux 實作
#include <unistd.h>
#define sleep_ms(m) usleep(m * 1000)
static void __curup(int height) {
    while (++i < height) printf("\033[1A");  // ANSI 轉義碼移動游標
}
#else
// Windows 實作
#include <Windows.h>
#define sleep_ms(m) Sleep(m)
static void __curup(int height) {
    COORD cr = {0,0};
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cr);
}
#endif

2. 螢幕緩衝區資料結構

使用一維陣列模擬二維像素矩陣,結構體一次性配置記憶體減少碎片:

struct screen {
    int frate;      // 幀週期(ms)
    int width;      // 螢幕寬度
    int height;     // 螢幕高度
    char *pix;      // 像素緩衝區:0=無雪花, 1+=雪花數量
};

// 一次 malloc 配置結構體 + 像素緩衝區
scr = malloc(sizeof(struct screen) + sizeof(char)*width*height);
scr->pix = ((char *)scr) + sizeof(struct screen);

3. 安全記憶體管理模式

雙重指標銷毀函式避免野指標:

void screen_destory(struct screen** pscr) {
    if (NULL == pscr || NULL == *pscr) return;
    free(*pscr);
    *pscr = NULL;  // 關鍵:釋放後立即置空
}

雪花演算法核心邏輯

第一行雪花生成(頂端)

#define _INT_SHEAD (1<<2)  // 每 4 格一個雪花
static void __snow_head(char* snow, int len) {
    memset(snow, 0, len);
    int r = 0;
    for (;;) {
        int t = rand() & (_INT_SHEAD - 1);  // 位運算取模,等價 rand() % 4
        if (r + t >= len) break;
        snow[r + t] = 1;
        r += _INT_SHEAD;
    }
}

後續行雪花位置計算(依賴上一行)

#define _INT_SWING 3  // 擺動範圍:-1, 0, +1
static void __snow_next(struct screen* scr, int idx) {
    int width = scr->width;
    char* psnow = scr->pix + width*(idx - 1);  // 上一行
    char* snow  = psnow + width;               // 當前行
    memset(snow, 0, width);

    for (int i = 0; i < width; ++i) {
        for (int t = psnow[i]; t > 0; --t) {   // 處理疊加雪花
            int j = i + rand() % _INT_SWING - 1;  // -1, 0, +1
            j = (j < 0) ? width - 1 : (j >= width ? 0 : j);  // 環狀邊界
            ++snow[j];
        }
    }
}

動畫主迴圈與幀率控制

int screen_draw_snow(struct screen* scr) {
    static int __speed = 0;
    if (++__speed != _INT_VSNOW) return 1;  // 速率控制

    __speed = 0;
    for (int idx = scr->height - 1; idx > 0; --idx)
        __snow_next(scr, idx);
    __snow_head(scr->pix, scr->width);
    return 0;
}

void __flash_snow_buffer(struct screen* scr, char* buf) {
    for (;; sleep_ms(scr->frate)) {
        if (screen_draw_snow(scr)) continue;  // 未到繪製時機

        // 將像素緩衝區轉為可列印字元
        int rt = 0;
        for (int i = 0; i < scr->height; ++i) {
            for (int j = 0; j < scr->width; ++j)
                buf[rt++] = scr->pix[i*scr->width + j] ? '*' : ' ';
            buf[rt++] = '\n';
        }
        buf[rt - 1] = '\0';
        puts(buf);
        __curup(scr->height);  // 游標回頂端,實現動畫覆蓋
    }
}

完整程式碼與執行方式

完整原始碼已整合於文章末尾(含跨平台巨集、資料結構、演算法實作與主程式)。

Windows (Visual Studio)

新增主控台專案,貼上程式碼按 F5 執行。

Windows 執行畫面

Linux (GCC)

gcc -g -Wall snow.c -o snow.out
./snow.out

Linux 執行畫面

編譯提示:Linux 需連結 -lm 數學庫(若使用 rand() 通常不需要),Windows 須確保專案設定為主控台應用程式。

延伸思考:C 語言的簡單與複雜

文中穿插探討 NULL、0、'\0'、"0"、false 的異同,以及 for(;;) 與 while(true) 的組合語言等價性——這正是 C 語言「簡單語法,深邃語義」的縮影,也是成為資深開發者的必修課。

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