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.