Red de conocimiento informático - Conocimiento del nombre de dominio - Cómo escribir el efecto de animación de la nieve en lenguaje C

Cómo escribir el efecto de animación de la nieve en lenguaje C

#include?

#include?

#include?

#include?

/*

*? Comando de Shell/comando de consola para borrar la pantalla y algunas implementaciones dependientes de la plataforma

* Si se define __GNUC__, se supone que el compilador gcc se utiliza para la plataforma Linux

* En caso contrario, se supone que es la plataforma Windows

*/

#if?definido(__GNUC__)

//Lo siguiente depende de la implementación de Linux

#include?

# define?sleep_ms(m)?\

usleep(m?*?1000)

//Mover función del cursor hacia arriba?Linux

static?void ?__curup (int?altura)

{

int?i?=?-1;

mientras?(++i

printf("\033[1A");?//¿Volver primero a la línea anterior?

}

#else?

// ?Crear una función de espera? 1s? 60? cuadros?

//?¿Crear una función de espera aquí en milisegundos?,?Necesita confiar en la implementación del sistema operativo

#include?

#define?sleep_ms(m)?\

Sleep(m)

//Mover el cursor hacia arriba

static?void?__curup(int?height)

{

COORD?cr?=?{0,0};

//?GetStdHandle(STD_OUTPUT_HANDLE)?Obtener el objeto de pantalla,?Establecer el cursor

SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),?cr);

}

#endif?/*__GNUC__?¿El código multiplataforma es feo?*/

//?Define las macros de píxeles de ancho y alto de la pantalla inicial

#define?_INT_WIDTH(100)

#define?_INT_HEIGHT(50)

//?La tasa de fotogramas de actualización de la pantalla

#define?_INT_FRATE(40)

//?La tasa de caída de los copos de nieve, en relación con el múltiplo de "marcos de actualización de pantalla"

#define?_INT_VSNOW(10)

/*

*? Error al manejar la macro, el mensaje debe ser una constante de cadena encerrada entre " "

*?__FILE__:?Ruta completa del archivo

*?__func__:?Nombre de la función

*?__LINE__:?Número de líneas

*?__VA_ARGS__: ?Macro de parámetro variable,

*?## indica conexión directa,?Por ejemplo?a##b?<=>?ab

*/

# define?cerr(msg,...)?\

