Usted y su colega han sido contratados por una pequeña empresa de juegos de azar. La empresa quiere personalizar más su juego de bingo. Actualmente utiliza los clásicos cartones de 25 celdas numeradas que se adquieren en algunas librerías. En la empresa quieren tener la capacidad de cambiar el diseño por uno propio, y en algunos eventos los números por otros símbolos. Por ejemplo, para un "té de canastilla" quieren permitir al cliente escoger las 75 palabras y fabricar cartones con ellas. La empresa necesita un software que además de generar cartones con palabras o símbolos arbitrarios, sea capaz de "cantar el bingo", es decir, simular una sesión de juego. Finalmente la compañía espera que durante dicha sesión el software indique cuándo y cuáles han sido los cartones ganadores de acuerdo a las diferentes modalidades de juego: cuatro esquinas, línea/diagonal, L, o cartón lleno.
El proyecto se ha dividido en varias fases. En la primera se pretende hacer un comando que realice el trabajo descrito anteriormente. Si la fase es exitosa, la empresa les podría recontratar para hacer una versión de la aplicación con interfaz gráfica más amigable para los empleados. Una tercera fase podría darse para implementar una versión web, donde los jugaores de bingo compren y jueguen en línea. Este enunciado de proyecto sólo cubre la primera fase, es decir, se debe implementar un comando que realice lo siguiente:
$ bingo --help Create Bingo cards and simulate game sessions. Usage: bingo generate NUMBER card.svg [-s symbols.txt] [-c callingcard.svg] bingo call [card.idx] [-t type] [-s symbols.txt] [-w winners] Actions: generate Generate random cards in current directory call Simulate a bingo game session Options: NUMBER Number of cards to be generated card.svg Graphic design of the card with ${field} placeholders card.idx Contains all the generated cards and their 24 or 25 symbols -c callingcard.svg Fill out the given calling card with all 75 symbols -s symbols.txt Use the given 75 symbols instead of numbers -t type Pattern to be matched in order to win. Valid types: four-corners, straight-line, diagonal, any-line, roving-L, blackout -w winners Number of winners until finish the session
Ustedes y el personal de la pequeña empresa, han acordado tres avances de proyecto o entregables. Uno cada semana, de tal forma que permita a la empresa percibir el avance del software y poder decidir mejoras o cambios si fuese necesario. Los entregables se describen en las siguientes secciones. Los porcentajes de cada entregable indican el porcentaje de pago que la empresa les dará del proyecto total.
En esta fase se implementa la capacidad de generar cartones de bingo. El siguiente ejemplo de invocación
$ bingo generate 1000 classic.svg
indica al comando que debe generar 1000 cartones de bingo utilizando el diseño incluido en el archivo classic.svg
, al cual llamaremos la plantilla del cartón. La pequeña empresa cuenta con un diseñador gráfico que realiza el diseño de los cartones en un programa de ilustración. El diseño lo almacena en un archivo de gráficos vectoriales redimensionables (SVG, Scalable Vector Graphics). Es un archivo de texto en formato XML, similar al HTML, con la diferencia de que en lugar de ser elementos de una página web (como párrafos/imágenes/enlaces), son de diseño, como rectángulos, curvas, y efectos.
El comando bingo
no debe afectar el diseño gráfico del cartón, sino, su contenido. El contenido del cartón son 25 ó 26 textos: el número de cartón, y los números/símbolos que deben ser escritos en las celdas (seleccionados al azar). Por acuerdo con la empresa, el diseñador gráfico marcará estos campos dentro del archivo SVG con el formato ${field}
. El campo ${card_number} debe ser cambiado con el número de cartón, y los 24 ó 25 campos ${N,M}
con el número o símbolo escogido al azar para la fila número N
y columna número M
. La celda del centro del cartón se marca con ${center}
, que podría ser reemplazada por un carácter (como un asterisco) o un número si se quiere el cartón de 25 números. El cartón resultante de reemplazar todos los campos ${field}
es otro archivo SVG, que debe ser almacenado en la misma carpeta donde se encuentra la plantilla del cartón. Los nombres de los cartones generados son escogidos por los desarrolladores, por ejemplo, classic-0001.svg
, classic-0002.svg
, ..., classic-1000.svg
.
bingo_cards.zip
El ejemplo de invocación anterior, bingo generate 1000 classic.svg
, no indica los símbolos a utilizar en las celdas, por tanto, el comando asumirá que son los números de 1 a 75. El usuario puede indicar al comando utilizar otros símbolos con el parámetro -s
. Por ejemplo:
$ bingo generate 240 babyshower.svg -s babywords.txt
indica que se deben generar 240 cartones de bingo, utilizando la plantilla babyshower.svg
y en lugar de utilizar números de 1 a 75, se deben utilizar las palabras almacenadas en babywords.txt
. El archivo de símbolos (babywords.txt
) debe contener 75 líneas no vacías. Si tuviera menos es un error, su tuviera más se ignoran a partir de la 76. Cada línea representa un símbolo, el cual puede ser un texto o [opcional] un nombre de un archivo de imagen. En cualquier caso, los 75 símbolos (sean números, palabras o nombres de archivos de imagen), se deben dividir en 5 grupos. Cada grupo se asigna a una única columna en los cartones. Por ejemplo, los primeros 75/5==15 números (de 1 a 15) se deben asignar al azar únicamente en la primera columna (usualmente rotulada con "B"), los siguientes 15 números (de 16 a 30) en la segunda columna (rotulada con "I") y así sucesivamente.
Note además que como cualquier otro comando, bingo
debe ser capaz de mostrar ayuda con el parámetro --help
, y su versión e información de contacto de los desarrolladores con el parámetro --version
.
Dado que este entregable es parte de la primera fase del proyecto y el código se piensa reutilizar para las aplicaciones gráficas y en web, ustedes deben desarrollar clases reutilizables. Utilice la Biblioteca Estándar de C++ cuanto sea posible. El primer entregable consta de:
Al final de la primera semana la empresa tendrá la capacidad de producir cartones de bingo e imprimirlos. Para la segunda semana, la pequeña empresa espera poder jugar bingo al estilo tradicional, es decir, cantar los números o los símbolos sea usando una tómbola, fichas o una computadora.
Para cartones numerados de 1 a 75 la empresa dispone de tómbolas con bolas numeradas. Pero para cartones de símbolos escogidos por el usuario, se deben fabricar las fichas manualmente. Es deseable que el programa produzca un cartón de fichas para cantar el bingo. Este cartón contiene todos los 75 símbolos. Después de impreso y recortado, se le brinda al locutor para que escoja las fichas al azar mientras canta el bingo. Su programa produciría este cartón al invocarse con la opción -c
, por ejemplo:
$ bingo generate 240 babyshower.svg -s babywords.txt -c callingcard.svg
Al ejecutar el comando anterior, el programa bingo
además de producir 240 cartones, produciría un archivo babywords-callingcard.svg
que contiene los 75 símbolos obtenidos de babywords.txt
, pero con un formato diseñado para impresión y recorte. El archivo callingcard.svg
es similar al de un cartón usual de bingo, con la diferencia de que no contiene 25 celdas, sino 75 celdas con el campo ${symbol}
. Cada campo debe reemplazarse por uno de los 75 símbolos. Las celdas están diseñadas para recortarse y producir las fichas que el animador del evento utilizará para escoger al azar y cantar el bingo.
bingo_cards.zip
Si el usuario olvida generar el cartón de fichas durante la generación de los cartones de bingo, podrá hacerlo posteriormente, indicando lo único necesario: el archivo de símbolos (con el parámetro -s
) y el diseño del cartón de fichas (con el parámetro -c
). Por ejemplo:
$ bingo generate -s babywords.txt -c callingcard.svg
El nombre del cartón de fichas resultante será la combinación del nombre del archivo de símbolos, un guión, y el nombre y extensión del archivo de diseño del cartón de fichas. En la invocación anterior corresponde a babywords-callingcard.svg
.
Si no se tiene una tómbola o fichas, o el evento es virtual, resulta conveniente o necesario que la computadora "cante el bingo". Por ejemplo, la invocación
$ bingo call
provocará que el programa cante al azar los números entre 1 y 75. Los números (o símbolos) se cantan en modo interactivo. Es decir, el programa escoge un número o símbolo al azar, lo presenta pero no pasa al siguiente de inmediato, sino que espera a que se presione la tecla Entrar antes de continuar con el siguiente número o símbolo. En cada iteración se imprime además el estado de las fichas. Por ejemplo:
$ bingo call Bingo call for symbols 1 through 75 Press ENTER key to call next number...⏎ B -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- I -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- N -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- G -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- O -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- Number: 65 ⏎ B -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- I -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- N -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- G -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- O -- -- -- -- 65 -- -- -- -- -- -- -- -- -- -- Number: 25 ⏎ B -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- I -- -- -- -- -- -- -- -- -- 25 -- -- -- -- -- N -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- G -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- O -- -- -- -- 65 -- -- -- -- -- -- -- -- -- -- Number: 73 ⏎ ...
El programa termina su ejecución al acabar todos los números/símbolos o si el usuario ingresa el carácter EOF en lugar de presionar un Enter. En la invocación anterior no se especificó un archivo de símbolos, por lo que se utilizaron números de 1 a 75. Si se especifica un archivo de símbolos, estos ocuparán mucho espacio horizontal, por lo que se debe transponer la salida. Por ejemplo:
$ bingo call -s animalescr.txt Bingo call for symbols animalescr.txt Press ENTER key to call next symbol...⏎ B I N G O ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ Symbol 1: tepezcuintle⏎ B I N G O ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ tepezcuintle------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ Symbol 2: cuyeo⏎ B I N G O ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ tepezcuintle------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ cuyeo------------- ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ------------------ Symbol 3: zompopa⏎ ...
El algoritmo para seleccionar los números o símbolos debe ser eficiente. Prefiera algoritmos de shuffle. Note que en la impresión del tablero de fichas, cada número o ficha ocupa un campo de tamaño fijo. Para los símbolos el programa deberá determinar el ancho máximo, el cual puede variar de un listado a otro de símbolos.
Hasta el momento, cuando se le pide al programa generar cartones de bingo, este produce N
cartones en archivos SVG. Sin embargo en el próximo entregable, el programa deberá ser capaz de indicar inmediatamente cuándo un cartón ha ganado. El programa necesita información de cada cartón, pero buscar en los archivos SVG es impráctico e ineficiente.
Durante la generación de los cartones, el programa deberá además generar un archivo de índice. La función de este archivo es permitir al programa saber rápidamente cuáles números o símbolos componen a cada cartón. O dicho de otra forma, es un archivo que permite rápidamente cargar o recuperar los cartones que fueron generados previamente. El archivo de índice deberá tener el mismo nombre de la plantilla del cartón, pero con la extensión .idx
. La invocación
$ bingo generate 1000 classic.svg
genera 1000 archivos en la forma classic-I.svg
, donde I
va de 0001 a 1000, y además un archivo classic.idx
, con los 24 ó 25 números que componen a cada cartón. La invocación
$ bingo generate 240 babyshower.svg -s babywords.txt
debe generar 240 archivos SVG y un archivo babyshower.idx
con los 24 ó 25 símbolos que componen a cada cartón.
En resumen el segundo entregable consta de
${symbol}
.bingo generate -s symbols.txt -c callingcard.svg
.shuffle
.En la tercera semana la pequeña empresa espera que el programa mientras canta los números o los símbolos, sea capaz de indicar de inmediato cuáles son los cartones ganadores. Esta funcionalidad es útil para los juegos presenciales, pero realmente indispensable para los juegos virtuales. Para que el programa pueda determinar cartones ganadores, se le debe indicar dos parámetros: el archivo de índice y el tipo de juego, por ejemplo:
$ bingo call basic_v.idx -t four-corners
Indica al programa que debe cantar números de 1 a 75, y reporte cada vez que un cartón contenido en el índice basic_v.idx
llene sus cuatro esquinas. La siguiente podría ser una sesión hipotética
$ bingo call basic_v.idx -t four-corners Four corners Bingo call for symbols 1 through 75 Press ENTER key to call next number...⏎ [...] Number: 48 ⏎ B -- -- 03 04 -- -- -- -- 09 10 -- -- -- 14 -- I -- -- -- -- 20 -- -- -- -- 25 26 -- -- -- -- N -- -- 33 -- 35 -- -- -- -- -- 41 -- 43 -- -- G -- -- 48 49 -- -- -- 53 -- 55 -- 57 58 -- -- O 61 -- 63 -- 65 66 67 68 69 70 -- -- 73 74 -- Number: 15 B I N G O ! ! ! Winner 1: card # 0869 ⏎ B -- -- 03 04 -- -- -- -- 09 10 -- -- -- 14 15 I -- -- -- -- 20 -- -- -- -- 25 26 -- -- -- -- N -- -- 33 -- 35 -- -- -- -- -- 41 -- 43 -- -- G -- -- 48 49 -- -- -- 53 -- 55 -- 57 58 -- -- O 61 -- 63 -- 65 66 67 68 69 70 -- -- 73 74 -- Number: 28 ⏎ B -- -- 03 04 -- -- -- -- 09 10 -- -- -- 14 15 I -- -- -- -- 20 -- -- -- -- 25 26 -- 28 -- -- N -- -- 33 -- 35 -- -- -- -- -- 41 -- 43 -- -- G -- -- 48 49 -- -- -- 53 -- 55 -- 57 58 -- -- O 61 -- 63 -- 65 66 67 68 69 70 -- -- 73 74 -- Number: 6 B I N G O ! ! ! Winner 2: card # 0448 Winner 3: card # 0107 Press ENTER key to call next number...EOF $
El parámetro -t type
indica el tipo de patrón que se debe llenar para ganar un bingo. Los valores válidos se listan a continuación. Si no se especifica el parámetro -t
se asume cartón lleno (blackout
).
four-corners
. Debe llenar las cuatro esquinas del cartón.straight-line
. Cualquiera de las 10 líneas horizontales o verticales del cartón.diagonal
. Cualquiera de las dos diagonales del cartón.any-line
. Cualquiera de las 12 líneas horizontales, verticales o diagonales.roving-L
. Cualquiera de las cuatro L.blackout
. Cartón lleno (por defecto).Si se especifica el parámetro -s symbols.txt
, en lugar de cantar números de 1 a 75, se escogen al azar los símbolos encontrados en el archivo. El estado de las fichas se presenta de forma transpuesta.
Por defecto, el programa continúa cantando números aunque algún cartón haya ganado un bingo. El programa se detiene hasta que se ingrese EOF
o se acaben los 75 símbolos. Sin embargo, en algunas circustancias, el organizador de un evento de bingo podría tener un número limitado de premios. Por ejemplo, si se tienen premios para los primeros 5 cartones que llenen una L en un bingo de términos de programación, se podría invocar:
$ bingo call programming.idx -s programming.txt -t roving-L -w 5
La instrucción siguiente le indica al programa cantar el bingo utilizando símbolos de programación; avisar cuándo un cartón llena una L; y terminar la ejecución cuando 5 cartones (distintos) hayan ganado, es decir, cuando se tengan 5 ganadores (winners) y por tanto, se hayan repartido los 5 premios.
En resumen el tercer entregable consta de
-t
. Reporta los cartones ganadores de acuerdo a cada uno de los seis tipos de patrones de juego: four-corners
, straight-line
, diagonal
, any-line
, roving-L
, blackout
.-w
con un número N
, termina la ejecución del programa cuando se han encontrado N
ganadores.