C語言如何 實現 下雪效果

題外話 程序員

 

前言算法

1.本文主要圍繞 如何 在 控制檯上 下起 一場 只有本身能看見的雪shell

2.是個簡易跨平臺的,主要是C語言編程

3.動畫 採用 1s 40幀, 雪花具備 x軸速度和y軸速度api

4.比較簡單,能夠給學生做爲C語言結課做業吧. 服務器

 

正文數據結構

1.1 先簡單處理跨平臺函數

   本文寫做動機,仍是感謝一下大學的啓蒙老師,讓我知道了有條路叫作程序員,能夠做爲工做生存下去.那就上代碼了.oop

首先代碼定位 是 面向 簡單跨平臺,至少讓 gcc 和 vs 可以跑起來. 動畫

其實跨平臺都是嚼頭, 說白了就是一些醜陋的宏. 真但願全部系統合二爲一,採用統一的標準api 設計,但這是不可能的,就至關於很早以前的電視制式同樣.

那麼咱們先看 圍繞跨平臺的宏

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

/*
* 時間 : 2015年12月26日11:43:22
* 描述 : 應該算過節吧,今天,寫了個雪花特效 代碼,
*            送給 大學啓蒙 蘆老師
*                        學生王志 祝福上
* */

/*
* 清除屏幕的shell 命令/控制檯命令,還有一些依賴平臺的實現
* 若是定義了 __GNUC__ 就假定是 使用gcc 編譯器,爲Linux平臺
*    不然 認爲是 Window 平臺
*/
#if defined(__GNUC__)
//下面是依賴 Linux 實現
#include <unistd.h>
#define sleep_ms(m) \
        usleep(m * 1000)

//向上移動光標函數 Linux
static void __curup(int height)
{
    int i = -1;
    while (++i<height)
        printf("\033[1A"); //先回到上一行  
}
#else 

// 建立等待函數 1s 60 幀 至關於 16.7ms => 1幀, 咱們取16ms
// 咱麼的這屏幕 推薦 1s 25幀吧 40ms
// 這裏建立等待函數 以毫秒爲單位 , 須要依賴操做系統實現
#include <Windows.h>
#define sleep_ms(m) \
        Sleep(m)

//向上移動光標
static void __curup(int height)
{
    COORD cr = {0,0};
    // GetStdHandle(STD_OUTPUT_HANDLE) 獲取屏幕對象, 設置光標
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cr);
}
#endif /*__GNUC__ 跨平臺的代碼都很醜陋 */

首先是 sleep_ms 這個宏, 傳入一個毫秒數,讓操做系統等待.

對於__curup 實現的很差. 功能是 讓 控制檯當前光標移動到 上面的 height 位置,對於 window直接移動到第一行(0,0)位置.

上面一共用了 5個頭文件 仍是容易的代碼. string.h 主要用的是 memset 函數, 讓一段內存初始化,用0填充.

對於time.h 主要是爲了 初始化時間種子,方便每次運行都不同.

    // 初始化隨機數種子,改變雪花軌跡
    srand((unsigned)time(NULL));

 

1.2 再說主業務代碼

      這裏程序員運行的主業務,先說一說這裏用的數據結構 以下

// 定義初始屏幕的寬高像素宏
#define _INT_WIDTH        (100)
#define _INT_HEIGHT        (50)
// 屏幕刷新幀的速率
#define _INT_FRATE        (40)
// 雪花飄落的速率,相對於 屏幕刷新幀 的倍數
#define _INT_VSNOW        (10)

