Generar 10 cartas de la baraja española sin repeticiones

publicado por: Anonymous

Tengo un ejercicio en el que debo generar 10 cartas de la baraja española de forma aleatoria sin que se repita la misma carta. No puedo generar directamente las 48 cartas y luego sacar 10 por requisitos del problema.

Entonces, tengo que conseguir de forma DIRECTA generar las 10 cartas sin que se repita. La única manera en la que se me ocurre resolver esto es comparar la nueva carta generada con las anteriores que ya se han metido (Esto es el segundo for) y si hay alguna igual quitarle a la i-- un valor y que pruebe otra vez, y si no está repetida pues que meta en el arrayList la nueva carta generada.

Como veis, el código parece estar correctamente, pero cuando lo ejecutas varias veces siempre hay alguna carta que se repite, es decir, el mismo numero y palo y esto no tiene que ser así.

import java.util.*;
public class Ejercicio8Baraja {
    public static void main(String[] args) {
        //Objetos
        Scanner teclado = new Scanner(System.in);
        ArrayList<Baraja> cartas = new ArrayList<Baraja>(10);
        //variables
        int palo = 0, numero = 0, n = 0;
        String palorandom = "";

        numero = (int) Math.floor(Math.random() * (12 - 1 + 1) + 1); // Valor entre M y N, ambos incluidos.
        //System.out.print(numero);
        palo = (int) Math.floor(Math.random() * (4 - 1 + 1) + 1); // Valor entre M y N, ambos incluidos.
        if (palo == 1) {
            palorandom = "Oros";
        } else if (palo == 2) {
            palorandom = "Bastos";
        } else if (palo == 3) {
            palorandom = "Espadas";
        } else {
            palorandom = "Copas";
        }
        cartas.add(new Baraja(numero, palorandom));
        for (int i = 0; i < 10; i++) {
            System.out.println("Principio primer for");
            numero = (int) Math.floor(Math.random() * (12 - 1 + 1) + 1);
            palo = (int) Math.floor(Math.random() * (4 - 1 + 1) + 1);
            if (palo == 1) {
                palorandom = "Oros";
            } else if (palo == 2) {
                palorandom = "Bastos";
            } else if (palo == 3) {
                palorandom = "Espadas";
            } else {
                palorandom = "Copas";
            }
            for (int j = 0; j < cartas.size(); j++) {
                n += 2;
                //System.out.println("Principio segundo for"+n);
                if (numero == cartas.get(j).getNumero() && palorandom.equals(cartas.get(j).getPalo())) {
                    i--;
                    break;
                } else {
                    cartas.add(new Baraja(numero, palorandom));
                    break;
                }
                //System.out.println("Final segundo for");
            }


        } //fin primer for

        //mostrar la baraja española
        for (Baraja b: cartas) {
            System.out.print(b.toString());
        }

    } //main
} //clase

solución

Podrías implementar el siguiente código. Asumiendo que tu clase Baraja tiene 2 propiedades llamadas número y palo, (int y String respectivamente). Independientemente de cómo implementes tu clase, la idea es escoger la cantidad de barajas aleatoriamente de acuerdo a lo que indique el usuario.

Para ello, debemos generar un número aleatorio entre 1 y 12, ya que la baraja española contiene 4 palos con números entre 1 y 12. También debemos escoger aleatoriamente el palo (Bastos, Espadas, Copas, Oros).

Para lograrlo voy a tomar una clase baraja muy simple, y los valores (String) de los palos los almacenaré fuera de la clase en un Array. Lo que haré será generar números aleatorios entre 0 y 3, que indicarán el valor del índice del Array, así seleccionaré un palo al azar.

El código quedaría así:

import java.util.*;

class Baraja {
  private String palo;
  private int numero;

  public static void Baraja() {

  }

  public Baraja(int _numero, String _palo) {
    this.numero = _numero;
    this.palo = _palo;
  }

  public String getPalo() {
    return this.palo;
  }

  public int getNumero() {
    return this.numero;
  }

  public void setPalo(String _palo) {
    this.palo = _palo;
  }

  public void setNumero(int _numero) {
    this.numero = _numero;
  }
}

public class baraja_aleatoria{

  public static void main(String[] args) {
    String Palo[] = {"Oros","Bastos","Espadas","Copas"}; //Array con el valor de los palos de la baraja
    Scanner sc = new Scanner(System.in);
    System.out.println("Diga el número de cartas que desea:");
    int cantidad = sc.nextInt();
    ArrayList<Baraja> barajas = new ArrayList<Baraja>();
    while (cantidad > 0) {
      int numero = ((int) Math.round(Math.random() * 11)) + 1; // produce números entre 1 y 12 aleatoriamente
      int p = (int) Math.round(Math.random() * 3); // produce números entre 0 y 3 aleatoriamente
      boolean existe = false;
      Baraja baraja = new Baraja(numero, Palo[p]); // Creamos la baraja
      for(int i = 0; i < barajas.size(); i++) {
        if(numero == barajas.get(i).getNumero() && Palo[p] == barajas.get(i).getPalo()) { // comparamos la baraja con las ya almacenadas
          existe = true;
          break; // Si la baraja ya fue seleccionada no se sigue verificando
        }
      }
      if(!existe) {
        barajas.add(baraja); // solo añadimos la baraja si es diferente a todas las ya escogidas
        cantidad--;
      }
    }
  barajas.forEach(baraja -> System.out.println("Baraja: " + baraja.getNumero() + " de " + baraja.getPalo()));
  }
}

Esto produce la siguiente salida:

Ejemplo de salida de código

Como puedes apreciar en el código, he cambiado tus 2 bucle for anidados por un bucle for anidado dentro de un bucle while. La idea que tienes de alterar el índice de tu bucle externo es mejor realizarla usando un bucle while.

En cada iteración (cantidad > 0) del bucle while se genera una nueva baraja. Luego se realiza una comparación de dicha baraja con las que ya están almacenadas en nuestro ArrayList. Si la baraja no existe en nuestro ArrayList entonces se puede añadir y se reduce el valor de cantidad, de lo contrario se vuelve a jecutar otra corrida para obtener una nueva baraja.

De esta forma puedes obtener la cantidad de barajas aleatoriamente que requieras sin repetición.

Si ejecutas el programa pidiendo 49 barajas, el mismo se quedará en un bucle infinito, debido a que la última baraja que genere siempre estará repetida y el valor cantidad siempre será mayor que cero.

Espero que esta respuesta aclare tu duda.

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *