Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - eferion

#651
Programación C/C++ / Re: Estructuras en C
21 Marzo 2014, 10:14 AM
A ver si te he entendido bien.

Estas hablando de depurar programas, no?

Si no es así no sigas leyendo jejeje.

Cuando compilas un programa puedes hacerlo en modo debug o en modo release. La diferencia entre ambos modos es que el modo release aplica una serie de optimizaciones en el código para hacerlo más rápido. El modo debug, en cambio, inserta "marcadores" en el código para poder depurarlo. En resumen, cuando compilas en modo debug, el programa es más lento y grande que si lo compilas en modo release.

Cuando tienes un programa compilado en modo debug puedes usar unos programas llamados depuradores. Un depurador es una aplicación que permite seguir la traza de la aplicación para rastrear problemas en el código. Un depurador, para poder funcionar, necesita el ejecutable y el código fuente para relacionar ambos y presentarte la información de forma amigable.

Los depuradores, por definición, no tienen interfaz gráfica, son aplicaciones de modo consola. El problema que presenta utilizar un depurador en modo consola es que navegar por el código (por ejemplo para poner breakpoints o evaluar variables) puede ser bastante tedioso y frustrante... aunque con práctica todo se consigue.

Los IDEs suelen utilizar uno de estos depuradores, lo que sucede es que te lo presentan con una interfaz gráfica que además se integra automáticamente con tu código fuente, lo que reduce muchísimo la curva de aprendizaje. Yo, a título personal, prefiero depurar a través de un IDE que depurar "a pelo". He probado las dos formas y elijo la primera.

Dicho esto, hay depuradores para todos los colores y gustos. A mi personalmente me gusta bastante el que trae el VisualStudio. Al menos comparado con el que viene con QtCreator no hay color. El de CodeBlocks aún no he tenido ocasión de utilizarlo... aún no se integra del todo bien con Qt.
#652
De todas formas, para tener una opinión sólida lo mejor es experimentarlo uno mismo.

Configura un servidor web en un pc tuyo para que sea capaz de ejecutar aplicaciones de C++ y así podrás comprobar sus ventajas / desventajas.
#653
Al principio, antes de que naciese PHP, Java y compañía, las aplicaciones Web con contenido dinámico se escribían en C y Perl ( por poner dos ejemplos ).

Hoy en día, teniendo lenguajes enfocados principalmente al diseño Web, éstos lenguajes han ido perdiendo protagonismo.

Tu piensa que un programa escrito en C tiene acceso, per se, a todos los recursos del sistema, luego una entrada sin validar supone un problema bastante serio de seguridad... en PHP muchas veces no conseguirás más que inyección SQL, ya que la capa PHP se encarga de controlar los accesos no autorizados.

Otro problema que tenían las páginas escritas en C es que cada nueva petición se procesaba en un hilo diferente... lo que hacía que el rendimiento del servidor se degradase con rapidez.

Además, para terminar, las Webs realizadas en PHP, Java, .Net son muchísimo más fáciles de mantener y ampliar que las realizadas en C++.

Resumiendo:

* Se puede... sí
* Vas a encontrar servidores que soporten esta posibilidad... puede que haya alguno, pero es complicado.
* Es sencillo de mantener un portal en C++... no.
#655

      if(!condicion)
      {
        repeticion --;
        //condicionc = true;
      }
      if(repeticion == 4)
      {
          nivel++;
          gotoxy(35,1); printf("NIVEL %i",nivel);               

          gotoxy(ix,iy); puts(borrar_nave);     
          gotoxy(ix,iy); puts(borrar_nave);   
          gotoxy(ix,iy); puts(borrar_nave);   

          iy -= 2; //iy = iy - 2;

          gotoxy(ix,iy); puts(nave_l1);     
          gotoxy(ix,iy); puts(nave_l2);   
          gotoxy(ix,iy); puts(nave_l3);

          repeticion = 0;


      }


Partiendo de ese código... si lo resumimos para quedarnos con lo importante tenemos:


      if(!condicion)
      {
        repeticion --;
      }
      if(repeticion == 4)
      {
          nivel++;
          repeticion = 0;
      }


Dicho de otra forma... coges un int ( 2^32 combinaciones = 4.294.967.296 combinaciones ) y lo vas decrementando empezando por cero... es decir, de 0 a 4 pasando primero por negativos... tendrías que jugar unos 4.300 millones de turnos para que te cambie de nivel.

En serio, renombra esas variables... no es tan complicado y queda un código más sencillo de seguir:


#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

#define ARR 72
#define ABA 80
#define IZQ 75
#define DER 77

#define CHAR_SALUD    3
#define CHAR_DIAMANTE 4
#define CHAR_BLANCO   ' '

#define MAX_CORAZONES 3
#define MAX_DIAMANTES 25
#define MAX_PROGRESO  1000
#define MAX_VIDAS     3

