Crea Cartones de Bingo automáticamente en Java

Hola a todos, hoy os voy a explicar como podemos generar un cartón de bingo con Java.

Seguro que alguna vez has jugado al bingo en tu vida, tenemos unos cartones con una serie de números y de huecos, pero ¿Cómo podríamos generarlos? Vamos a verlo.

Formato y reglas de un cartón de bingo

El cartón de bingo tiene unas reglas especificas que se deben cumplir:

  • Cada fila tiene 5 números y 4 huecos vacíos.
  • Cada columna tiene 1 número y 2 huecos o 2 números y 1 hueco vacío.
  • Las columnas están ordenadas de menor a mayor, siendo el menor el que mas arriba este.
  • Cada columna tiene un rango de números:
    • Columna 1: 1-9
    • Columna 2: 10-19
    • Columna 3: 20-29
    • Columna 4: 30-39
    • Columna 5: 40-49
    • Columna 6: 50-59
    • Columna 7: 60-69
    • Columna 8: 70-79
    • Columna 9: 80-90

Analiza esta foto y comprueba que se cumple todo lo anterior:

carton bingo java

Te dejo un PDF con más ejemplos.

Pasos a realizar para crear un cartón de bingo

¿Cómo lo representamos? El cartón de bingo lo vamos a representar como una matriz de números de 3 filas y 9 columnas. Los huecos los representaremos como un -1.

Tenemos una serie de pasos que tenemos que realizar para generarlo:

  1. Rellenar nuestra matriz de números.
  2. Ordenar números por cada columna.
  3. Poner los huecos.
  4. Mostrar el cartón, sustituyendo -1 por el carácter deseado.

Seguramente, te estés preguntado que porque no marco los huecos antes de rellenar todo si luego lo voy a sustituir por -1, la razón es simple, por la ordenación de columnas, ya que puede afectar a la ordenación, se puede hacer, pero implica más código.

Código base para nuestro cartón de bingo

Para cada paso, utilizaremos una función pero tendremos un código inicial que es este:

package ejercicio_matrices_ddr_14;

import java.util.Arrays;

public class Ejercicio_matrices_DDR_14 {

    public static void main(String[] args) {

        int[][] carton = new int[3][9];

        // Rellenar numeros en el carton
        // Ordena cada columna del carton
        // Marca los huecos del cartón
        // Mostramos el cartón

    }

    public static int generaNumeroAleatorio(int minimo, int maximo) {
        return (int) (Math.random() * (maximo - minimo + 1) + (minimo));
    }

}

Si te interesa saber más como generar números aleatorios lo puedes ver en este tutorial:

Como generar números aleatorios con el método Math.random de Java

Rellenar números de nuestro cartón de bingo

Nuestro primer paso, será rellenar la matriz de números aleatorios, este seria el código para rellenar los números:


public static void rellenarNumerosCarton(int[][] carton) {

    // Declaramos las variables necesarias
    int numAleatorio;
    boolean repetido;

    // Recorre los números
    for (int j = 0; j < carton[0].length; j++) {
        for (int i = 0; i < carton.length; i++) {
            do {
                repetido = false;
                // Genera un número aleatorio
                // En la columna 0, el numero estará entre 1 y 9
                // Entre las columnas 1 y 7, el numero estará entre (10 * j) y ((10 * j) + 9)
                // En la columna 8, el numero estará entre 80 y 90
                switch (j) {
                    case 0:
                        numAleatorio = generaNumeroAleatorio(1, 9);
                        break;
                    case 8:
                        numAleatorio = generaNumeroAleatorio(80, 90);
                        break;
                    default:
                        numAleatorio = generaNumeroAleatorio(10 * j, (10 * j) + 9);
                        break;
                }

                // Se puede hacer con un bucle
                // Comprobamos si se repite el primero
                if (i == 1 && carton[0][j] == numAleatorio) {
                    repetido = true;
                    // Comprobamos si se repite el primero o el segungo
                } else if (i == 2 && (carton[0][j] == numAleatorio || carton[1][j] == numAleatorio)) {
                    repetido = true;
                }

            } while (repetido);

            // Añadimos el número
            carton[i][j] = numAleatorio;
        }
    }
}