/*
* 錯誤處理宏,msg必須是""括起來的字符串常量
* __FILE__        : 文件全路徑
* __func__        : 函數名
* __LINE__        : 行數行
* __VA_ARGS__    : 可變參數宏,
* ##表示直接鏈接, 例如 a##b <=> ab
*/
#define cerr(msg,...) \
    fprintf(stderr, "[%s:%s:%d]" msg "\n",__FILE__,__func__,__LINE__,##__VA_ARGS__);

/*
*  屏幕結構體, 具備 寬高
*  frate  : 繪製一幀的週期, 單位是 毫秒
*  width  : 屏幕的寬,基於窗口的左上角(0,0)
*  height : 屏幕的高
*  pix    : 用一維模擬二維 主要結構以下
*             0 0 0 1 0 0 1 0 1 0
*             0 1 0 1 0 1 0 1 2 0
*             . . .
*             => 0表示沒像素, 1表示1個像素,2表示2個像素....
*/
struct screen {
    int frate; // 也能夠用 unsigned 結構
    int width;
    int height;
    char *pix;
};

建立了一個繪圖對象 struct screen 這裏 構建這個結構體的時候用了下面一個技巧

    //後面是 爲 scr->pix 分配的內存 width*height
    scr = malloc(sizeof(struct screen) + sizeof(char)*width*height);

一次分配兩個內存空間.下面是主要實現的api 對象

/*
* 建立一個 屏幕結構指針 返回
*
* int frate    : 繪製一幀的週期
* int width    : 屏幕寬度
* int height    : 屏幕高度
* return        : 指向屏幕結構的指針
* */
struct screen* screen_create(int frate, int width, int height);

/*
* 銷燬一個 屏幕結構指針, 併爲其置空
* struct screen** : 指向 屏幕結構指針的指針, 二級銷燬一級的
* */
void screen_destory(struct screen** pscr);

/**
* 屏幕繪製函數,主要生成一個雪花效果
*
* struct screen* : 屏幕數據
* return          : 0表示能夠繪製了,1表示圖案不變
*/
int screen_draw_snow(struct screen* scr);

/**
* 屏幕繪製動畫效果, 繪製雪花動畫
*
* struct screen* : 屏幕結構指針
*/
void screen_flash_snow(struct screen* scr);

建立銷燬, 繪製一個雪花界面, 繪製雪花動畫效果的api. 其實都很類似,用opengl 庫, 主要讓咱們省略了須要單獨和操做系統顯示層打交道工做.

這裏介紹一下,我的 一個 簡單避免 野指針的 的方法, 具體看下面實現

/*
* 銷燬一個 屏幕結構指針, 併爲其置空
* struct screen** : 指向 屏幕結構指針的指針, 二級銷燬一級的
* */
void
screen_destory(struct screen** pscr)
{
    if (NULL == pscr || NULL == *pscr)
        return;
    free(*pscr);
    // 避免野指針
    *pscr = NULL;
}

在執行以後置空,由於C程序員對NULL必定要敏感,造成條件反射. 和你們開個玩笑 ,

 

請問 :
      C 語言中, NULL , 0 , '\0' , "0", false  有什麼異同 ?

 

歡迎同行,在招聘的時候問問,應聘初級開發工做者. 爲何C須要扣的那麼細. 由於其它語言.你不明白是什麼,

你能夠用的很好. 可是C你寫的代碼,若是不知道會有怎樣的結果,那麼 線上就一大片服務器直接崩掉.並且還很難找出

問題所在. 由於C很簡單,越簡單就是越複雜.就越須要專業的維護人員.致使它成了'玩具'.

最後看一下 主業務

 

// 主函數,主業務在此運行
int main(int argc, char *argv[])
{
    struct screen* scr = NULL;

    //建立一個屏幕對象
    scr = screen_create(_INT_FRATE, _INT_WIDTH, _INT_HEIGHT);
    if (NULL == scr)
        exit(EXIT_FAILURE);

    //繪製雪花動畫
    screen_flash_snow(scr);

    //銷燬這個屏幕對象
    screen_destory(&scr);

    return 0;
}

仍是很是容易看懂的, 建立一個屏幕對象,繪製雪花效果.銷燬屏幕對象.

 

1.3 說一寫 接口的實現細節

先看幾個簡單的api 實現,建立和銷魂代碼以下,很直白.

/*
* 建立一個 屏幕結構指針 返回
*
* int frate    : 繪製一幀的週期
* int width    : 屏幕寬度
* int height    : 屏幕高度
* return        : 指向屏幕結構的指針
* */
struct screen*
    screen_create(int frate, int width, int height)
{
    struct screen *scr = NULL;

    if (frate<0 || width <= 0 || height <= 0) {
        cerr("[WARNING]check is frate<0 || width<=0 || height<=0 err!");
        return NULL;
    }

    //後面是 爲 scr->pix 分配的內存 width*height
    scr = malloc(sizeof(struct screen) + sizeof(char)*width*height);
    if (NULL == scr) {
        cerr("[FATALG]Out of memory!");
        return NULL;
    }
    scr->frate = frate;
    scr->width = width;
    scr->height = height;
    //減小malloc次數,malloc消耗很大,內存泄露呀,內存碎片呀
    scr->pix = ((char *)scr) + sizeof(struct screen);

    return scr;
}

/*
* 銷燬一個 屏幕結構指針, 併爲其置空
* struct screen** : 指向 屏幕結構指針的指針, 二級銷燬一級的
* */
void
screen_destory(struct screen** pscr)
{
    if (NULL == pscr || NULL == *pscr)
        return;
    free(*pscr);
    // 避免野指針
    *pscr = NULL;
}

後面說一下 如何 繪製 屏幕中雪花

主要算法 是

a.有個屏幕 w x h

b.屏幕從上面第一行 出雪花 , 出雪花 位置是隨機的[0,w], 可是有個距離,這個距離內只有一個雪花

c.下一行 雪花 依賴上一行雪花的生成, 每一個雪花在能夠飄動的時候, 只能 在[-1,1] 範圍內

d.實現動畫 效果 就是 每畫一幀就等待 一段時間

 

下面看具體一點的 a

    //建立一個屏幕對象
    scr = screen_create(_INT_FRATE, _INT_WIDTH, _INT_HEIGHT);

scr對象就是咱們的建立屏幕. _INT_WIDTH 和 _INT_HEIGHT 就是屏幕大小. 對於_INT_FRATE 表示繪製一幀時間.

 

b實現 代碼以下:

//構建開頭 的雪花,下面宏表示每 _INT_SHEAD 個步長,一個雪花,須要是2的冪
//static 能夠理解爲 private, 宏,位操做代碼多了確實難讀
#define _INT_SHEAD (1<<2)
static void __snow_head(char* snow, int len)
{
    int r = 0;

    //數據須要清空
    memset(snow, 0, len);
    for (;;) {
        //取餘一個技巧 2^3 - 1 = 7 => 111 , 並就是取餘數
        int t = rand() & (_INT_SHEAD - 1);
        if (r + t >= len)
            break;
        snow[r + t] = 1;
        r += _INT_SHEAD;
    }
}
#undef _INT_SHEAD

技巧如上,能夠看說明. 這裏 科普一下, 對於 for(;;) {} 和 while(true) {} 異同.

for(;;) {} 和 while(true) {} 這兩段代碼轉成彙編是同樣的, 不同 的是 強加的意願. 第一個 但願 跳過 檢測步驟 速度更快一點.

再擴展一點.

//另外一種 循環語句, goto 仍是 很強大實用的
__for_loop:
 
     if(false)
        goto __for_break;       
 
goto __for_loop;
__for_break:

能夠再擴展深一點, 還有一種 api 比 這個goto 還NB. 有機會分享. 特別強大, 是異常處理程序本質.

 

對於c.

//經過 上一個 scr->pix[scr->width*(idx-1)] => scr->pix[scr->width*idx]
//下面的宏 規定 雪花左右搖擺 0 向左一個像素, 1 表示 不變, 2表示向右一個像素
#define _INT_SWING (3)
static void __snow_next(struct screen* scr, int idx)
{
    int width = scr->width;
    char* psnow = scr->pix + width*(idx - 1);
    char* snow = psnow + width;
    int i, j, t; // i索引, j保存下一個瞬間雪花的位置,t 臨時補得,解決雪花重疊問題


                 //爲當前行重置
    memset(snow, 0, width);
    //經過上一次雪花位置 計算下一次雪花位置
    for (i = 0; i<width; ++i) {
        for (t = psnow[i]; t>0; --t) { // 雪花能夠重疊
                                       // rand()%_INT_SWING - 1 表示 雪花 橫軸的偏移量,相對上一次位置
            j = i + rand() % _INT_SWING - 1;
            j = j<0 ? width - 1 : j >= width ? 0 : j; // j若是越界了,左邊越界讓它到右邊,右邊越界到左邊
            ++snow[j];
        }
    }
}

下一行雪花 依賴 上一行雪花, 這裏 有點像插入排序.

總體的繪製代碼 以下

/**
* 屏幕繪製函數,主要生成一個雪花效果
*
* struct screen* : 屏幕數據
* return          : 0表示能夠繪製了,1表示圖案不變
*/
int
screen_draw_snow(struct screen* scr)
{
    // 靜態變量,默認初始化爲0,每次都共用
    static int __speed = 0;
    int idx;

    if (++__speed != _INT_VSNOW)
        return 1;

    //下面 就是 到了雪花飄落的時刻了 既 __speed == _INT_VSNOW
    __speed = 0;

    //這裏從新構建雪花界面,先構建頭部,再從尾部開始構建
    for (idx = scr->height - 1; idx > 0; --idx)
        __snow_next(scr, idx);

    //構建頭部
    __snow_head(scr->pix, scr->width);

    return 0;
}

繪製了一個屏幕對象的雪花. __speed 記錄 繪製次數, _INT_VSNOW 控制繪製速率

 

d 的實現代碼 以下

首先實現一個 銷燬屏幕代碼和 繪製代碼

 

//buf 保存scr 中pix 數據,構建後爲 (width+1)*height, 後面宏是雪花圖案
#define _CHAR_SNOW '*'
static void __flash_snow_buffer(struct screen* scr, char* buf)
{
    int i, j, rt;
    int height = scr->height, width = scr->width;
    int frate = scr->frate; //刷新的幀頻率    

                            //每次都等一下
    for (;;sleep_ms(frate)) {
        //開始繪製屏幕
        rt = screen_draw_snow(scr);
        if (rt)
            continue;

        for (i = 0;i<height; ++i) {
            char* snow = scr->pix + i*width;
            for (j = 0; j<width; ++j)
                buf[rt++] = snow[j] ? _CHAR_SNOW : ' ';
            buf[rt++] = '\n';
        }
        buf[rt - 1] = '\0';

        //正式繪製到屏幕上
        puts(buf);

        //清空老屏幕,屏幕光標回到最上面
        __curup(height);
    }
}
#undef _CHAR_SNOW

這裏 sleep_ms(frate); 是等待時間,不然太快, 人眼看不見.

繪製原理是 讓屏幕轉成控制檯可以認識的字符. 塞入到buf 中.

__curup(height); 讓繪製光標回到開頭.

後面還有一段 代碼實現

/**
* 屏幕繪製動畫效果, 繪製雪花動畫
*
* struct screen* : 屏幕結構指針
*/
void
screen_flash_snow(struct screen* scr)
{
    char* buf = NULL;
    // 初始化隨機數種子,改變雪花軌跡
    srand((unsigned)time(NULL));

    buf = malloc(sizeof(char)*(scr->width + 1)*scr->height);
    if (NULL == buf) {
        cerr("[FATAL]Out of memory!");
        exit(EXIT_FAILURE);
    }

    __flash_snow_buffer(scr, buf);

    //1.這裏理論上不會執行到這,沒加控制器. 2.對於buf=NULL,這種代碼 能夠省掉,看編程習慣
    free(buf);
    buf = NULL;
}

這種雙函數實現一個功能技巧用的也不少. 例如寫快速排序代碼, 就是這樣.

到這裏 咱們 設計和實現都完成了.

 

2.代碼效果展現

2.1 window 上展現

使用VS新建一個控制檯項目,F5就能夠了效果以下

是動態的.

 

2.2 對於Linux

直接使用

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

運行效果以下

 

到這裏 , C語言實現雪花效果就如上了.

 

2.3 完整的代碼展現. 感謝 有你,一路同行.

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

/*
* 時間 : 2015年12月26日11:43:22
* 描述 : 應該算過節吧,今天,寫了個雪花特效 代碼,
*            送給 大學啓蒙 蘆老師
*                        學生王志 祝福上
* */

/*
* 清除屏幕的shell 命令/控制檯命令,還有一些依賴平臺的實現
* 若是定義了 __GNUC__ 就假定是 使用gcc 編譯器,爲Linux平臺
*    不然 認爲是 Window 平臺
*/
#if defined(__GNUC__)
//下面是依賴 Linux 實現
#include <unistd.h>
#define sleep_ms(m) \
        usleep(m * 1000)

//向上移動光標函數 Linux
static void __curup(int height)
{
    int i = -1;
    while (++i<height)
        printf("\033[1A"); //先回到上一行  
}
#else 

// 建立等待函數 1s 60 幀 至關於 16.7ms => 1幀, 咱們取16ms
// 咱麼的這屏幕 推薦 1s 25幀吧 40ms
// 這裏建立等待函數 以毫秒爲單位 , 須要依賴操做系統實現
#include <Windows.h>
#define sleep_ms(m) \
        Sleep(m)

//向上移動光標
static void __curup(int height)
{
    COORD cr = {0,0};
    // GetStdHandle(STD_OUTPUT_HANDLE) 獲取屏幕對象, 設置光標
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cr);
}
#endif /*__GNUC__ 跨平臺的代碼都很醜陋 */

// 定義初始屏幕的寬高像素宏
#define _INT_WIDTH        (100)
#define _INT_HEIGHT        (50)
// 屏幕刷新幀的速率
#define _INT_FRATE        (40)
// 雪花飄落的速率,相對於 屏幕刷新幀 的倍數
#define _INT_VSNOW        (10)

/*
* 錯誤處理宏,msg必須是""括起來的字符串常量
* __FILE__        : 文件全路徑
* __func__        : 函數名
* __LINE__        : 行數行
* __VA_ARGS__    : 可變參數宏,
* ##表示直接鏈接, 例如 a##b <=> ab
*/
#define cerr(msg,...) \
    fprintf(stderr, "[%s:%s:%d]" msg "\n",__FILE__,__func__,__LINE__,##__VA_ARGS__);

/*
*  屏幕結構體, 具備 寬高
*  frate  : 繪製一幀的週期, 單位是 毫秒
*  width  : 屏幕的寬,基於窗口的左上角(0,0)
*  height : 屏幕的高
*  pix    : 用一維模擬二維 主要結構以下
*             0 0 0 1 0 0 1 0 1 0
*             0 1 0 1 0 1 0 1 2 0
*             . . .
*             => 0表示沒像素, 1表示1個像素,2表示2個像素....
*/
struct screen {
    int frate; // 也能夠用 unsigned 結構
    int width;
    int height;
    char *pix;
};

/*
* 建立一個 屏幕結構指針 返回
*
* int frate    : 繪製一幀的週期
* int width    : 屏幕寬度
* int height    : 屏幕高度
* return        : 指向屏幕結構的指針
* */
struct screen* screen_create(int frate, int width, int height);

/*
* 銷燬一個 屏幕結構指針, 併爲其置空
* struct screen** : 指向 屏幕結構指針的指針, 二級銷燬一級的
* */
void screen_destory(struct screen** pscr);

/**
* 屏幕繪製函數,主要生成一個雪花效果
*
* struct screen* : 屏幕數據
* return          : 0表示能夠繪製了,1表示圖案不變
*/
int screen_draw_snow(struct screen* scr);

/**
* 屏幕繪製動畫效果, 繪製雪花動畫
*
* struct screen* : 屏幕結構指針
*/
void screen_flash_snow(struct screen* scr);

// 主函數,主業務在此運行
int main(int argc, char *argv[])
{
    struct screen* scr = NULL;

    //建立一個屏幕對象
    scr = screen_create(_INT_FRATE, _INT_WIDTH, _INT_HEIGHT);
    if (NULL == scr)
        exit(EXIT_FAILURE);

    //繪製雪花動畫
    screen_flash_snow(scr);

    //銷燬這個屏幕對象
    screen_destory(&scr);

    return 0;
}

/*
* 建立一個 屏幕結構指針 返回
*
* int frate    : 繪製一幀的週期
* int width    : 屏幕寬度
* int height    : 屏幕高度
* return        : 指向屏幕結構的指針
* */
struct screen*
    screen_create(int frate, int width, int height)
{
    struct screen *scr = NULL;

    if (frate<0 || width <= 0 || height <= 0) {
        cerr("[WARNING]check is frate<0 || width<=0 || height<=0 err!");
        return NULL;
    }

    //後面是 爲 scr->pix 分配的內存 width*height
    scr = malloc(sizeof(struct screen) + sizeof(char)*width*height);
    if (NULL == scr) {
        cerr("[FATALG]Out of memory!");
        return NULL;
    }
    scr->frate = frate;
    scr->width = width;
    scr->height = height;
    //減小malloc次數,malloc消耗很大,內存泄露呀,內存碎片呀
    scr->pix = ((char *)scr) + sizeof(struct screen);

    return scr;
}

/*
* 銷燬一個 屏幕結構指針, 併爲其置空
* struct screen** : 指向 屏幕結構指針的指針, 二級銷燬一級的
* */
void
screen_destory(struct screen** pscr)
{
    if (NULL == pscr || NULL == *pscr)
        return;
    free(*pscr);
    // 避免野指針
    *pscr = NULL;
}

//構建開頭 的雪花,下面宏表示每 _INT_SHEAD 個步長,一個雪花,須要是2的冪
//static 能夠理解爲 private, 宏,位操做代碼多了確實難讀
#define _INT_SHEAD (1<<2)
static void __snow_head(char* snow, int len)
{
    int r = 0;

    //數據須要清空
    memset(snow, 0, len);
    for (;;) {
        //取餘一個技巧 2^3 - 1 = 7 => 111 , 並就是取餘數
        int t = rand() & (_INT_SHEAD - 1);
        if (r + t >= len)
            break;
        snow[r + t] = 1;
        r += _INT_SHEAD;
    }
}
#undef _INT_SHEAD

//經過 上一個 scr->pix[scr->width*(idx-1)] => scr->pix[scr->width*idx]
//下面的宏 規定 雪花左右搖擺 0 向左一個像素, 1 表示 不變, 2表示向右一個像素
#define _INT_SWING (3)
static void __snow_next(struct screen* scr, int idx)
{
    int width = scr->width;
    char* psnow = scr->pix + width*(idx - 1);
    char* snow = psnow + width;
    int i, j, t; // i索引, j保存下一個瞬間雪花的位置,t 臨時補得,解決雪花重疊問題


                 //爲當前行重置
    memset(snow, 0, width);
    //經過上一次雪花位置 計算下一次雪花位置
    for (i = 0; i<width; ++i) {
        for (t = psnow[i]; t>0; --t) { // 雪花能夠重疊
                                       // rand()%_INT_SWING - 1 表示 雪花 橫軸的偏移量,相對上一次位置
            j = i + rand() % _INT_SWING - 1;
            j = j<0 ? width - 1 : j >= width ? 0 : j; // j若是越界了,左邊越界讓它到右邊,右邊越界到左邊
            ++snow[j];
        }
    }
}

/**
* 屏幕繪製函數,主要生成一個雪花效果
*
* struct screen* : 屏幕數據
* return          : 0表示能夠繪製了,1表示圖案不變
*/
int
screen_draw_snow(struct screen* scr)
{
    // 靜態變量,默認初始化爲0,每次都共用
    static int __speed = 0;
    int idx;

    if (++__speed != _INT_VSNOW)
        return 1;

    //下面 就是 到了雪花飄落的時刻了 既 __speed == _INT_VSNOW
    __speed = 0;

    //這裏從新構建雪花界面,先構建頭部,再從尾部開始構建
    for (idx = scr->height - 1; idx > 0; --idx)
        __snow_next(scr, idx);

    //構建頭部
    __snow_head(scr->pix, scr->width);

    return 0;
}

//buf 保存scr 中pix 數據,構建後爲 (width+1)*height, 後面宏是雪花圖案
#define _CHAR_SNOW '*'
static void __flash_snow_buffer(struct screen* scr, char* buf)
{
    int i, j, rt;
    int height = scr->height, width = scr->width;
    int frate = scr->frate; //刷新的幀頻率    

                            //每次都等一下
    for (;;sleep_ms(frate)) {
        //開始繪製屏幕
        rt = screen_draw_snow(scr);
        if (rt)
            continue;

        for (i = 0;i<height; ++i) {
            char* snow = scr->pix + i*width;
            for (j = 0; j<width; ++j)
                buf[rt++] = snow[j] ? _CHAR_SNOW : ' ';
            buf[rt++] = '\n';
        }
        buf[rt - 1] = '\0';

        //正式繪製到屏幕上
        puts(buf);

        //清空老屏幕,屏幕光標回到最上面
        __curup(height);
    }
}
#undef _CHAR_SNOW

/**
* 屏幕繪製動畫效果, 繪製雪花動畫
*
* struct screen* : 屏幕結構指針
*/
void
screen_flash_snow(struct screen* scr)
{
    char* buf = NULL;
    // 初始化隨機數種子,改變雪花軌跡
    srand((unsigned)time(NULL));

    buf = malloc(sizeof(char)*(scr->width + 1)*scr->height);
    if (NULL == buf) {
        cerr("[FATAL]Out of memory!");
        exit(EXIT_FAILURE);
    }

    __flash_snow_buffer(scr, buf);

    //1.這裏理論上不會執行到這,沒加控制器. 2.對於buf=NULL,這種代碼 能夠省掉,看編程習慣
    free(buf);
    buf = NULL;
}

 

後記

     到這裏就結束了,此次分享的比較簡單,有興趣的同窗能夠 看看, 推薦寫一遍. 代碼看不懂的時候,多歇歇,看得懂的時候,多寫寫,

就有套路了. 歡迎吐槽. 錯誤是在所不免的.

     這個冬天,雪花很美,(。⌒∇⌒)

相關文章
相關標籤/搜索