Listas/Memoria Dinamica, juego BattleShip

Iniciado por johndoe1337, 23 Noviembre 2013, 00:21 AM

0 Miembros y 4 Visitantes están viendo este tema.

johndoe1337

Saludos, quisiera utilizar listas y memoria dinámica en mi juego, el objetivo es poder remover un barco en cierta posición y volver a colocarlo en otra ya sea porque me equivoque o algo , alguien tiene alguna idea de como implementarlas en mi código ?? Cualquier ayuda en bien agradecida.

Aquí les dejo el código:


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


/* Macros */
#define AGUA '^'
#define TOCADO '*'
#define OCULTA 'O'
#define PORTAVIONES 5
#define ACORAZADO 4
#define SUBMARINO 3
#define CRUCERO 3
#define DESTRUCTOR 2

typedef struct
{
   char letra;
   int numero;
}Casilla;

char TableroJ1[10][10],TableroJ2[10][10],Aux[10][10],frase[50]="\0";
int Barcos[5]={PORTAVIONES,ACORAZADO,SUBMARINO,CRUCERO,DESTRUCTOR};
Casilla Lista[100];
int aux=0,contador=0,tocadosJ1=0,tocadosJ2=0;

/* Funciones */
void IniciarTablero(char[10][10],char);
void IniciarTableroJ2();
void DibujarTablero(char[10][10]);
void PedirCasilla(int);
int VerificarCasilla(char[10][10],Casilla,int,char);
void Almacenar(char[10][10],int,Casilla,char);
void TurnoJ1();
void TurnoJ2();
char AtacarCasilla(char[10][10],Casilla);
void GenerarLista();

/* Main */
int main()
{
   IniciarTablero(TableroJ1,AGUA); // Poner todas las casillas con el símbolo de agua (^).
   DibujarTablero(TableroJ1); // Dibujar el tablero.

   /* Colocar los barcos en las posiciones deseadas */
   strcpy(frase,"[Casillas del portaviones (5 casillas)]\n");
   printf("%s",frase);
   PedirCasilla(PORTAVIONES);
   strcpy(frase,"[Casillas del acorazado (4 casillas)]\n\0");
   printf("%s",frase);
   PedirCasilla(ACORAZADO);
   strcpy(frase,"[Casillas del submarino (3 casillas)]\n");
   printf("%s",frase);
   PedirCasilla(SUBMARINO);
   strcpy(frase,"[Casillas del crucero (3 casillas)]\n");
   printf("%s",frase);
   PedirCasilla(CRUCERO);
   strcpy(frase,"[Casillas del destructor (2 casillas)]\n");
   printf("%s",frase);
   PedirCasilla(DESTRUCTOR);
   printf("     TABLERO CREADO\n");
   Sleep(1000);

   system("cls");
   printf("Generando tablero oponente...");
   IniciarTablero(Aux,OCULTA); // Poner todas las casillas con el símobolo de casilla oculta(O).
   IniciarTableroJ2(); // Generar aleaoriamente el tablero del oponente.
   GenerarLista();
  system("cls");
   printf("\n\n\n\n\n\n                              EMPIEZA EL JUEGO\n");
   Sleep(2000);

   /* Iniciar la batalla */
   while (1)
   {
      TurnoJ1(); // Turno del jugador
      if (tocadosJ1 == 17) // Si se han destruído todos los barcos
      {                // del oponente se gana y acaba el juego.
         system("cls");
         printf(" GANASTE\n");
         return 0;
      }

      TurnoJ2(); // Turno del oponente.
      if (tocadosJ1 == 17) // Si se han destruído todos los barcos
      {                // del jugador se pierde y acaba el juego.
         system("cls");
         printf(" PERDISTE\n");
         return 0;
      }
   }
}

/* Función que inicia el tablero con el símbolo deseado */
void IniciarTablero(char Tablero[10][10],char simbolo)
{
   int i,j;

   for(i=0;i<10;i++)
   {
      for (j=0;j<10;j++)
         Tablero[i][j]=simbolo;
   }
}

