array bidimensiona con numeros aleatorios sin repetir

Iniciado por Baaz, 9 Abril 2015, 00:07 AM

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

Baaz

buenas, tengo un problema y queria saber si alguno me podria ayudar la cuestion es que tengo un trabajo del instituto el cual consiste en hacer un bingo tengo que crear un array de 3x9 y rellenarlo con numeros aleatorios hasta ahi todo bien:

public static void main(String[] args) {
        Random rnd = new Random();
           
        int [][] carton=new int [3][9];
       
            for (int i = 0; i < carton.length; i++) {
                for (int j = 0; j < carton.length; j++) {
                    carton[j]=rnd.nextInt(90)+1;
                }
            }


el problema es que tengo que rellenarla sin que los numeros aleatorios se repitan y no se como hacer para que no se repitan supongo que añadiendo un if y otra variable pero no se plantearlo bien agradeceria una respuesta un saludo.

Usuario Invitado

1) Por favor, antes de publicar algo, léanse un toque las reglas. Si vas a colocar código Java, utiliza las etiquetas GeSHi.

Primero, tu código está mal. La forma de llenar una matríz es la siguiente:

Código (java) [Seleccionar]

for(int row=0; row<numbers.length; row++) {
   for(int col=0; col<numbers[row].length; col++) {
       numbers[row][col] = generateRandomNumber();
   }
}


El método generateRandomNumber() que usaremos para generar los números de las cartillas es un método recursivo:

Código (java) [Seleccionar]
private Integer generateRandomNumber() {
   Integer number = 1 + RANDOM_GEN.nextInt(90);
   if(isRepeated(number)) {
       number = generateRandomNumber();
   }
   return number;
}


Que llama al método isRepeated que evalúa si un número ya existe dentro de la matríz:

Código (java) [Seleccionar]
private Boolean isRepeated(final Integer number) {
   Boolean isRepeated = false;
   for(Integer[] row : numbers) {
       for(Integer col : row) {
           if(col == number)
               isRepeated = true;
        }
    }
    return isRepeated;
}


Luego, puedes obtener la cartilla:

Código (java) [Seleccionar]
public Integer[][] getCard() throws IllegalAccessException {
   if(numbers[0][0] == null) {
       throw new IllegalAccessException("Primero llene la cartilla");
   }
   return numbers;
}


Y, el método main sería así:

Código (java) [Seleccionar]
public static void main(String[] args) {
   Bingo bingo = new Bingo().generateNumbers();
   try {
       for(Integer[] row : bingo.getCard()) {
           for(Integer col : row) {
               System.out.println(col);
            }
        }
    } catch(IllegalAccessException e) {
        javax.swing.JOptionPane.showMessageDialog(null,e.getMessage());
    }
}


Nota que en el método getCard() lanzamos una IllegalAccessException si tratamos de obtener la cartilla y ésta está vacía. Ésta excepción la capturamos en el método main y mostramos el mensaje en un JOptionPane.

El código, quedaría así:

Código (java) [Seleccionar]

import java.util.Random;

public class Bingo {
   private Integer[][] numbers = new Integer[9][3];
   private final Random RANDOM_GEN = new Random(System.nanoTime());
   
   public Integer[][] getCard() throws IllegalAccessException {
       if(numbers[0][0] == null) {
           throw new IllegalAccessException("Primero llene la cartilla");
       }
       return numbers;
   }
   public Bingo generateNumbers() {
       for(int row=0; row<numbers.length; row++) {
           for(int col=0; col<numbers[row].length; col++) {
               numbers[row][col] = generateRandomNumber();
           }
       }
       return this;
   }
   private Integer generateRandomNumber() {
       Integer number = 1 + RANDOM_GEN.nextInt(90);
       if(isRepeated(number)) {
           number = generateRandomNumber();
       }
       return number;
   }
   private Boolean isRepeated(final Integer number) {
       Boolean isRepeated = false;
       for(Integer[] row : numbers) {
           for(Integer col : row) {
               if(col == number)
                   isRepeated = true;
           }
       }
       return isRepeated;
   }
   public static void main(String[] args) {
       Bingo bingo = new Bingo().generateNumbers();
       try {
           for(Integer[] row : bingo.getCard()) {
               for(Integer col : row) {
                   System.out.println(col);
               }
           }
       } catch(IllegalAccessException e) {
           javax.swing.JOptionPane.showMessageDialog(null,e.getMessage());
       }
   }
}