Ordenar números por cada columna de nuestro cartón de bingo

El siguiente paso es ordenar cada una de las columnas. Este es el código:

public static void ordenarColumnasCarton(int[][] carton) {

    int[] numeros = new int[3];
    for (int j = 0; j < carton[0].length; j++) {

        // Obtengo los numeros de la columna x
        for (int i = 0; i < carton.length; i++) {
            numeros[i] = carton[i][j];
        }

        // Ordeno los numeros
        Arrays.sort(numeros);

        // Vuelvo a asignar los valores, ya ordenados
        for (int i = 0; i < numeros.length; i++) {
            carton[i][j] = numeros[i];
        }

    }
}

Poner los huecos en nuestro cartón

Esta parte es la más difícil de todas, ya que hay ciertas cosas que debemos tener en cuenta.

Lo primero que podemos pensar, es que si ponemos aleatoriamente los huecos en cada fila ya estaría, el problema de esto es que es muy probable es que se queden columnas sin huecos o que se repartan mal los huecos.

Mi consejo es generar grupos de huecos por cada columna, habiendo 6 grupos de 1 hueco vacío y 3 grupos de 2 huecos vacíos, revisa la foto del inicio y veras que se cumple. Por lo que cuando estemos en una columna que tenga dos huecos, recorreremos de nuevo la columna.

La estrategia es la siguiente, debemos «nivelar» el numero de huecos, es decir, si tenemos 3 huecos en la fila 0 y 1 y en la fila 2 hay 2 huecos, debemos darle prioridad a este ultimo, para que estén nivelados. En caso de empate, elegiremos un hueco al azar. Tendremos un array para indicar si una posición de la columna esta o no disponible para poner un hueco vacio.

Resumen

  1. Generar un array con 6 unos y 3 doses.
  2. Recorrer las columnas.
  3. Marcar todos los huecos disponibles.
  4. Comprobar si el numero de huecos vacíos son iguales.
  5. Sino son iguales, buscamos la fila con menores huecos e indicamos que el resto no están disponibles.
  6. Coloco el hueco vacío en una posición aleatoria disponible.
  7. Si es una columna en la que tengo que poner 2 huecos vacíos, compruebo el numero de posiciones ocupadas y si es menor que 2, restamos en uno el índice de la columna para que vuelva a hacer todo el proceso.
  8. Volvemos al paso 3.

Te muestro el código explicado paso a paso:

public static void marcarHuecosCarton(int[][] carton) {

    // generar un array de 9 posiciones con 6 unos y 3 doses
    int[] distribucion = {1, 1, 1, 1, 1, 1, 1, 1, 1};

    int posicionAleatoria;
    // Solo generamos 3 doses
    for (int i = 0; i < 3; i++) {
        do {
            posicionAleatoria = generaNumeroAleatorio(0, distribucion.length - 1);
        } while (distribucion[posicionAleatoria] == 2);
        // Colocamos un 2
        distribucion[posicionAleatoria] = 2;
    }

    // Recorrer array e ir llevando una cuenta del numero de huecos de cada fila, no puede superar 4
    int numHuecos[] = new int[3];
    boolean huecoDisponible[] = new boolean[3];
    int menor, filaAleatoria, posOcupadas;
    boolean iguales;

    for (int j = 0; j < carton[0].length; j++) {

        // Marco las posiciones como disponible
        Arrays.fill(huecoDisponible, true);

        // Compruebo si son iguales
        iguales = true;
        for (int i = 0; i < numHuecos.length - 1 && iguales; i++) {
            if (numHuecos[i] != numHuecos[i + 1]) {
                iguales = false;
            }
        }

        // Sino son iguales, debo descartar aquellos que distintos al menor hueco
        if (!iguales) {

            // Busco el menor hueco
            menor = numHuecos[0];
            for (int i = 1; i < numHuecos.length; i++) {
                if (numHuecos[i] < menor) {
                    menor = numHuecos[i];
                }
            }

            // Marco como no disponible los huecos diferentes al menor
            for (int i = 0; i < huecoDisponible.length; i++) {
                if (numHuecos[i] != menor) {
                    huecoDisponible[i] = false;
                }
            }

        }

        // Compruebo donde colocar los huecos
        do {
            // Genero una fila aleatoria
            filaAleatoria = generaNumeroAleatorio(0, carton.length - 1);
            // Salgo si el hueco esta disponible y no esta repetido
        } while (!huecoDisponible[filaAleatoria] || carton[filaAleatoria][j] == -1);

        // Coloco el hueco
        carton[filaAleatoria][j] = -1;

        // Incremento en 1 el numero de huecos de esa fila
        numHuecos[filaAleatoria]++;

        // Solo compruebo las posiciones ocupadas si tengo que poner dos huecos
        if (distribucion[j] == 2) {
            // Compruebo cuantos huecos hay en la columna
            posOcupadas = 0;
            for (int i = 0; i < carton.length; i++) {
                if (carton[i][j] == -1) {
                    posOcupadas++;
                }
            }

            // Si hay menos posiciones ocupadas que el de la distribucion de la columna, repetimos
            if (posOcupadas < distribucion[j]) {
                j--;
            }
        }
    }
}

