Corrección ejercicio en C de un bingo

Iniciado por vaillo33, 11 Enero 2019, 11:47 AM

0 Miembros y 1 Visitante están viendo este tema.

vaillo33

Buenas, les dejo por aqui mi código, me estoy volviendo loco intentando ver lo que he hecho mal, no encuentro el error, me podéis ayudar??. El enunciado del problema sería el siguiente:
En este ejercicio implementaremos el juego del bingo simplificado. Habrá dos jugadores, con sus respectivos cartones compuestos por 20 números aleatorios del 1 al 100 (todos los números de un cartón han de ser forzosamente distintos). Por otro lado, se irá generando una secuencia de números aleatorios comprendidos también entre 1 y 100, que representan las bolas que van saliendo del bombo (esta secuencia tampoco podrá tener números repetidos). La mecánica del programa será la siguiente: en cada iteración, mostraremos los números que han ido saliendo del bombo hasta el momento, así como los dos cartones, donde habremos tachado (en vez del número saldrá una X) los números que ya hayan salido. Esperaremos entonces a que el usuario pulse una tecla y a continuación sacaremos una nueva bola del bombo, actualizaremos los cartones con la nueva bola y volverá a aparecer toda la información (lista con las bolas que han salido y cartones actualizados). El programa terminará cuando alguno de los dos cartones se complete, con lo que el jugador asociado a dicho cartón ganará.

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <conio.h>
int controladorCarton1=0, final=0, bolas=0;
void ImprimoPrincipio(void){
   printf("----------------------------\n");
   printf("Juego del bingo simplificado\n");
   printf("----------------------------\n");
}

int GeneradorNumero(void){           //Genero un numero aleatorio
   int num;

   num = rand() % 100;
   return num;
}
int Bola(void){
   int numerosbolas[100], sacadas[100], y=0, z, v;
   printf("Bolas: ");
   for(int x=0;x<100;x++){          //creo un vector con todos los numeros del 1 al 100
       numerosbolas[y]=x+1;
       y++;
   }

   do{
       z=GeneradorNumero();
   }while(numerosbolas[z]==0);
   v=numerosbolas[z];
   numerosbolas[z]=0;
   return v;
}

void Carton1(void){
   int numeroscarton1[100], y=0, z, vectorcarton1 [20], v, bola, contador1, sacadas[100];
   printf("Carton 1: \n");
   if(controladorCarton1==0){
       for(int x=0;x<100;x++){          //creo un vector con todos los numeros del 1 al 100
           numeroscarton1[y]=x+1;
           y++;
       }
       for(int u=0;u<20;u++){
           z=GeneradorNumero();

           do{
               z=GeneradorNumero();
           }while(numeroscarton1[z]==0);

           vectorcarton1[u]=numeroscarton1[z];
           numeroscarton1[z]=0;
           printf("%d",vectorcarton1[u]);
           v=vectorcarton1[u]/10;
           if(v<1){
               printf("  ");
           }else{
               printf(" ");
           }
           if(u==4||u==9||u==14||u==19){
               printf("\n");

           }
       }
   }else{
       bola=Bola();
       sacadas[bolas]=bola;
       bolas++;
       for(int i=0;i<20;i++){
           if(vectorcarton1[i]==bola){
               vectorcarton1[i]='X';
               contador1++;
           }
           for(int j=0;j<20;j++){
               printf("%d",vectorcarton1[j]);
               v=vectorcarton1[j]/10;
               if(v<1){
                   printf("  ");
               }else{
                   printf(" ");
               }
               if(j==4||j==9||j==14||j==19){
                   printf("\n");

               }
           }
           if(contador1==20){
               printf("Gana el jugador 1\n");
               final=1;
               return;

           }
       }

   }
   controladorCarton1=1;
}

