怎么用c写 下雨或下雪的 程序

怎么用c写 下雨或下雪的 程序,第1张

初始察仿化肢则

void Init_Data()

{

int i

for( i=0i<POINTi++)

{

Snow[i].x=0

Snow[i].y=0

Snow[i].size=0

}

for( i=0i<MaxXi++)

Map[i]=MaxY

}

显示:

void MakeSnow()

{

int i

if( CurSnow>=POINT ) return

for( i=0Snow[i].sizei++ )

CurSnow++

Snow[i].x=random(MaxX)

Snow[i].y=random(DOWNSPEED)

Snow[i].size=random(MaxSize)+1

}

设定显示坐标

void ShowSnow( int x, int y, int size, int flag )

{

int color=0

if ( flag ) color=15

switch( size )

{

case 1:

putpixel( x, y, color )

break

case 2:

setcolor( color )

line( x-1, y-1, x+1, y+1 )

line( x-1, y+1, x+1, y-1 )

break

case 3:

setcolor( color )

line( x-1, y-1, x+1, y+1 )

line( x-1, y+1, x+1, y-1 )

/*

line( x-2, y-2, x+2, y+2 )

line( x-2, y+2, x+2, y-2 )*/

line( x-2, y, x+2, y )

line( x, y-2, x, y+2 )

break

}

}

雪花移动效果:

void Move( int n, int tox, int toy )

{

int x, y, size, i, j

float person

x=Snow[n].x

y=Snow[n].y

size=Snow[n].size

/* check end */

j=y

if( x<tox )

{

person=(DOWNSPEED *1.0) / ( tox-x )*1.0

for( i=xi<=toxi++ )

{

if( j>=Map[i] )

{

tox=i-size

break

}

j+=(int)( (i-x+1)*person )

}

}

else if( x>tox )

{

person=(DOWNSPEED *1.0) / ( x-tox )*1.0

for( i=xi>=toxi-- )

{

if( j>=Map[i] )

{

tox=i+size

break

}

j+=(int)( (x-i+1)*person )

}

}

if( y+DOWNSPEED>历没棚=Map[tox] )

{

switch( size )

{

case 1:

Map[x]--

break

case 2:

Map[x]-=2

if( x>0 &&Map[x-1]>Map[x] ) Map[x-1]=Map[x]

if( x<MaxX-1 &&Map[x+1]>Map[x] ) Map[x+1]=Map[x]

break

case 3:

Map[x]-=3

if( x>1 &&Map[x-2]>Map[x] ) Map[x-1]=Map[x]

if( x>0 &&Map[x-1]>Map[x] ) Map[x-1]=Map[x]

if( x<MaxX-2 &&Map[x+2]>Map[x] ) Map[x+1]=Map[x]

if( x<MaxX-1 &&Map[x+1]>Map[x] ) Map[x+1]=Map[x]

break

}

CurSnow--

y=Map[x]+size

Snow[n].x=x

Snow[n].y=y

Snow[n].size=0

}

else /* not end */

{

Snow[n].x=tox

Snow[n].y=toy

}

}

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <time.h>

/*

* 清除屏幕的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 = 0i<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

}

# include <dos.h># include <time.h># include <conio.h># include <stdio.h># include <stdlib.h># include <graphics.h>struct Snow //雪的结构体 { int xint yint sizeint speed}snow[200]int snownum=0//初始化雪花数量 void *save1,*save2,*save3,*save4//储存各个元素和腔运 void Copy() //唤梁储存元素主程序 { setcolor(0)setfillstyle(1,15)fillellipse(200,200,2,2)//大雪花 fillellipse(200,210,2,1)//圆返中雪花 fillellipse(210,200,1,1)//小雪花 save1=malloc(imagesize(196,196,204,204))//储存大雪花 save2=malloc(imagesize(196,196,204,204))//储存中雪花 save3=malloc(imagesize(196,196,204,204))//储存小雪花 save4=malloc(imagesize(196,196,204,204))//储存背景色的图块 getimage(196,196,204,204,save1)getimage(196,208,204,212,save2)getimage(208,198,212,202,save3)getimage(96,96,104,104,save4)cleardevice()} void DrawSnow() //下雪主程序 { int irandomize()while(!kbhit()) { if(snownum!=120) //初始设置雪花属性 { snow[snownum].speed=2+random(3)snow[snownum].x=20+random(600)snow[snownum].y=0snow[snownum].size=random(3)snownum++} for(i=0i<snownumi++) putimage(snow[i].x,snow[i].y,save4,0)for(i=0i<snownumi++) { snow[i].y+=snow[i].speedswitch(snow[i].size) //选择下落的雪花大小 {case 0: putimage(snow[i].x,snow[i].y,save1,0)breakcase 1: putimage(snow[i].x,snow[i].y,save2,0)breakcase 2: putimage(snow[i].x,snow[i].y,save3,0)break} if(snow[i].y>500) //雪花落下后重新计算雪花属性 { snow[i].speed=3+random(3)snow[i].x=20+random(600)snow[i].y=0snow[i].size=random(3)} } delay(5000)} } void main() {int driver=DETECT,modeinitgraph(&driver,&mode,"")Copy()DrawSnow()}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12382464.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存