Saludos.
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein

DarK_FirefoX

#2
Excelente respuesta! Pero voy a meterme un poco y preguntar algo.

¿Que hace exáctamente el método isRepeated()?

(Entiendo la funcionalidad, pero no veo que es lo que hace -> ¿Recorre el array bidimensional completo buscando por el numero aleatorio ya este insertado?

El problema es que no me he familiarizado completamente con la sintaxis de JAVA.




Usuario Invitado

#3
Hola DarK_FirefoX,

Sip, es exactamente eso. Es lo mismo que hacer:

Código (java) [Seleccionar]
for(int row=0; row<numbers.length; row++) {
   for(int col=0; col<numbers[row].length; col++) {
       if(numbers[row][col] == number)
           isRepeated = true;
   }
}


Incluso se puede otpimizar un poco, para que rompa el loop principal al detectar un número repetido:

Código (java) [Seleccionar]
private Boolean isRepeated(final Integer number) {
   Boolean isRepeated = false;
   mainloop:
   for(Integer[] row : numbers) {
       for(Integer col : row) {
           if(col == number) {
               isRepeated = true;
               break mainloop;
           }
       }
   }
   return isRepeated;
}



Un saludo.
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein

Baaz

muchas gracias gus garsaky la verdad que muchas cosas aun ni las había visto pero me gusta porque así aprendo mas recién es mi primer año de DAM (desarrollo de aplicación multiplataforma) y por eso me cuesta mucho pero muchas gracias y perdón por no haber puesto el código donde tenia que ir es que soy nuevo en el foro jeje un saludo!

Usuario Invitado

#5
No te preocupes, no pasa nada ^^. Un saludo y dale duro a la carrera.
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein

DarK_FirefoX

Cita de: Gus Garsaky en  9 Abril 2015, 02:20 AM
Hola DarK_FirefoX,

Sip, es exactamente eso. Es lo mismo que hacer:

Código (java) [Seleccionar]
for(int row=0; row<numbers.length; row++) {
   for(int col=0; col<numbers[row].length; col++) {
       if(numbers[row][col] == number)
           isRepeated = true;
   }
}


Incluso se puede otpimizar un poco, para que rompa el loop principal al detectar un número repetido:

Código (java) [Seleccionar]
private Boolean isRepeated(final Integer number) {
   Boolean isRepeated = false;
   mainloop:
   for(Integer[] row : numbers) {
       for(Integer col : row) {
           if(col == number) {
               isRepeated = true;
               break mainloop;
           }
       }
   }
   return isRepeated;
}



Un saludo.

Gracias, entendido. Eso era lo que pensaba.

Pero pensando, puedo sugerir hacer esa revisión (de si está repetido) dinamicamente, aunque en este caso no será perceptible (por el pequeño tamaño del array original), pero creando un array de bool con el tamaño definido por la cantidad de números posibles a poner en el array bidimensional, y una vez que se genere el número se indexa y se cambia este array a true, luego la comprobación sería solo indexar y comprobar el estado del array en esa posición. (tendría una complejidad temporal de O(1)), no se si me explico.

Salu2s

Usuario Invitado

#7
Ya veo, algo como el algoritmo Bucket Sort. Sip, en arrays grandes puede llegar a ser más eficiente, aunque en la VM actual no lo creo. Por ejemplo, for y while tardan 234 milisegundos en recorrer un array de 15 millones, osea .234 segundos, Iterator 340. Puedes ver el benchmark aquí.

Como puedes observar, es poquísimo tiempo para tan exorbitante muestra.


Saludos.
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein

DarK_FirefoX

Cita de: Gus Garsaky en  9 Abril 2015, 13:49 PM
Ya veo, algo como el algoritmo Bucket Sort. Sip, en arrays grandes puede llegar a ser más eficiente, aunque en la VM actual no lo creo. Por ejemplo, for y while tardan 234 milisegundos en recorrer un array de 15 millones, osea .234 segundos, Iterator 340. Puedes ver el benchmark aquí.

Como puedes observar, es poquísimo tiempo para tan exorbitante muestra.

Saludos.

Exacto, por eso dije que era un sugerencia a tener en cuenta para ese método, pues en este caso no es perceptible pues la entrada de datos es pequeña! Solo algo a tener en cuenta si se le quiere dar otro uso!

Salu2s