#define AVANCE        2

typedef struct
{
  int x;
  int y;
} Coordenadas;

typedef struct
{
  Coordenadas coord_nave;
  Coordenadas coord_diamantes[ MAX_DIAMANTES ];

  int num_vidas;
  int corazones;
  int nivel;
  int progreso;
} DatosJuego;

// Dibujo de la nave
char *nave[]        = { " ***  ", " ** * ", " ***  " };
char *nave_vacia[]  = { "      ", "      ", "      " };
char *explosion1[]  = { "  **  ", " **** ", "  **  " };
char *explosion2[]  = { "* ** *", " **** ", "* ** *" };

void inicializar( DatosJuego* datos_juego )
{
  memset( datos_juego, 0, sizeof( DatosJuego ) );

  datos_juego->coord_nave.x = 1;
  datos_juego->coord_nave.y = 19;

  datos_juego->num_vidas = MAX_VIDAS;
  datos_juego->corazones = MAX_CORAZONES;
  datos_juego->nivel = 1;
}

void gotoxy(int x, int y)
{
  HANDLE hCon;
  COORD dwPos;

  dwPos.X = x;
  dwPos.Y = y;

  hCon = GetStdHandle( STD_OUTPUT_HANDLE );
  SetConsoleCursorPosition( hCon, dwPos );
}

void pintar_nave( Coordenadas coord, char* patron[] )
{
  int i;
  for ( i=0; i<3; i++ )
  {
    gotoxy( coord.x, coord.y + i );
    puts( patron[ i ] );
  }
}

void pintar_nivel( int nivel )
{
  gotoxy( 35, 1 );
  printf( "NIVEL: %d", nivel );
}

void pintar_vidas( int vidas )
{
   gotoxy( 2, 1 );
   printf( "VIDAS %d", vidas );
}

void pintar_salud( int salud )
{
  int i;

  gotoxy( 72, 1 );

  for( i = 0; i < salud; i++ )
    putchar( CHAR_SALUD );

  for ( ; i < 3; i++ )
    putchar( CHAR_BLANCO );
}

void pintar_explosion( Coordenadas coord )
{
  int i;

  for ( i = 0; i < 3; i++ )
  {
    gotoxy( coord.x, coord.y + i );
    puts( explosion1[ i ] );
  }

  Sleep( 380 );

  for ( i = 0; i < 3; i++ )
  {
    gotoxy( coord.x, coord.y + i );
    puts( explosion2[ i ] );
  }

  Sleep(380);

  pintar_nave( coord, nave );
}

void reiniciar_diamante( Coordenadas* coord )
{
  gotoxy( coord->x, coord->y );
  putchar( CHAR_BLANCO );

  if ( coord->x == 0 )
  {
    // Este codigo permite que los asteroides salgan repartidos
    // por el escenario al inicio de la partida
    coord->x = ( rand( ) % 50 ) + 29;
  }
  else
    coord->x = 79;

  coord->y = (rand( ) % 20 ) + 5;
}

void mover_diamante( Coordenadas* coord )
{
  gotoxy( coord->x, coord->y );
  putchar( CHAR_BLANCO );

  if ( coord->x < 2 )
    reiniciar_diamante( coord );
  else
    coord->x--;

  gotoxy( coord->x, coord->y );
  putchar( CHAR_DIAMANTE );
}

int colision( Coordenadas coord_nave, Coordenadas coord_diamante )
{
  int to_return = 0;

  // Comprobamos que el asteroide esta en la misma vertical que
  // la nave
  if ( ( coord_diamante.y >= coord_nave.y )
    && ( coord_diamante.y <= coord_nave.y + 2 ) )
  {
    // Ahora se comprueba si esta en la misma horizontal
    if ( ( coord_diamante.x <= coord_nave.x + 5 )
      && ( coord_diamante.x > coord_nave.x ) )
    {
      to_return = 1;
    }
  }

  return to_return;
}