fprintf(stderr,?"[%s:%s:%d]"?msg?"\n" ,__ARCHIVO__,__func__,__L

INE__,##__VA_ARGS__);

/*

*?Estructura de pantalla,?Tiene?ancho y alto

*?frate?:?Dibujar un marco El período, la unidad es milisegundos

*?width?:?El ancho de la pantalla, basado en la esquina superior izquierda de la ventana (0,0)

*?height ?:?El ancho de la pantalla Alto

*?pix:? ¿Utiliza una dimensión para simular dos dimensiones? La estructura principal es la siguiente

*?0?0?0? 1?0?0?1?0?1? 0

*?0?1?0?1?0?1?0?1?2?0

*? .?.?.

*?=>?0 significa que no hay píxeles, ?1 significa 1 píxel, 2 significa 2 píxeles....

*/

struct?screen?{

int?frate;?//?También puedes usar la estructura ?unsigned?

int?width;

int ?height;

char? *pix;

};

/*

*?Crear un?puntero de estructura de pantalla?return

*

*?int?frate:?El período de dibujo de un fotograma

*?int?width:?Ancho de pantalla

*?int?height:?Alto de la pantalla

*?return:?Puntero a la estructura de la pantalla

*?*/

struct?screen*?screen_create (int?frate,?int?width,?int ?height);

/*

* Destruye un puntero de estructura de pantalla y déjalo en blanco

* ?struct?screen**?:?Puntero a?puntero de estructura de pantalla,?destrucción nivel-nivel

*?*/

void?screen_destory(struct?screen**?pscr );

*?*/

void?screen_destory(struct?screen**?pscr);

p>

/**

*?Función de dibujo de pantalla, genera principalmente un efecto de copo de nieve

*

*?struct?screen*?:? Datos de pantalla

*?return? :?0 significa que se puede dibujar, 1 significa que el patrón permanece sin cambios

*/

int?screen_draw_snow(struct?screen* ?scr);

/**

*?Efecto de animación de dibujo de pantalla,? Animación de dibujo de copo de nieve

*

*?struct ?screen*?:?Puntero de estructura de pantalla

*/

void?screen_flash_snow(struct?screen*?scr);

//?Función principal, el negocio principal se ejecuta aquí

int?main(int?argc,?char?*argv[])

{

struct?screen*?scr? =?NULL;

//Crear un objeto de pantalla

scr?=?screen_create(_INT_FRATE,?_INT_WIDTH,?_INT_HEIGHT);

if?(NULL ?==?scr)

exit(EXIT_FAILURE);

//Dibujar animación de copo de nieve

screen_flash_snow(scr);

/ /Destruir este objeto de pantalla

screen_destory(&scr);

return?0;

}

/*

*?¿Crear un?Puntero de estructura de pantalla? Retorno

*

*?int?frate:?El período de dibujo de un cuadro

*?

int?width:?Ancho de pantalla

*?int?height:?Alto de pantalla

*?return:?Puntero a la estructura de la pantalla

*?* /

struct?screen*

screen_create(int?frate,?int?width,?int?height)

{

estructura ?screen?*scr?=?NULL;

if?(frate<0?||?width?<=?0?||?height?<=?0)?{

cerr("[ADVERTENCIA]check?is?frate<0?||?width<=0?||?height<=0?err!");

return?NULL

}

//A continuación se muestra la memoria asignada para scr->pix?width*height

scr?=?malloc(sizeof(struct ?screen)? +?sizeof(char)*width*height);

if?(NULL?==?scr)?{

cerr("[FATALG]¡Sin? memoria! ");

return?NULL;

}

scr->frate?=?frate;

scr ->ancho? =?width;

scr->height?=?height;

//Reducir el número de mallocs, el consumo de malloc es muy grande, pérdidas de memoria, fragmentación de la memoria

scr->pix?=?((char?*)scr)?+?sizeof(struct?screen);

return?scr;

}

/*

* Destruye un puntero de estructura de pantalla y déjalo en blanco

*?struct?screen**:?points to? El puntero del puntero de estructura de pantalla, ?Destrucción nivel-nivel

*?*/

void

screen_destory(struct?screen**?pscr)

{

si?(NULL?==?pscr?||?NULL?==?*pscr)

return;

gratis(*pscr);

//?Evita los punteros salvajes

*pscr?=?NULL;

}

/ /Construye el copo de nieve al principio. La siguiente macro significa que cada tamaño de paso _INT_SHEAD, un copo de nieve, debe ser una potencia de 2

// ¿estático puede entenderse como código de operación de bits?macro privado. Es realmente difícil de leer.

#define?_INT_SHEAD?(1<<2)

static?void?__snow_head(char*?snow,?int?len)

{

int?r?=?0;

//Los datos deben borrarse

memset(snow,?0,?len);

p>

for?(;;)?{

//¿Un truco para tomar el resto?2^3?-?1?=?7?=>?111?,?The union tomará el resto

int?t?=?rand()?&?(_INT_SHEAD?-?1);

if?(r?+?t?> =?len)

romper;

nieve[r?+?t]?=?1;

r?+=?_INT_SHEAD

;

}

}

#undef?_INT_SHEAD

//Pass?Previous?scr->pix[scr-> ancho *(idx-1)]?=>?scr->pix[scr->width*idx]

//¿La siguiente macro estipula que los copos de nieve se mueven hacia la izquierda y hacia la derecha un píxel? a la izquierda, ?1? significa sin cambios, ?2 significa un píxel a la derecha

#define?_INT_SWING?(3)

static?void?__snow_next(struct?screen*? scr, ?int?idx)

{

int?width?=?scr->ancho;

char*?psnow?=?scr-> pix? +?width*(idx?-?1);

char*?snow?=?psnow?+?width;

int?i,?j,?t ;? ///?i índice,?j guarda la posición del siguiente copo de nieve instantáneo, t? se compensa temporalmente para resolver el problema de superposición del copo de nieve //Restablecer para la fila actual

memset(snow,?0 ,?width) ;

//¿Calcular la siguiente posición del copo de nieve hasta la última posición del copo de nieve?

for?(i?=?0;?i

for?(t?=?psnow[i];?t>0;?--t)?{?//?Los copos de nieve pueden superponerse

// ?rand() %_INT_SWING?-?1? representa el desplazamiento del eje horizontal del copo de nieve, con respecto a la posición anterior

j?=?i?+?rand()?%?_INT_SWING? -?1;

j?=?j<0width?-?1?:?j?>=?width0?:?j;?//?jSi cruza el límite, el lado izquierdo cruza el límite y va hacia la derecha, y el lado derecho cruza el límite hacia la Izquierda

++snow[j];

}

}

}

/**

*?Función de dibujo de pantalla, genera principalmente un efecto de copo de nieve

*

* ?struct?screen*?:?Datos de pantalla

*?return?:?0 significa que se puede dibujar, 1 significa que el patrón permanece sin cambios

*/

int

screen_draw_snow(struct?screen*?scr)

{

//?Variable estática, inicializada a 0 de forma predeterminada, utilizada siempre

estática?int?__velocidad?=?0;

int?idx;

if?(++__velocidad?!=?_INT_VSNOW)

return?1;

// ¿Siguiente? ¿Es hora de que caigan los copos de nieve? __speed?==?_INT_VSNOW

__speed?=?0;

//Reconstruya la interfaz del copo de nieve aquí, primero construya el encabezado y construya desde la cola

for?(idx?=?scr->height?-?1;?idx?>?0;? --idx)

__snow_next (scr,?idx);

//Construir la cabeza

__snow_head(scr->pix,?scr->width );

return?0 ;

}

//buf?Guarda los datos de pix en scr?, después de la construcción es?(ancho+1 )*height,?La siguiente macro es un patrón de copo de nieve

#define?_CHAR_SNOW?'*'

static?void?__fla

sh_snow_buffer(struct?screen*?scr,?char*?buf)

{

int?i,?j,?rt;

int?height ?=?scr->height,?width?=?scr->width;

int?frate?=?scr->frate;?//Actualizar frecuencia de fotogramas

/ /Esperar cada vez

para?(;;sleep_ms(frate))?{

//Empezar a dibujar la pantalla

rt?=?screen_draw_snow (scr );

si?(rt)

continuar;

para?(i?=?0;i

char*?snow?=?scr->pix?+?i*width;

for?(j?=?0;?j

buf[rt++]?=?snow[j]_CHAR_SNOW?:?'?';

buf[rt++]?=?'\n';

p>

}

buf[rt?-?1]?=?'\0';

//Dibujado formalmente en la pantalla

puts(buf);

//Borrar la pantalla anterior y devolver el cursor de la pantalla a la parte superior

__curup(height);

}

}

#undef?_CHAR_SNOW

/**

*? ¿Efecto de animación de dibujo de pantalla,? *

*?struct?screen*?:?Puntero de estructura de pantalla

*/

void

screen_flash_snow(struct?screen* ?scr )

{

char*?buf?=?NULL;

//?Inicializa la semilla de números aleatorios y cambia la trayectoria del copo de nieve

srand((unsigned)time(NULL));

buf?=?malloc(sizeof(char)*(scr->width?+?1)*scr->height);

if?(NULL?==?buf)?{

cerr("[FATAL]¿Sin?memoria!");

exit( EXIT_FAILURE);

}

__flash_snow_buffer(scr,?buf);

///1. .?2. Para buf=NULL, este tipo de código se puede omitir, dependiendo de los hábitos de programación

free(buf);

buf?=?NULL;

}