viernes, 16 de octubre de 2009

Release!! serpiente.c (Snake)

Hace tiempo "publiqué" un juengo de serpiente con ncurses y hoy quiero revelar su código fuente !!!
El motivo es simple: Apoyo al OpenSource. (No al sofware privado) [Y yo con Windows,XD]

El código fuente viene comentado pero no muy detallado, XD. [Ahora lo leo de nuevo y ciertamente me mareo, me sorprendo a mí mismo, si ahora me mandara hacerlo de nuevo, tendría que dejarme una cuantas hora para idearmelo todo de nuevo,XD, es muy difícil de leerlo].

Aqui os dejo un copy+paste del codigo. (Espero que no haya incompatiblidad y que blogger no me coma ningún caracter...)

Aclaración: La función kbhit es copiado de otra persona
y las librerias de los includes estan separado con espacio, porque sino blogger lo omite.
===== Serpiente.c =====

/*********************************************************
*Fichero: serpiente.c
*Fecha: 15-05-2009
*Autor: Sui Zhao
*Contacto: sui1990(at)gmail(dot)com
*
*Descripcion:
* El tipico juego de serpiente
*
*gcc -lncurses -o serpiente serpiente.c
*
*Ultima actuacion:
************************************************************/

#include - stdio.h>
#include - ncurses.h>
#include - stdlib.h>

//* libreria y funcion para kbhit
#include - termios.h>
#include - unistd.h>
#include - sys/types.h>
#include - sys/time.h>
void changemode(int);
int kbhit(void);

//-------------------

//Funciones


void inicio();

/* ordenes() -> tiene como fin de anhadir
*los movimiento en que debe mover
*/
void ordenes(int y, int x, int longitud, int direccion);

// mover() -> todos los movimieto
void mover();

// Funcion dentro de mover
void ordena_posi_ejecutar(int aux);

//al dar una tecla
void dar_tecla();

//Funcion para aparecer la comida
void comida();

// game over
void fin_juego();

void bienvenida();
//Variables Globales
int y,x;
int longitud;
int el_ultimo;
int comida_y;
int comida_x;
int cantidad_comida=0;


struct POSICION
{
struct EJECUTA
{
int y;
int x;
int direccion;
}ejecuta[50];
}posicion[50];


//----prueba---



//------------

/*
* Direcciones:
* arriba = 1 = w = 119
* abajo = 2 = s = 115
* izq. = 3 = a = 97
* derch. = 4 = d = 100
*
*
* y, x = Posicion de la cabeza del serpiente
*/

main()
{
initscr();
bienvenida();

inicio();

mover();

getch();
endwin();
}


void inicio()
{
y=10;
x=25;
longitud=5;


posicion[1].ejecuta[1].y = 10;
posicion[1].ejecuta[1].x = 25;
posicion[1].ejecuta[1].direccion = 2;

posicion[2].ejecuta[1].y = 9;
posicion[2].ejecuta[1].x = 25;
posicion[2].ejecuta[1].direccion = 2;

posicion[3].ejecuta[1].y = 8;
posicion[3].ejecuta[1].x = 25;
posicion[3].ejecuta[1].direccion = 2;

posicion[4].ejecuta[1].y = 7;
posicion[4].ejecuta[1].x = 25;
posicion[4].ejecuta[1].direccion = 2;

posicion[5].ejecuta[1].y = 6;
posicion[5].ejecuta[1].x = 25;
posicion[5].ejecuta[1].direccion = 2;

comida();

}


void ordenes(int y, int x, int longitud, int direccion)
{
int aux;

for (aux=1;aux<=longitud;aux++)
{
el_ultimo=1;
while (posicion[aux].ejecuta[el_ultimo].direccion != 0)
{
el_ultimo++;
}
posicion[aux].ejecuta[el_ultimo].y = y;
posicion[aux].ejecuta[el_ultimo].x = x;
posicion[aux].ejecuta[el_ultimo].direccion = direccion;

}
}


void mover()
{
int aux;
int tiempo=1;
int aux_comida_y;
int aux_comida_x;
while (tiempo<=60000)
{
erase();

// iniciar la comida
move(comida_y,comida_x);
printw("*");
refresh();
// una vez que sea comido, generar mas comida
if (posicion[1].ejecuta[1].y == comida_y && posicion[1].ejecuta[1].x == comida_x)
{
aux_comida_y = comida_y;
aux_comida_x = comida_x;
comida();
++cantidad_comida;
}

// si toca algun tecla
if (kbhit())
{
dar_tecla();
}

for(aux=1; aux<=longitud;aux++)
{
ordena_posi_ejecutar(aux);
}


//dibujar los movimientos
for(aux=1; aux<=longitud;aux++)
{
switch(posicion[aux].ejecuta[1].direccion)
{//case 1,2,3,4
case 1:

posicion[aux].ejecuta[1].y = posicion[aux].ejecuta[1].y - 1;
move(posicion[aux].ejecuta[1].y,posicion[aux].ejecuta[1].x);
printw("o");
refresh();
break;

case 2:
posicion[aux].ejecuta[1].y = posicion[aux].ejecuta[1].y + 1;
move(posicion[aux].ejecuta[1].y,posicion[aux].ejecuta[1].x);
printw("o");
refresh();
break;

case 3:
posicion[aux].ejecuta[1].x = posicion[aux].ejecuta[1].x - 1;
move(posicion[aux].ejecuta[1].y,posicion[aux].ejecuta[1].x);
printw("o");
refresh();
break;

case 4:
posicion[aux].ejecuta[1].x = posicion[aux].ejecuta[1].x + 1;
move(posicion[aux].ejecuta[1].y,posicion[aux].ejecuta[1].x);
printw("o");
refresh();
break;
}
}

if (posicion[longitud].ejecuta[1].y == aux_comida_y &&
posicion[longitud].ejecuta[1].x == aux_comida_x)
{
++longitud;

//pasar todas las ordenes que tenga al ultimo
int aux_el_ultimo;
for(aux_el_ultimo=1;aux_el_ultimo<=el_ultimo;aux_el_ultimo++)
{
posicion[longitud].ejecuta[aux_el_ultimo].direccion =
posicion[longitud - 1].ejecuta[aux_el_ultimo].direccion;
posicion[longitud].ejecuta[aux_el_ultimo].y =
posicion[longitud - 1].ejecuta[aux_el_ultimo].y;
posicion[longitud].ejecuta[aux_el_ultimo].x =
posicion[longitud - 1].ejecuta[aux_el_ultimo].x;
}


switch(posicion[longitud - 1].ejecuta[1].direccion)
{
//case 1,2,3,4
case 1:
//posicion[longitud].ejecuta[1].y = posicion[longitud - 1].ejecuta[1].y + 1;
posicion[longitud].ejecuta[1].y = posicion[longitud - 1].ejecuta[1].y + 1;
posicion[longitud].ejecuta[1].x = posicion[longitud - 1].ejecuta[1].x;

break;

case 2:
posicion[longitud].ejecuta[1].y = posicion[longitud - 1].ejecuta[1].y - 1;
posicion[longitud].ejecuta[1].x = posicion[longitud - 1].ejecuta[1].x;
break;

case 3:
posicion[longitud].ejecuta[1].y = posicion[longitud - 1].ejecuta[1].y;
posicion[longitud].ejecuta[1].x = posicion[longitud - 1].ejecuta[1].x + 1;
break;

case 4:
posicion[longitud].ejecuta[1].y = posicion[longitud - 1].ejecuta[1].y;
posicion[longitud].ejecuta[1].x = posicion[longitud - 1].ejecuta[1].x - 1;
break;
}

aux_comida_y = comida_y;
aux_comida_x = comida_x;


}




// linea de separacion
int aux_linea;
for(aux_linea=0;aux_linea<=23;aux_linea++)
{
move(aux_linea,51);
printw("|");
}

move(2,53);
printw("Comistes: %i",cantidad_comida);



refresh();
usleep(250000);
tiempo++;

//-- si esta fura de rango
if (posicion[1].ejecuta[1].y <> 23 ||
posicion[1].ejecuta[1].x <> 50)
{
fin_juego();
}

//si toca propio cuerpo
for(aux=3;aux<=longitud;aux++)
{
if (posicion[1].ejecuta[1].y == posicion[aux].ejecuta[1].y &&
posicion[1].ejecuta[1].x == posicion[aux].ejecuta[1].x)
{
fin_juego();
}
}

}


}


void ordena_posi_ejecutar(int aux)
{
// posicion[aux].ejecutar[0] -> tmp, swap
int n_cambio;
int ejecutable = 0;
int aux_ejecutable =1;
// ver ordenes ya que ya dispone detro de cada

while(posicion[aux].ejecuta[aux_ejecutable].direccion != 0)
{
++ejecutable;
++aux_ejecutable;
}


//cuando solo tiene una orden, recta
if (ejecutable ==1)
{
//no hace nada
}else
{



if(posicion[aux].ejecuta[1].y == posicion[aux].ejecuta[2].y &&
posicion[aux].ejecuta[1].x == posicion[aux].ejecuta[2].x)
{


for (n_cambio=1;n_cambio<=ejecutable;n_cambio++)
{
posicion[aux].ejecuta[n_cambio - 1].direccion =
posicion[aux].ejecuta[n_cambio].direccion;
posicion[aux].ejecuta[n_cambio - 1].y = posicion[aux].ejecuta[n_cambio].y;
posicion[aux].ejecuta[n_cambio - 1].x = posicion[aux].ejecuta[n_cambio].x;
}
posicion[aux].ejecuta[ejecutable].direccion = 0;


}
}


}



void dar_tecla()
{
int tecla;
tecla = getchar();
/*--------
move(10,52);
printw("%i",tecla);
refresh();
getch();
//--------- */
switch(tecla)
{
//arriba
case 119:
if(posicion[1].ejecuta[1].direccion != 2)
ordenes(posicion[1].ejecuta[1].y , posicion[1].ejecuta[1].x, longitud, 1);
break;

// abajo
case 115:
if(posicion[1].ejecuta[1].direccion != 1)
ordenes(posicion[1].ejecuta[1].y , posicion[1].ejecuta[1].x, longitud, 2);
break;

//izquierda
case 97:
if(posicion[1].ejecuta[1].direccion != 4)
ordenes(posicion[1].ejecuta[1].y, posicion[1].ejecuta[1].x, longitud, 3);
break;

//derecha
case 100:
if(posicion[1].ejecuta[1].direccion != 3)
ordenes(posicion[1].ejecuta[1].y, posicion[1].ejecuta[1].x, longitud, 4);
break;
}



}


void comida()
{

// MAX = 24 * 80 , pero usar 24 * 50
// comida y , x son aleatorio
do{
srand(time(NULL));
comida_y = rand()% 25;

srand(time(NULL));
comida_x = rand() % 51;
}while (comida_y == 0 && comida_x ==0);
move(comida_y, comida_x);
printw("*");
refresh();

}


void fin_juego()
{
move(9,52);
printw("============================");
move(10,52);
printw(" G A M E O V E R ");
move(11,52);
printw("============================");
move(13,52);
printw("Pulse una tecla para salir");
refresh();
getch();
endwin();
exit(0);
}


void bienvenida()
{

move(1,0);
printw("················································");
move(2,0);
printw("··············································");
move(3,0);
printw("············@@@@@@@@@@@·················");
move(4,0);
printw("··········@@@@@@@@@@@@@@@···············");
move(5,0);
printw("·········@@@········@@@@@@····················");
move(6,0);
printw("·······@@@@············@@@@···················");
move(7,0);
printw("······@@@@··············@@@@··················");
move(8,0);
printw("······@@@@··············@@@@··················");
move(9,0);
printw("·····@@@@·······@@······@@@@··················");
move(10,0);
printw("·····@@@@······@@@·····@@@@···················");
move(11,0);
printw("·····@@@@·······@@@@@@@@@@····················");
move(12,0);
printw("·····@@@@·········@@@@@@·························");
move(13,0);
printw("······@@@@····································");
move(14,0);
printw("······@@@@··················//················");
move(15,0);
printw("·······@@@@················//··········{}····");
move(16,0);
printw("·········@@@···············\\\\·················");
move(17,0);
printw("··········@@@···············\\\\··||··||··||····");
move(18,0);
printw("·············@@·············//··||··||··||····");
move(19,0);
printw("···············@@@·········//····\\\\//···||····");
move(20,0);
printw("········································");
refresh();

int aux_linea;
for(aux_linea=0;aux_linea<=23;aux_linea++)
{
move(aux_linea,51);
printw("|");
}
refresh();


move(4,52);
printw("Game: SNAKE");
move(6,52);
printw("Autor: Sui Zhao");
move(7,52);
printw("Fecha: 24-05-09");

move(9,52);
printw("============================");
move(10,52);
printw(" S T A R T T H E G A M E ");
move(11,52);
printw("============================");
move(13,52);
printw(" Pulse una tecla");
move(14,52);
printw(" para empezar...");
refresh();
getch();
}


/***************** kbhit ********************/
void changemode(int dir)
{
static struct termios oldt, newt;

if ( dir == 1 )
{
tcgetattr( STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newt);
}
else
tcsetattr( STDIN_FILENO, TCSANOW, &oldt);
}

int kbhit (void)
{
struct timeval tv;
fd_set rdfs;

tv.tv_sec = 0;
tv.tv_usec = 0;

FD_ZERO(&rdfs);
FD_SET (STDIN_FILENO, &rdfs);

select(STDIN_FILENO+1, &rdfs, NULL, NULL, &tv);
return FD_ISSET(STDIN_FILENO, &rdfs);

}
/*********************************************/

=== EOF ====

Saludos, Good Luck!!

3 comentarios:

Monzi dijo...

Lol, yo era el probador beta del juego :-)
Lo tenía en el ordenador cogiendo polvo virtual. La verdad es que impresiona programar todo ese pastel. Programación de aplicaciones no es lo mio; prefiero programación web...

Sui dijo...

es lo mismo... web, escritorio... la idea de programacion es la misma,

Monzi dijo...

Pero los códigos no. Me son más fáciles las de programación web.

Publicar un comentario

 
Powered by Blogger