Voy a hacerte una somera descripción intentando usar los datos de tu estrucutra cuanto se aposible y útil
De entrada mantenemos la estructura del jugador muy similar. No declaro el tipo de cada datos, hazlo según tu conveniencia.
Estructura DatosJugador
Nombre
Apellido
Cedula //Cada cédula es unica. OK: pero un jugador puede comprar más de un cartón, verdad?... entonces esto no importa.
Monto //Esto es para pagar el cartón??????
IndexCarton // Cada cartón es único
BolasTachadas //Restan // Le cambio el nombre, su propósito es confuso con ese nombre.
//Record // ¿es realmente necesario?. Si sí, añade el soporte para esto cuando lo demás, lo elemental para el juego funcione.
Fin Estructura
Array tipo DatosJugador Jugadores() //este array contiene a todos los jugadores.
Los cartones, mejor que considerar chorrocientos cartones, es considerar un array muy grande, el cartón nº 1 toma los índices del 0 al 19, el nº 2 del 20 al 39, el cartón nº 3, del 40 al 59... etc...
Array tipo Entero Cartones() //este array contiene los cartones de todos los jugadores.
Array tipo Entero BolasPremio() // este array contiene las bolas que van saliendo. consideramos las bolas desde 0 a 99.
// Estos valores cámbialos a tu gusto, los que pongo son de ejemplo.
Constante c_MaximoJugadores = 25 //si se alcanza los 25 jugadores, se rechaza añadir más jugadores a la partida.
constante c_MinJugadores = 2 // si hay menos jugadores, no hay ppartida posible.
Constante c_ValoresXCarton = 20 ' 4 filas por 5 columnas, Acertar una fila es =
Entero NumJugadoresPartida //se pone al terminar una partida, y se va actualizando a medida que ingresan los jugadores.
Constante c_PrecioCarton = 25 // bingocoins. Lo que paga un jugador por cada cartón que compra.
Constante c_PremioXLinea = 200 //bingocoins. Lo que recibe un jugador si 'canta línea' .
Constante c_PremioXBingo = 1500 //bingocoins. lo que recibe un jugador si 'canta bingo'.
Evento IngresarJugador(Nombre, Apellido, Cedula, Monto, Mas)
Funcion CrearInstancia // Equivale al New
// Este array lo podemos redimensionar una vez al valor máximo alcanzable (sigue siendo un valor muy manejable). Evita redimensionarlo en cada partida con el número de jugadores en curso.
Redimensionar Cartones(0 a (c_Maxjugadores * c_ValoresXCarton) -1 )
Redimensionar BolasPremio(0 a 99) // el array del premio también basta con redimensionarlo una vez cuandos e crea la instancia.
fin Funcion
Ambos arrays podrían ser uno solo, si al array Cartones se le añaden 100 posiciones más al final. Pero resultará más cómodo operar de forma separada.
// NumJugadores, debiera ser por ejemplo el número de jugadores inscritos en una lista... (interesador en jugar una partida).
//Un jugador puede estar anotado más de una vez, (esto es quiere participar con más de 1 cartón si es en la misma partida).
//El orden de acceso es riguroso... en el orden de anotados en la lista.
Buleano = Funcion NuevaPartida(NumJugadores)
Si (NumJugadores < c_Minjugadores) luego
Devolver FALSE
Fin si
Si (NumJugadores > c_Maxjugadores) luego
NumJugadores = c_Maxjugadores //se trunca al máximo, o se devuelve FALSE
Fin si
Redimensionar array Jugadores(0 a NumJugadores-1)
Buleano Ingresado=FALSE, Mas=FALSE
Bucle para k desde 0 a NumJugadores -1
Hacer // Añade un jugador en cada ciclo. Damos por hecho que es así, pero si
Ingresado = IngresarJ(k, Mas)
Repetir Mientras (Ingresado = FALSE) y (Mas = TRUE)
Fin bucle
NumJugadoresPartida = (k -1)
// Volvemos a comprobar que hay jugadores suficientes. Antes eran los interesados, ahora los que pudieron pagar su cartón.
Si (NumJugadoresPartida < c_Minjugadores) luego
Devolver FALSE
Fin si
llamada a Barajar //barajamos los valores de los cartones y los premios que hayan de salir.
Devolver TRUE
Fin Funcion
Esta función dispara un evento para solicitar al cliente los datos d elos jugadores inscritos en una lista con intención de jugar...
Chequea si pueden pagar el cartón, si no es así, saltará al siguiente...
No precisa chequear si la cédula existe ya, porque eso evita que un jugador pueda comprar más de un cartón.
Descuenta el preio del cartón al jugador si entra en la partida.
Buleano = Funcion IngresarJ(Entero K, Buleano Mas)
// En cada disparo de evento, debiera añadirse un jugador, procedente quizás de una lista de interesados a la espera de una 'mesa y silla' (un hueco en la partida).
DispararEvento IngresarJugador(Nombre, Apellidos, Cedula, Monto, Mas)
//Mas, debe devolver si hay más jugadores en la lista apuntados aparte de éste que se ingresa.
// esto es devolver TRUE, si no es el último en la lista, Y FALSE cuando sea el último.
Si (Monto >= c_PrecioCarton) luego // Si no puede pagar el cartón, no puede jugar???. El jugador no entra en esta partida.
//No verificamos que cédula no existe ya, porque esto imposibilita que un jugador pueda comprar más de un cartón
Jugadores(k).Nombre = Nombre
Jugadores(k).Apellidos = Apellidos
Jugadores(k).Cedula = Cedula
Jugadores(k).IndexCarton = (k * c_ValoresXCarton) //los valores de su cartón van desde dicho valor hasta 19 más arriba, tenemos 20 valores por cartón.
Jugadores(k).BolasTachadas = 0
Monto -= c_PrecioCarton //cobramos el cartón. Monto debe ser pasado por referencia, si no,
//el monto en origen no habrá cambiado. Solo se cobra si el jugador finalmente entra en la partida.
Jugadores(k).Monto = Monto // ya hemos descontado el precio del cartón, previamente.
Devolver TRUE
Si no
Devolver FALSE
Fin si
Fin funcion
Baraja los cartones y luego los premios. En ambos casos se acaba llamando finalmente a una misma función...
Funcion Barajar
// Barajar cartones...
llamada a BarajarCartones2
// Barajar Premios
BolasPremio = Barajar100
fin funcion
Esta función es simple, pero tiene un grave problema...
...y es que no garantiza que un valor no aparezca más de 1 vez en un mismo cartón.
Se provee una mejor solución en la siguiente función.
función la solución óptima.
Funcion BarajarCartones1
Bucle para k desde 0 hasta Cartones.LimiteMayor-1
Cartones(k) = Aleatorio(entre 0 y 99)
Fin bucle
Fin funcion
Esta función baraja los valores de los cartones...
Y garantiza que un valor no aparezca repetido en un mismo cartón.
No existen cartones separados, es un solo array donde un cartón va a continuación del previo...
Funcion BarajarCartones2
Array Bolas(0 a 99)
j = 0
Bucle para k desde 0 hasta NumJugadoresPartida -1
Bolas = Barajar100
n = 0
Bucle para i desde j hasta (j + c_ValoresXCarton - 1) // tomamos las primeras 20 bolas (que ya fueron barajadas. También podría elegirse al azar entre bolas, pero estando ya barajadas es superfluo.
Cartones(j) = Bolas(n)
n +=1 //n irá desde 0 a 19...
Fin Bucle
j = i // es equivalente a: j += c_ValoresXCarton, ó también: j += n
Fin bucle
Fin funcion
Crea un array de 100 elementos donde todos aparecen 1 vez (para garantizar la misma probabilidad a cada jugador-cartón). Luego lo que se baraja es el orden que ocupará cada valor en el array...
Array = Funcion Barajar100
Array Bolas(0 a 99)
//Bucle necesario, porque todos los valores han de tener la misma posibilidad de salir,
// luego todos los valores han de constar el mismo número de veces (al caso 1)
Bucle para k desde 0 hasta 99
Bolas(k) = k
Fin bucle
//Ahora se barajan cambiando el orden que ocupan. ...Pero todos siguen constando 1 sola vez,
// luego si se toman x bolas (sean las que sean), todas serán distintas (ninguna aparece repetida).
Bucle para k desde 99 hasta 1 retrocediendo de 1 en 1
tmp = Aleatorio(entre k y 1)
Bolas(tmp) = Bolas(k)
Bolas(k) = Bolas(tmp)
Fin bucle
Devolver Bolas //entrega el array barajado.
Fin Funcion
Puesto que hay 100 bolas en el bingo (valores 0 a 99), y los cartones tienen solo 20 valores, está garantizado que el bingo a lo sumo se resuelve en tantos bolas sacadas como la salida de la última bola.
Va quedando pués la función que va extrayendo las bolas (recuerda que las bolas que van a salir las hemos barajado ya de antemano, saldrán en un orden aleatorio y todas constan en el bingo y aparecen 1 sola vez.
Esta función llamará a otras de comprobación...
Funcion IniciarPartida //Esta función debe invocarse solo tras la función NuevaPartida y solo si aquella devuelve TRUE
Entero Bolas = 0 //cantidad de valores que se han sacado ya del bingo.
Entero Bola //valor actual que se acaba de sacar del bingo.
Buleano Bingo = False //alguien cantó bingo?
Buleano Linea = False //alguien cantó Linea?
Entero Lineas //para verificar las diferentes líneas en busca de 'línea'
Entero Index //Indice donde localizar en el cartón
Hacer
//Sacar la siguiente bola del bingo.
Bola = BolasPremio(Bolas) // ya están barajadas.
Bucle para j desde 0 a NumJugadoresPartida -1
//Indice apunta al cartón del jugador (índice en el array donde comienza) para el jugador que se va a verificar su cartón.
Indice = (j * c_ValoresXCarton)
Si (Linea = FALSE) luego //No puede cantarse 'Bingo' sin antes cantarse 'Linea'
Lineas = 0
Hacer // Este bucle verifica las 4 líneas (de un cartón), para al encontrar una, la primera... se 'cante' línea...
Linea = VarificarLinea(Indice , Bola, j)
Si (Linea = TRUE) luego //pagar al jugador que obtuvo la línea.
Jugadores(j).Monto += c_PremioXLinea
Fin si
Lineas += 1
Indice += 5
Repetir Mientras (Lineas < 3) y (Linea = FALSE)
Si no
Bingo = VerificarBingo(Indice, Bola,j)
Si (Bingo = TRUE) luego // pagar al jugador que obtuvo el bingo, y será fin de la partida...
Jugadores(j).Monto += c_PremioXBingo
Fin si
Fin si
Siguiente en bucle
Bolas += 1
Repetir Mientras (Bolas < 100) y (Bingo = FALSE)
Fin funcion
Para ser honestos, hay que dar la posibilidad de que haya más de un jugador que cante, "Linea" y "Bingo" en la misma tirada de la bola (y repartir el premio entre todos ellos, no otorgarlo al primero que lo cante (que al caso es el primero que aparece en el array).
... Queda a tu esfuerzo hacer las modificaciones pertienentes para cubrir esa posibilidad....
Hay 4 líneas y cada línea ocupa 5 valores. El '5' podría ser tambén una constante c_LargoLinea=5 y '4' como c_NumLineas=4
Un valor coincidente se puede tachar poniendo su valor a -1. Así se puede contar cuantas bolas s ehan tachado en una línea.
Ojo: Esta función verifica 1 sola línea del cartón, por eso en su llamada se llama varias veces (desde la función que la invoca) hasta cubrir todas las líneas del cartón.
Por tanto podría optimizarse, Cuando se 'tache' una bola, ya no es preciso comprobar el resto de líneas del cartón (aunque sí, la línea entera).
Buleano = Funcion VerificarLinea(Entero Index, Entero Bola, Entero Jugador)
Entero n
Bucle para k desde Index a (Index + 4) // por ejemplo 0,1,2,3,4 ó: 5,6,7,8,9
Si (Cartones(k) = -1) luego
n += 1 //contamos las tachadas en esta línea
Si no
Si (Cartones(k) = Bola) luego
Cartones(k ) = -1 // Tachada para la próxima vez
Jugadores(Jugador).BolasTachadas +=1
n += 1
Fin si
Fin si
Fin bucle
// Si están tachadas todas en la línea devuelve TRUE, obtuvo Linea.
Devolver (n = 5)
Fin funcion
Es parecida a la previa, pero la cuenta de 'BolasTachadas' determina si se logró el bingo.
Buleano = Funcion VerificarBingo(Entero Index, Entero Bola, Entero Jugador)
Bucle para k desde Index a Index + c_ValoresXCarton-1
Si (Cartones(k) = Bola) luego
Cartones(k ) = -1 // Tachada para la próxima vez
Jugadores(Jugador).BolasTachadas +=1
Fin si
Fin bucle
//Si las tachadas = todas las que tiene el cartón devulve TRUE, obtuvo Bingo.
Devolver (Jugadores(Jugador).BolasTachadas = c_ValoresXCarton)
Fin funcion
El pseudocódigo lo he escrito sobre la marcha de un plumazo, así que es normal que haya alguna inconsistencia y que haya de ser repasado... pero es más que suficiente para ofrecerte un vistazo claro de la dinámica del juego y por donde van los tiros...
Queda básicamente, la parte de la lista de los interesados en jugar, que debería ser algún tipo de lista... donde los jugadores se inscriben y pueden hacerlo más de una vez. Su inscripción solo debe requerir sus datos: nombre, apellidos, cédula... el monto, jamás debe ser pasado por valor, si no por refernecia, so pena de que una múltiple inscripción, no descontaría del monto real, si no de la copia recibida a cada ocasión... eso, la parte de la interfaz o de consola (si tiras por consla) y entenderlo para pasarlo a C ó al lenguaje que quieras, queda a tu esfuerzo)...
Se me hace raro que uses letras... pero bueno, es cuestión de adaptarlo si esto es imprescindibles. En todo caso con letras los valores irían del 0 al 25 (letras A-Z), luego no parece que tenga mucho sentido tener ¿¿¿¿cartones de 25 letras????... en ese caso usa cartones de 8-12 letras.
-----------------------------------
p.d.: Repasado un poco y mejorada la indentación y añadido algunos comentarios más...
Con cualquier duda pregunta...