Mostrar el cartón

Y ya por fin, el último paso que es mostrar nuestro cartón. Recuerda que los huecos los hemos marcado como -1, este es el código:

public static void mostrarCarton(int[][] carton) {

    // Recorremos el carton
    for (int i = 0; i < carton.length; i++) {
        for (int j = 0; j < carton[i].length; j++) {

            // Si es -1, ponemos un * o **, segun la columna
            if (carton[i][j] == -1) {
                // Si es la primera columna, pongo un * y sino pongo 2 *
                if (j == 0) {
                    System.out.print("* ");
                } else {
                    System.out.print("** ");
                }

            } else {
                // Muestro el valor tal cual
                System.out.print(carton[i][j] + " ");
            }
        }
        // Salto de linea
        System.out.println("");
    }
}

Resultado

El código final es el siguiente:

package ejercicio_matrices_ddr_14;

import java.util.Arrays;

public class Ejercicio_matrices_DDR_14 {

    public static void main(String[] args) {

        int[][] carton = new int[3][9];

        // Rellenar numeros en el carton
        rellenarNumerosCarton(carton);
        // Ordena cada columna del carton
        ordenarColumnasCarton(carton);
        // Marca los huecos del cartón
        marcarHuecosCarton(carton);
        // Mostramos el cartón
        mostrarCarton(carton);

    }

    public static void rellenarNumerosCarton(int[][] carton) {

        // Declaramos las variables necesarias
        int numAleatorio;
        boolean repetido;

        // Recorre los números
        for (int j = 0; j < carton[0].length; j++) {
            for (int i = 0; i < carton.length; i++) {
                do {
                    repetido = false;
                    // Genera un número aleatorio
                    // En la columna 0, el numero estará entre 1 y 9
                    // Entre las columnas 1 y 7, el numero estará entre (10 * j) y ((10 * j) + 9)
                    // En la columna 8, el numero estará entre 80 y 90
                    switch (j) {
                        case 0:
                            numAleatorio = generaNumeroAleatorio(1, 9);
                            break;
                        case 8:
                            numAleatorio = generaNumeroAleatorio(80, 90);
                            break;
                        default:
                            numAleatorio = generaNumeroAleatorio(10 * j, (10 * j) + 9);
                            break;
                    }

                    // Se puede hacer con un bucle
                    // Comprobamos si se repite el primero
                    if (i == 1 && carton[0][j] == numAleatorio) {
                        repetido = true;
                        // Comprobamos si se repite el primero o el segungo
                    } else if (i == 2 && (carton[0][j] == numAleatorio || carton[1][j] == numAleatorio)) {
                        repetido = true;
                    }

                } while (repetido);

                // Añadimos el número
                carton[i][j] = numAleatorio;
            }
        }
    }