/* Función que genera el tablero del oponente aleatoriamente */
void IniciarTableroJ2()
{
   Casilla aleatoria;
   char pos,posicion[2]={'v','h'};
   int i;

   IniciarTablero(TableroJ2,AGUA); // Primero se rellena el tablero con el símoblo de agua (^).
   srand(time(NULL));
   for (i=0;i<5;i++)
   {
      do
      {
         aleatoria.letra=(rand()%10)+65; // Casilla
         aleatoria.numero=(rand()%10)+1; // aleatoria.
         pos=posicion[rand()%2]; // Posición aleatoria.
      }while(!VerificarCasilla(TableroJ2,aleatoria,Barcos[i],pos)); // Verificar si la casilla es válida.
      Almacenar(TableroJ2,Barcos[i],aleatoria,pos); // Se almacena el barco en el tablero.
   }
}

/* Dibujar el tablero */
void DibujarTablero(char Tablero[10][10])
{
   int i,j,letra=65;

   system("cls");
   printf("        1 2 3 4 5 6 7 8 9 10\n\n");
   for (i=0;i<10;i++,letra++)
   {
      printf("     %c  ",letra);
      for (j=0;j<10;j++)
         printf("%c ",Tablero[i][j]);
      printf("\n\n");
   }
   printf("%s",frase);
}

/* Función que pide una casilla a partir de la cual se introduce */
/* un barco determinado en posición vertical u horizontal */
void PedirCasilla(int barco)
{
   Casilla cas;
   char posicion;
   int valida;

   do {
      valida=0;
      fflush(stdin);
      printf("Letra: ");
      scanf("%c",&cas.letra);
      cas.letra=toupper(cas.letra);
      if (cas.letra < 65 || cas.letra > 74) // Verificar si la letra pertenece al rango válido.
         valida++;
      printf("Numero: ");
      scanf("%d",&cas.numero);
      if (cas.numero < 1 || cas.numero > 10) // Verificar si el número pertenece al rango válido.
         valida++;
      printf("Vertical u horizontal (v/h): ");
      fflush(stdin);
      scanf("%c",&posicion);
      if (posicion != 'v' && posicion != 'h') // Verificar si la posición es válida.
         valida++;
      if (!VerificarCasilla(TableroJ1,cas,barco,posicion))
         valida++;
      if (valida > 0) // Si falla algún parámetro anterior
      {            // se muestra un mensaje de error.
         printf("Casilla no valida o posicion no valida\n");
         Sleep(1000);
      }
      DibujarTablero(TableroJ1);
   }while(valida > 0); // Se vuelven a pedir los parámetros hasta que sean correctos.
   Almacenar(TableroJ1,barco,cas,posicion); // Almacenar el barco en le tablero
   strcpy(frase,"\0");
   DibujarTablero(TableroJ1); // Dibujar el tablero
}

/* Función que verifica si la casilla inroducida es correcta */
int VerificarCasilla(char Tablero[10][10],Casilla cas,int barco,char posicion)
{
   int fila,columna,i,cont=0,tope;

   fila=cas.letra-65;
   columna=cas.numero-1;
   if (Tablero[fila][columna] != AGUA) // Si la casilla está ocupada.
      return 0;
   if (posicion == 'h') // Si la posición es horizontal, se verifica si
   {                // el barco cabe en la fila a partir de esa casilla.
      tope=columna+barco;
      for (i=columna;i<10 && i<tope;i++)
      {
         if (Tablero[fila][i] == AGUA) // Contar las casillas libres que tiene
            cont++;                 // la casilla elegida a partir de esta.
         else
            return 0;
      }
      if (cont < barco) // Si las casillas libres son insuficientes, la casilla no vale.
         return 0;
      return 1;
   }
   else // Mismo método que el anterior pero en vertical.
   {
      tope=fila+barco;
      for (i=fila;i<10 && i<tope;i++)
      {
         if (Tablero[i][columna] == AGUA)
            cont++;
         else
            return 0;
      }
      if (cont < barco)
         return 0;
      return 1;
   }
}

void Almacenar(char Tablero[10][10],int barco,Casilla cas,char posicion)
{
   int i,fila,columna,tope;
   char tipo;

   fila=cas.letra-65;
   columna=cas.numero-1;
   switch(barco) // Colocar una letra según el barco.
   {
      case PORTAVIONES:
         tipo='P';
         break;
      case ACORAZADO:
         tipo='A';
         break;
      case SUBMARINO:
         if (aux == 0)
         {
            tipo='S';
            aux++;
         }
         else
            tipo='C';
         break;
      case DESTRUCTOR:
         tipo='D';
         break;
   }

   /* Almacenar el barco según la posición y la casilla */
   if (posicion == 'h')
   {
      tope=columna+barco;
      for (i=columna;i<tope;i++)
         Tablero[fila][i]=tipo;
   }
   else
   {
      tope=fila+barco;
      for (i=fila;i<tope;i++)
         Tablero[i][columna]=tipo;
   }
}

/* Función turno del jugador */
void TurnoJ1()
{
   Casilla cas;
   int valida,fila,columna;

   strcpy(frase,"[Tu turno]\n");
   DibujarTablero(Aux);
   do {
      valida=0;
      fflush(stdin);
      printf("Letra: ");
      scanf("%c",&cas.letra);
      cas.letra=toupper(cas.letra);
      if (cas.letra < 65 || cas.letra > 74) // Verificar si la letra pertenece al rango válido
         valida++;
      printf("Numero: ");
      scanf("%d",&cas.numero);
      if (cas.numero < 1 || cas.numero > 10) // Verificar si el número pertenece al rango válido.
         valida++;
      fila=cas.letra-65;
      columna=cas.numero-1;
      if (Aux[fila][columna] != OCULTA) // Verificar si la casilla ya está "tocada".
         valida++;
      if (valida > 0) // Si falla algún parámetro anterior
      {            // se muestra un mensaje de error.
         printf("Casilla no valida\n");
         Sleep(1000);
      }
      DibujarTablero(Aux); // Se refresca" la pantalla.
   }while(valida > 0);
   Aux[fila][columna]=AtacarCasilla(TableroJ2,cas); // Comprobar la casilla.
   if (Aux[fila][columna] == TOCADO) // Si se ha tocado un barco oponente.
   {
      strcpy(frase,"[Tocado]\n");
      tocadosJ1++;
   }
   else // Si ha caído en agua.
      strcpy(frase,"[Agua]\n");
   DibujarTablero(Aux); // Dibujar el tablero
   system("pause");
}

/* Función turno del oponente */
void TurnoJ2()
{
   Casilla cas;
   int fila,columna;

   strcpy(frase,"[Turno de tu oponente]\n");
   DibujarTablero(TableroJ1);
   cas=Lista[contador++];
   fila=cas.letra-65;
   columna=cas.numero-1;
   TableroJ1[fila][columna]=AtacarCasilla(TableroJ1,cas); // Comprobar la casilla.
   if (TableroJ1[fila][columna] == TOCADO) // Si se ha tocado un barco oponente.
   {
      strcpy(frase,"[Tocado]\n");
      tocadosJ2++;
   }
   else // Si ha caído en agua.
      strcpy(frase,"[Agua]\n");
   DibujarTablero(TableroJ1); // Dibujar el tablero
   system("pause");
}

/* Función que comprueba la casilla a atacar */
char AtacarCasilla(char Tablero[10][10],Casilla cas)
{
   int fila,columna;

   fila=cas.letra-65;
   columna=cas.numero-1;
   if (Tablero[fila][columna] == 'P' || Tablero[fila][columna] == 'A' || Tablero[fila][columna] == 'S' || Tablero[fila][columna] == 'C' || Tablero[fila][columna] == 'D')
      return TOCADO; // Si se acierta.
   return AGUA;
}