void jugar( DatosJuego* datos_juego )
{
  //rutina de los diamantes

  int i;
  for ( i = 0; i < MAX_DIAMANTES; i++ )
    mover_diamante( &datos_juego->coord_diamantes[ i ] );

  //rutina de mover la ave
  if( _kbhit( ) )
  {
    unsigned char tecla = _getch( );

    switch (tecla)
    {
      case ARR:
        if ( datos_juego->coord_nave.y > 4 )
        {
          pintar_nave( datos_juego->coord_nave, nave_vacia );
          datos_juego->coord_nave.y -= AVANCE;
        }
        break;

      case ABA:

        if (datos_juego->coord_nave.y < 20 )
        {
          pintar_nave( datos_juego->coord_nave, nave_vacia );
          datos_juego->coord_nave.y += AVANCE;
        }
        break;

      case IZQ:
        if( datos_juego->coord_nave.x > 4 )
        {
          pintar_nave( datos_juego->coord_nave, nave_vacia );
          datos_juego->coord_nave.x -= AVANCE;
        }
        break;

      case DER:
        if( datos_juego->coord_nave.x < 70 )
        {
          pintar_nave( datos_juego->coord_nave, nave_vacia );
          datos_juego->coord_nave.x += AVANCE;
        }
        break;
    } //fin del switch
  }// Fin if

  pintar_nave( datos_juego->coord_nave, nave );

  //rutina para golpes de metoritos
  for ( i = 0; i < MAX_DIAMANTES; i++ )
  {
    if ( colision( datos_juego->coord_nave, datos_juego->coord_diamantes[ i ] ) )
    {
      reiniciar_diamante( &datos_juego->coord_diamantes[ i ] );
      pintar_nave( datos_juego->coord_nave, nave );

      datos_juego->corazones--;

      if( datos_juego->corazones == 0 )
      {
        datos_juego->num_vidas--;
        datos_juego->corazones = MAX_CORAZONES;
        pintar_vidas( datos_juego->num_vidas );
        pintar_explosion( datos_juego->coord_nave );
      }

      pintar_salud( datos_juego->corazones );
      break;
    }
  }

  /*rutina para cambio de nivel*/
  if ( datos_juego->progreso == MAX_PROGRESO )
  {
    datos_juego->nivel++;
    pintar_nivel( datos_juego->nivel );
    datos_juego->progreso = 0;
  }
  else
    datos_juego->progreso++;
}

int main ()
{
  DatosJuego datos_juego;

  inicializar( &datos_juego );

  pintar_vidas( datos_juego.num_vidas );
  pintar_salud( datos_juego.corazones );

  pintar_nivel(datos_juego.nivel );
  pintar_nave( datos_juego.coord_nave, nave );

  while( datos_juego.num_vidas > 0 )
  {
    jugar( &datos_juego );

    int sleep = 80 - datos_juego.nivel * 10;
    if ( sleep < 10 )
      sleep = 10;
    Sleep( sleep );
  }


  gotoxy( 30, 11 );
  puts( "*******************" );
  gotoxy( 30, 12 );
  puts( "*    Game Over    *" );
  gotoxy( 30, 13 );
  puts( "*******************" );

  gotoxy( 0, 24 );
  _getch( );
  return EXIT_SUCCESS;
}

#656
Si no hacen falta capturas... cualquiera que pruebe tu código ve el resultado.

Lo que te estamos diciendo es que el diseño que has elegido es muy pobre y propenso a errores y prueba de ello es que no es fácil encontrar el error en un programa tan corto.

Te propongo que readaptes un poco el código... y como muestra de buena fe te pongo algunas propuestas:

1. Usa estructuras. Las variables estarán organizadas y será más sencillo evitar el uso de variables globales:


typedef struct
{
 int x;
 int y;
} Coordenada;

typedef struct
{
 // Coordenadas de la nave
 Coordenada coord_nave;

 // Coordenadas de cada asteroide
 Coordenada coord_asteroides[ MAX_ASTEROIDES ];

 // Numero de vidas restantes
 int vidas;

 // Nivel de salud
 int salud;
 
 // Nivel del juego
 int nivel;

 // Progreso del juego. Para saber cuando subir de nivel
 int progreso;
} DatosJuego;


2. Usa defines. Vienen muy bien para evitar tener valores fijos en el código:


// Numero total de asteroides
#define MAX_ASTEROIDES 4

// progreso necesario para pasar de nivel
#define MAX_PROGRESO 1000

// desplazamiento de la nave
#define MOV_NAVE    2

// Caracter para pintar los asteroides
#define CHAR_ASTEROIDE 3

// Caracter para pintar la salud
#define CHAR_SALUD     4

// Para limpiar la pantalla
#define CHAR_BLANCO    ' '


3. Crea funciones para las tareas repetitivas. Por ejemplo pintar la nave:


void pintar_nave( Coordenadas coord )
{
 int i;
 for ( i=0; i<3; i++ )
 {
   gotoxy( coord.x, coord.y + i );
   puts( nave[ i ] );
 }
}


Ten en cuenta que para que el código anterior funcione es necesario redefinir la forma de describir la nave... algo así estaría bien (copiado de amchacon):


char nave[][]=
                  {
                    { " ***   " },  
                    { " ** *  " },
                    { " ***   " }
                  };


Y lo mismo puedes hacer para borrar la nave....


void borrar_nave( Coordenadas coord )
{
 int i;
 for ( i=0; i<3; i++ )
 {
   gotoxy( coord.x, coord.y + i );
   puts( nave_vacia[ i ] );
 }
}


Puedes, de echo, juntar ambas funciones en una sola y pasarle como argumento la matriz para pintar la nave o borrarla... pero eso ya te lo dejo a ti.

4. Evita las variables globales. No son necesarias como norma general.



int main( )
{
 DatosJuego datos_juego;

 // inicializamos la estructura
 memset( &datos_juego, 0, sizeof( DatosJuego ) );
 datos_juego.coord_nave.x = 1;
 datos_juego.coord_nave.y = 19;
 datos_juego.vidas = 3;
 datos_juego.salud = 3;
 datos_juego.nivel = 1;

 vidas( datos_juego.vidas );
 Barra_salud( datos_juego.salud );
 gotoxy(35,1); printf("NIVEL %d", datos_juego.nivel );  
 
 pintar_nave( datos_juego.coord_nave );  
   
 while( datos_juego.vidas > 0 )
   jugar( &datos_juego);
   
 gotoxy(22,16); printf("Game Over");
 Sleep(120);  
 getch();
 return 0;
}


5. Evita instrucciones duplicadas:

Por ejemplo el código que controla la pulsación del teclado tiene código repetitivo hasta la saciedad.


switch (tecla)
{        
 case ARR:
   if ( datos_juego->coord_nave.y > 4 )
   {
     borrar_nave( datos_juego->coord_nave );
     datos_juego->coord_nave.y -= MOV_NAVE;
   }                              
   break;
                           
 case ABA:
   // Nota que ya no es 70 sino 20, la consola tiene unicamente 25 filas
   if( datos_juego->coord_nave.y < 20 )
   {
     borrar_nave( datos_juego->coord_nave );
     datos_juego->coord_nave.y += MOV_NAVE;
   }                              
   break;

 case IZQ:
   if ( datos_juego->coord_nave.x > 4 )
   {
     borrar_nave( datos_juego->coord_nave );
     datos_juego->coord_nave.x -= MOV_NAVE;
   }                              
   break;
                           
 case DER:
    if ( datos_juego->coord_nave.x < 70 )
   {
     borrar_nave( datos_juego->coord_nave );
     datos_juego->coord_nave.x += MOV_NAVE;
   }                              
   break;
} //fin del switch

pintar_nave( datos_juego->coord_nave );


Con estos dos pasos el código ya lucirá un aspecto bastante más saludable. Será más complicado confundirse al usar las variables y será más sencillo seguir el código que has escrito.

Dale un repaso al código siguiendo estas pautas... u otras similares a tu elección y si no consigues resolver tu problema pon tu nuevo código.

Ah sí, por segunda vez Usa las etiquetas GeSHi para que el codigo sea legible si no, voy a empezar a plantearme el no responderte.

PD.: por si te preguntabas sobre la variable "progreso"... la idea que pensé es que con cada refresco, progreso se incrementase en una unidad. Al llegar a MAX_PROGRESO, se pone el contador a 0 y se sube el nivel.

Cuando corrijas tu código te comento si quieres cómo puedes hacer que aumente la dificultad con cada nivel.
#657
Cita de: Gh057 en 20 Marzo 2014, 17:24 PM
ahora bien, dicho concepto entonces me trastoca los libros... si una recurrencia se toma como una recursividad, la función factorial realizada por sumatoria (entiéndase por iteraciones) no representaría en sí una recursividad también?

dicho de otro modo cualquier sumatoria n, n+1,n+2... nn sería recursivo; implica acceder al valor anterior de n para continuar la serie...


Esto más o menos viene a resumir lo que he expuesto.
#658
El caso es que en programación, al menos hasta donde yo alcanzo, por recursividad se entiende al proceso mediante el cual una función o algoritmo se llama a sí mismo para obtener un resultado.

Reutilizar valores anteriores, al menos en programación, no se entiende por recursividad.

Entre otras cosas en programación SIEMPRE reutilizas valores anteriores:

ejemplo típico: un bucle

for( i=0; i< 20; i++ )

Estás reutilizando el valor anterior de i... la alternativa es escribir las iteraciones a pelo.

Esto es recursividad??? no creo.

y qué diferencia hay entre esto y reutilizar los valores de un vector??

* que los valores del vector han sido calculados ?? el de i también, no se llega a i=5 por arte de magia.

* que los valores del vector se necesitan para la solución final ?? el valor de i también... si no se podría prescindir de esta variable.

Esta es, a grandes rasgos, mi opinión al respecto

#659
¿recursividad? ¿donde?

Hace un uso un poco extraño del vector... pero por lo demás...
#660
if ( i > 0 && (i + 1)%8 == 0 )

O más sencillo.

if ((i + 1)%8 == 0 )

Todo i en el rango ( 0..31 ) que verifica "(i+1)%8==0" es necesariamente mayor que 0, puesto que (0+1)%8 == 1%8 == 1 != 0.

;)