void Carton2 (void){
   int numeroscarton2[100], y=0, z, vectorcarton2 [20], v;
   printf("Carton 2: \n");
   for(int x=0;x<100;x++){          //creo un vector con todos los numeros del 1 al 100
       numeroscarton2[y]=x+1;
       y++;
   }
   for(int u=0;u<20;u++){
       z=GeneradorNumero();

       do{
           z=GeneradorNumero();
       }while(numeroscarton2[z]==0);

       vectorcarton2[u]=numeroscarton2[z];
       numeroscarton2[z]=0;
       printf("%d",vectorcarton2[u]);
       v=vectorcarton2[u]/10;
       if(v<1){
           printf("  ");
       }else{
           printf(" ");
       }
       if(u==4||u==9||u==14||u==19){
           printf("\n");

       }
   }
}



int main(void){
   srand(time(NULL));
   ImprimoPrincipio();
   Carton1();
   printf("\n");
   Carton2();
   getchar();
   system("cls");
   do{
       ImprimoPrincipio();
       Carton1();
       getchar();
   }while(final==0);
   getchar();
   return 0;

}


MAFUS

Encierra tu código entre etiquetas code
Aprieta sobre edición en tu mensaje, después aprieta el botón # y cortas el código y lo pegas en medio de las dos etiquetas que te han aparecido.

vaillo33

Graciaas!!, ¿Alguien encuentra mis fallos?? :o

Serapis

El tiempo es oro. No pidas que revisen todo tu código para buscar fallos. Aparte que hay diferentes tipos de fallos, comenzando por el enfoque del problema...

Es infinitamente mejor (si quieres recibir ayuda), señalar que te falla. Así quien quiera ayudar se centra en la parte del código específica... para indicarte porqué falla.

vaillo33

La parte del código que falla es al crear una bola, y revisar el carton 1, para ver si tiene ese número el poner una X en vez del numero, pero muchas gracias por tu consejo nebire!

Serapis

#5
Tienes el código un poco enfarragoso.

antes de ponserse a escribir código, es mejor verlo en tu mente... Realmente se trata de reflejar tal como lo hacmeos en la realidad. Y así acostumbra a escribir en prosa, primero... verás que luego es casi traducir/transcribir...

Al iniciar el juego:
1 - Si no quedan cartones, crear x cartones.
Esta sola línea ya sugiere  3 cosas:
- Señala que debe haber un campo que refleje el número de cartones libres.
- Una función que crea cartones.
- Un parámetro en la función que señala cuantos cartones se van a crear...
- Previamente debe quedar claro, cuantas bolas contiene el bingo: 80, 90, 100, 120, etc...
- Previamente debe quedar claro, cuantos valores contiene cada cartón... 12,15, etc...


Y podría ser algo así:


   entero BolasXBingo = 100
   entero BolasPorCarton = 20

   entero SiguienteCarton          // Indice dle siguiente cartón disponible en la banca.
   entero CartonesXPartida = 2  // cantidad mínima a repartir para jugar una partida.
   array string CartonesBanca(0 a 99)  //tendrían la forma: -3-7-11-19-25-11-48-91-....94-  Es decir cada número de bola está encerrado entre guiones.



   funcion NuevaPartida
       Si ((SiguienteCarton+CartonesXPartida)  => BolasXBingo)
           CrearCartones((BolasXBingo-CartonesXPartida), SiguienteCarton)
       fin si

       ... más cosas que se irán añadiendo debajo.
   fin funcion



   Funcion CrearCartones(entero NumCartones, entero Inicio)
       entero k, fin

       fin = (Inicio + NumCartones)

       Si (fin <=BolasXBingo)
           bucle para k desde Inicio hasta fin
               CartonesBanca(k) = CrearNuevoCarton
           siguiente
       Sino
           bucle para k desde Inicio hasta BolasXBingo
               CartonesBanca(k) = CrearNuevoCarton
           siguiente

           fin = (fin modulo BolasXBingo)
           bucle para k desde 0 hasta fin
               CartonesBanca(k) = CrearNuevoCarton
           siguiente
       Fin si
   fin funcion

   // Crea un cartón nuevo. Sus bolas no están repetidas en el cartón, pero alguna puede aparecer en otros cartones.
   // Un cartón es un string, con los números d elas bolas encerrados todos ellos entre guiones, así:
   //        "-5-9-13-14-26-29-30-36-45-48-51-54-62-66-73-79-85-89-92-98-"
   string Funcion CrearNuevoCarton
       entero k, n
       string carton = "-"

       bucle para k desde 1 a BolasPorCarton
           Hacer
               n = random(entre 1 y BolasXBingo)
           Repetir mientras ExisteBolaEnCarton(carton, n) = TRUE

           carton = (carton + n.ToString + "-"
       Siguiente
     
       Devolver carton
   fin funcion

   // Verifica si existe una bola dada en un cartón.
   // Esta función se invoca mientras se crea un cartón y cuando se extrae una bola del bingo.
   buleano ExisteBolaEnCarton(string Carton, entero bola)
       string b = "-" + bola.ToString + "-"  //bola.ToString es una conversión de entero a string.
     
       //una búsqueda para ver si el string 'b' está contenido en el string 'carton'.
       // OJO: para buscar la bola 5, realmente buscamos "-5-", sino daría ok, si contuviera 15, 25, etc...
       devolver Carton.contiene(b)
   fin funcion


2 - Repartir cartones entre los jugadores.
Esta línea sugiere varias cosas:
- Hay varios jugadores, luego un campo debe reflejar cuantos jugadores son.
- Cuántos jugadores mínimos, se requieren para jugar el bingo. Quien dice jugadores, dice cartones.
- Es válido que un jugador tenga más de 1 cartón?.
- Los cartones simplemente se 'reparten' o se 'compran'...
Comprando la dinámica dle juego se complica un poco más, pués hay que poner precio a los cartones y ver si el jugador tiene suficiente dinero para comprar, además de llevar la cuenta del dinero de cada jugador más el de la banca.
-- Se puede simplicar repartiendo siempre por ejemplo x cartones (1,2 por ejemplo) a cada jugador.
-- Se puede simplificar dejando constante el número de jugadores (2,3,4,5,6 por ejemplo).
- Implica una función Repartir, que toma el siguiente cartón disponible y lo entrega al jugador.
Esto puede hacerse de 2 maneras, o se invoca una funcion 'getCarton', donde el  jugador es un parámetro de dicha función, donde se devuelve el cartón y al recibir se entrega al jugador.

Seguimos completando la función 'nuevapartida'... y el código fuera de funciones...

   entero JugadoresEnPartida = 2  // NUEVO: esto se pone arriba
   array entero CartonesDeJugadores(0 a JugadoresEnPartida -1) // NUEVO: ídem

   funcion NuevaPartida
       Si ((SiguienteCarton+CartonesXPartida)  => BolasXBingo)
            CrearCartones((BolasXBingo-CartonesXPartida), SiguienteCarton)
        fin si
   
       llamada a RepartirCartones  //NUEVO
     
       ... más cosas que se irán añadiendo debajo.
   fin funcion


RepartirCartones será una función que reparta todos los catones necesarios de la partida (en la modalidad simple para el juego basta así) que a su vez invoca a otra función que entrega el siguiente cartón disponible en la banca, en el array CartonesBanca.


   // hemos estabecido (para ejemplo) que se reparte 1 carton por jugador, y que aunque haya dos jugadores, su valor se almacena en JugadoresEnPartida y los cartones de cada en el array CartonesDeJugadores
   funcion RepartirCartones
       entero k

       bucle para k desde 0 a JugadoresEnPartida
             CartonesDeJugadores(k) = GetSiguienteCarton
       fin bucle
   fin funcion

   entero Funcion GetSiguienteCarton
       string carton

       carton = CartonesBanca(SiguienteCarton)
       SiguienteCarton = (SiguienteCarton +1)
       Si (SiguienteCarton = BolasXBingo) luego SiguienteCarton = 0

       devolver Carton
   fin funcion


3,4 y 5 - Ya tenemos creados los cartones y cada jugador con su cartón, aún faltan 3 cosas... iniciar el sorteo, verificar cuando se extrae una bola si tal o cual cartón la contiene y verificar cuando se canta bingo (cuando el juego acaba).
Volvemos a editar la función nueva partida... ya que es el 'main' del juego, la función principal.


   entero ValorPremio = 100  // NUEVO: esto se pone arriba
   array entero BolasBingo(0 a BolasXBingo-1) // NUEVO: ídem
   entero SiguienteBola   // NUEVO: ídem

   funcion NuevaPartida
       entero jugadorpremiado // NUEVO: ídem

       Si ((SiguienteCarton+CartonesXPartida)  => BolasXBingo)
            CrearCartones((BolasXBingo-CartonesXPartida), SiguienteCarton)
        fin si
   
       llamada a RepartirCartones  //NUEVO

       Llamada a BarajarBingo   // barajar el 'bombo'
       jugadorpremiado = Sortear  //sacar bolas del bingo

       Llamada a EntregarPremio(jugadorpremiado, ValorPremio)  //100 monedas para el ganador.
   fin funcion


3 - Recrear el bombo con sus bolas y barajarlas todas de una sola vez.

   funcion BarajarBingo
       entero i, j, k

       // Esto realmente es crear el bingo, bastaría invocarlo una sola vez cuando se abre el programa, las demás veces, solo barajarlo
       bucle para k desde 0  hasta BolasXBingo-1
           BolasBingo(k) = k+1   //las bolas se guardan en un array del 0 al 99, por ejemplo, pero el valor de las blas comienzan en 1 hasta el 100.
       siguiente

       // Ahora se baraja, con el algoritmo del sombrero (Fisher-Yates-Durstenfeld)
       bucle para k desde BolasXBingo-1 hasta 1 retrocediendo
           j = random(enter 0 y k)
           i = BolasBingo(j)
           BolasBingo(j)= BolasBingo(k)
           BolasBingo(k) = i
       siguiente

       SiguienteBola = 0
   fin funcion


4 - Como en el bombo se han barajado ya todas las bolas de una sola vez, el sorteo consiste en sacarlas en orden...

   entero = Funcion Sortear
       entero jp, bola

       // El bucle acaba cuando se da el premio.
       // NOTA: que salvo que esté mal programado, el premio se otorgará sí o sí, como muy tarde, con la última bola del bombo
       //     por ello resulta estéril añadir como segunda condición: (SiguienteBola < BolasXBingo)
       Hacer
           bola= BolasBingo(SiguienteBola)
           llamada a VerificarCartones(bola)
           jp = VerificarPremiado
           SiguienteBola= (SiguienteBola + 1)
       Repetir mientras  (jp= -1)

       devolver jp  // jp es el jugador premiado.
   fin funcion


Ahora verificamos cartones, esto es, tachamos la bola extraída en cada cartón que la contenga.

   Funcion VerificarCartones(entero BolaExtraida)
       entero k, ini, fin
       
       fin = (SiguienteCarton - 1)
       ini = (fin - CartonesXPartida)

       // OJO: Podría darse el caso que un cartón sea el 100 y el otro el 1... queda a tu esfuerzo, solucionar tales casos.
       bucle para k desde ini hasta fin
           Si ExisteBolaEnCarton(CartonesDeJugadores(k), BolaExtraida)
               TacharBola(CartonesDeJugadores(k), BolaExtraida)
           Fin si
       Siguiente
   fin funcion

   function TacharBola(string carton, entero bola)
       string b = bola.ToString
       carton.Remplazar(b, "x")   // se busca el texto (número) de la bola 'b' en cartón y se remplaza por 'x'
   fin funcion


5 - Esta función revisa cada cartón para ver si alguno tiene tachada todas las bolas.
Es más óptimo hacer esta revisión al mismo tiempo que revisa la bola a tachar, lo anoto más abajo como una observación.

   entero = Funcion VerificarPremiado
       entero k, ini, fin
       
       fin = (SiguienteCarton - 1)
       ini = (fin - CartonesXPartida)

       // OJO: Podría darse el caso que un cartón sea el 100 y el otro el 1... queda a tu esfuerzo, solucionar tales casos.
       bucle para k desde ini hasta fin
           Si CartonTieneTodasTachadas(CartonesDeJugadores(k))
               devolver k
           Fin si
       siguiente
       devlver -1
   Fin funcion

   // esta función es subóptima. Trata de buscar si contiene todas las bolas tachadas.
   buleano = funcion CartonTieneTodasTachadas(string carton)
       entero j, k, n
       string x
       
       j=0
       bucle para k desde 1 hasta BolasPorCarton
           // la función contiene, devuelve la posición donde aparece 'x', si no se encuentra teóricamente devuelve -1
           //     el parámetro j, indica desde donde comenzar a buscar
           n = Carton.Contiene("x", j)  
           Si (n > j)
               j = n+1
           sino
               devolver FALSE
           fin si    
       siguiente

       devolver TRUE
   fin funcion




NOTAS:
- Pasar el pseudocódigo a código queda a tu esfuerzo.
- Puede haber más de un premiado a la vez (esto es, tendrían un cartón idéntico), queda también a tu esfuerzo, o bien impedir esto, o bien repartir el premio entre los jugadores, así como verificar todos los cartones en busca d epremio. En el pseudocódigo se asume que solo un jugador puede ganar, luego si swe encuentra un ganador se aborta el resto de la búsqueda.
- No se añade pseudocódigo para la función EntregarPremio, queda a tu esfuerozo, si resulta de interés al caso.
- Una ligera optimización sobre cartones: En el propio cartón se podría indicar además las bolas restantes para bingo, por ejemplo al inicio o final del string del cartón se podría poner el número de bolas sin tachar (cuandos e crea el cartón se pone el número total de blas por cartón) y cuando se tache una, tomar el valor, restar uno y actualizar dicho valor (resulta muy fácil si es al comienzo o final dle string). Si un cartón llega a cero, será premiado, con lo que la misma función de verificar cartones para tachar bolas y buscar cartón premiado sería la misma.... como cada bola va encerrada entre guiones "-34-", este valor podría diferenciarse encerrándolo de forma diferente, así nunca se encontrará por error ese número, como una bola y se tache.


- Finalmente nota, que el pseudocófigo no es óptimo, ateniéndose a: "juego del bingo simplificado". Ya que por ejemplo, al crear cartones, nunca se buscan aleatoriamente los números, sino que las bolas del bingo deben proporcionar números de cartones exactos (por ejemplo  de un bingo de 100 bolas, da 5 cartones de 20 números, un bingo de 90 bolas da 6 cartones de 15 números, un bingo de 84 bolas da 7 cartones de 12 bolas, etc...), entonces las bolas del bingo, primero se crea un array del 1 a la última bola, y se baraja... entonces ese array acotado en tandas de 20, 15, 12... esto es, según la cantidad de bolas por cartón, son lo que definen un cartón. Así en ese array las bolas dle primer cartón son las que ocupan las posiciones en el array del 0 al 19, el 2º cartón 20 a 39... el 5º cartón 80 a 99). Y para ser equitativos, además habría de cumplirse ciertos requisitos mucho más restrictivos sobre los cartones, esto es estar equitativamente compensados en el reparto de bolas, a nadie le haría gracia tener las bolas 5,6,7,8,9 y 24,25,26,27,28 en su cartón...sino mas bien 2 o 3 bolas de cada decena... Cuando no es así, no es verdaderamente equitativo el azar para cada jugador. Eso sí, para un ejecrcicio vale...

- Quizás se me haya escapado algún gazapo... confío que en tal caso puedas verlo sobre la marcha.

vaillo33

Muchismaas gracias, realmente me has ayudado mas de lo que esperaba, tus consejos los utilizaré cada vez que tenga que programar!!!!. :D