/* Función que genera una lista aleatoria de casillas */
/* que usará la máquina para jugar atacar */
void GenerarLista()
{
   int i,j,num;
   Casilla aux;

   for (i=0;i<100;i++)
   {
      for (j=1;j<11;j++)
      {
         Lista[i].letra=j+64; // Almacenar todas las casillas
         Lista[i].numero=j;  // válidas en orden ascendente.
      }
   }
   srand(time(NULL));
   for (i=0;i<100;i++) // Desordenar las casillas.
   {
      num=rand()%100;
      aux=Lista[i];
      Lista[i]=Lista[num];
      Lista[num]=aux;
   }
}
[code]
[/code]

rir3760

Cita de: johndoe1337 en 23 Noviembre 2013, 00:21 AMquisiera utilizar listas y memoria dinámica en mi juego, el objetivo es poder remover un barco en cierta posición y volver a colocarlo en otra ya sea porque me equivoque o algo
1) La ventaja de las listas vinculadas es su mayor eficiencia (en comparación con el uso de un array) de las operaciones inserción y eliminación.
2) Reservar memoria en tiempo de ejecución permite su uso de manera eficiente al no conocer (de antemano) el numero de elementos de un array.

Como ninguno de los dos casos aplica en el juego de batalla naval no tiene caso (en mi opinión) implementar los cambios.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

johndoe1337

Me imagine que seria medio complicado, he tratado de implementar Listas y Memoria dinámica en el juego pero no creo que se pueda, al menos yo no puedo, quisiera hacerlo solo por aprendizaje personal o ver como se hace, crees que hubiera alguna forma de lograrlo, sabiendo que no tiene sentido hacerlo, pero solo para practicar.

Ahh otra pregunta seria, como puedo visualizar los dos jugadores en un mismo espacio ? es decir, como puedo poner que se vea mi juego y el de la maquina uno al lado del otro, me imagino que con un goto, algo parecido a esto " http://www.youtube.com/watch?v=V6aV85jqI_Q ".

Gracias!

rir3760

Solo tienes que modificar la función "DibujarTablero" para que reciba dos argumentos (los tableros de ambos jugadores). En su bucle principal imprimes la primera fila del primer tablero seguida de la primera fila del segundo tablero, la segunda fila del primer tablero seguida de la segunda fila del segundo tablero, etc..

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

johndoe1337

Si tienes tiempo, me podrías dar una mano ? y con respecto a introducir listas, entonces no hay forma de hacerlo ?

johndoe1337

O alguien que tenga tiempo, si pudiera ayudarme se lo agradeceria bastante.

Saludos


xaps

Por lo visto ese código no lo has hecho tú.

Te voy a volver a explicar lo que ya te ha dicho rir3760: Aquí no sale a cuenta utilizar memoria dinámica, ya que el tamaño del tablero es un tamaño prefijado. Tampoco sale a cuenta usar listas, ya que pierdes el acceso directo a las posiciones del tablero (ventaja que tienen los vectores frente a una lista).

En cuanto a lo de dibujar los dos tableros en pantalla, por suerte para ti es algo muy básico y muy fácil de aprender. Empieza por estudiar lo básico y ves proponiéndote retos más complicados poco a poco. No se puede empezar la casa por el tejado.

Saludos
"The programmers of tomorrow are the wizards of the future" - Gave Newel

johndoe1337

Cita de: xaps en 25 Noviembre 2013, 16:09 PM
Por lo visto ese código no lo has hecho tú.

Te voy a volver a explicar lo que ya te ha dicho rir3760: Aquí no sale a cuenta utilizar memoria dinámica, ya que el tamaño del tablero es un tamaño prefijado. Tampoco sale a cuenta usar listas, ya que pierdes el acceso directo a las posiciones del tablero (ventaja que tienen los vectores frente a una lista).

En cuanto a lo de dibujar los dos tableros en pantalla, por suerte para ti es algo muy básico y muy fácil de aprender. Empieza por estudiar lo básico y ves proponiéndote retos más complicados poco a poco. No se puede empezar la casa por el tejado.

Saludos
Ok, Gracias. Una ultima pregunta, este menu [ http://foro.elhacker.net/programacion_cc/para_que_dejeis_de_preguntar_de_una_vez_por_los_menus-t276719.0.html ] cual es la ventaja del este ? y para que tipo de caso utilizo un menú con esa variedad de funciones ?