    public static void ordenarColumnasCarton(int[][] carton) {

        int[] numeros = new int[3];
        for (int j = 0; j < carton[0].length; j++) {

            // Obtengo los numeros de la columna x
            for (int i = 0; i < carton.length; i++) {
                numeros[i] = carton[i][j];
            }

            // Ordeno los numeros
            Arrays.sort(numeros);

            // Vuelvo a asignar los valores, ya ordenados
            for (int i = 0; i < numeros.length; i++) {
                carton[i][j] = numeros[i];
            }

        }
    }

    public static void marcarHuecosCarton(int[][] carton) {

        // generar un array de 9 posiciones con 6 unos y 3 doses
        int[] distribucion = {1, 1, 1, 1, 1, 1, 1, 1, 1};

        int posicionAleatoria;
        // Solo generamos 3 doses
        for (int i = 0; i < 3; i++) {
            do {
                posicionAleatoria = generaNumeroAleatorio(0, distribucion.length - 1);
            } while (distribucion[posicionAleatoria] == 2);
            // Colocamos un 2
            distribucion[posicionAleatoria] = 2;
        }

        // Recorrer array e ir llevando una cuenta del numero de huecos de cada fila, no puede superar 4
        int numHuecos[] = new int[3];
        boolean huecoDisponible[] = new boolean[3];
        int menor, filaAleatoria, posOcupadas;
        boolean iguales;

        for (int j = 0; j < carton[0].length; j++) {

            // Marco las posiciones como disponible
            Arrays.fill(huecoDisponible, true);

            // Compruebo si son iguales
            iguales = true;
            for (int i = 0; i < numHuecos.length - 1 && iguales; i++) {
                if (numHuecos[i] != numHuecos[i + 1]) {
                    iguales = false;
                }
            }

            // Sino son iguales, debo descartar aquellos que distintos al menor hueco
            if (!iguales) {

                // Busco el menor hueco
                menor = numHuecos[0];
                for (int i = 1; i < numHuecos.length; i++) {
                    if (numHuecos[i] < menor) {
                        menor = numHuecos[i];
                    }
                }

                // Marco como no disponible los huecos diferentes al menor
                for (int i = 0; i < huecoDisponible.length; i++) {
                    if (numHuecos[i] != menor) {
                        huecoDisponible[i] = false;
                    }
                }

            }

            // Compruebo donde colocar los huecos
            do {
                // Genero una fila aleatoria
                filaAleatoria = generaNumeroAleatorio(0, carton.length - 1);
                // Salgo si el hueco esta disponible y no esta repetido
            } while (!huecoDisponible[filaAleatoria] || carton[filaAleatoria][j] == -1);

            // Coloco el hueco
            carton[filaAleatoria][j] = -1;

            // Incremento en 1 el numero de huecos de esa fila
            numHuecos[filaAleatoria]++;

            // Solo compruebo las posiciones ocupadas si tengo que poner dos huecos
            if (distribucion[j] == 2) {
                // Compruebo cuantos huecos hay en la columna
                posOcupadas = 0;
                for (int i = 0; i < carton.length; i++) {
                    if (carton[i][j] == -1) {
                        posOcupadas++;
                    }
                }

                // Si hay menos posiciones ocupadas que el de la distribucion de la columna, repetimos
                if (posOcupadas < distribucion[j]) {
                    j--;
                }
            }
        }
    }

    public static void mostrarCarton(int[][] carton) {

        // Recorremos el carton
        for (int i = 0; i < carton.length; i++) {
            for (int j = 0; j < carton[i].length; j++) {

                // Si es -1, ponemos un * o **, segun la columna
                if (carton[i][j] == -1) {
                    // Si es la primera columna, pongo un * y sino pongo 2 *
                    if (j == 0) {
                        System.out.print("* ");
                    } else {
                        System.out.print("** ");
                    }

                } else {
                    // Muestro el valor tal cual
                    System.out.print(carton[i][j] + " ");
                }
            }
            // Salto de linea
            System.out.println("");
        }
    }

    public static int generaNumeroAleatorio(int minimo, int maximo) {
        return (int) (Math.random() * (maximo - minimo + 1) + (minimo));
    }

}

Veamos algunos ejemplos:

carton bingo java 2 carton bingo java 3 carton bingo java 4

Espero que os sea de ayuda. Si tenéis dudas, preguntad. Estamos para ayudarte.

Compartir

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *