Autor Tema: Ejercicio cartas java  (Leído 3973 veces)

drate

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 24
    • Ver Perfil
Ejercicio cartas java
« en: 20 de Abril 2023, 16:10 »
Buenas tardes.
Cuelgo ejercicio de ordenación de cartas a falta de resolución de varias de sus clases. El cuál no tengo del todo claro.
Muchas gracias, un saludo.

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
Re: Ejercicio cartas java
« Respuesta #1 en: 24 de Abril 2023, 18:49 »
A ver, por el nombre de esta clase:
OrdPalNumInc
Supongo que se han de ordenar primero por el Palo, y luego por el Numero, de forma "incremental". Es decir, los palos en orden lexicográfico (parecido al orden alfabético) AAA,AAB,ABA,ABB,ABC, etc.... y los números por orden de valor numérico: 1(as), 2,3,4, ...., hasta el 12(rey)

Ordenar por palos no es problema, pues es comparar Strings, que Java ya sabe como debe hacerlo.
Pero por números, es más complicado, porque no son Integers. También son Strings:
Citar
numeros ={"AS", "DOS", "TRES", "CUATRO",
            "CINCO", "SEIS", "SIETE", "SOTA", "CABALLO", "REY"};
Así que hay que busca la forma de decirle al programa que el String AS es más pequeño que el String DOS.
Y que el String DOS es más pequeño que el String TRES, etc...
Bueno, eso lo veremos luego.

Volvamos  a la clase OrdPalNumInc
De momento, nos dan esto para completar:
Código: [Seleccionar]
public class OrdPalNumInc extends AlgoritmoOrdenacion{

@Override
    public void ordena(List listaCartas) {
        // Algoritmo de ordenación
    }

    public static int comparadorCarta(Carta c1, Carta c2) {
        // Comparador de cartas usado en el algoritmo de ordenación
        return 0;
    }

}

Primero habría que desarrollar el método comparadorCarta(), que es donde vamos escribir la lógica para que las cartas se comparen de forma que primero se ordenen según el palo, y si resulta que ambas cartas son del mismo palo, entonces se ordenan según el número.

La lógica sería:
* Si ambas cartas son exactamente iguales, se retorna 0.

* Si ambas cartas tienen el mismo palo, el orden depende de los números
   - Si los números fueran iguales, se retorna 0. En realidad esto ya está contemplado
    en el punto anterior.(Cartas exactamente iguales).
    - Si la carta c1 tiene un número inferior al de c2, se retorna -1.
    - Si la carta c2 tiene un número inferior al de c1, se retorna 1.

* Si las cartas tienen distinto palo, el número no influye. Hay que hacer una comparación lexicográfica de los nombres de los palos para decidir quién va primero al ordenar.
Las comparaciones lexicográficas son un poco complejas, pero la clase String ya sabe como hacerlas, así que se la pediremos a ella y retornaremos lo que ella diga.

Bien, esta lógica no es difícil. Solo está el problema al comparar los nombres de los números, ya que lo que necesitamos es su valor aritmético, pero el atributo "número" es un String. Sin embargo, podemos apoyarnos en el array de la clase Baraja donde están declarados los nombres de los números:
Código: [Seleccionar]
public static final String[] numeros ={"AS", "DOS", "TRES", "CUATRO",
            "CINCO", "SEIS", "SIETE", "SOTA", "CABALLO", "REY"};
Ahí están declarados en el orden correcto. Así que por ejemplo la posición que ocupa el String "AS" que es 0, nos sirve para saber que es menor que el String "DOS" el cuál ocupa la posición 1
Así que nos basta con obtener la posición que cada nombre de número ocupa en el array y hacer con ellos una comparación aritmética.

Quizás se entienda mejor leyendo el código:
Código: [Seleccionar]
    public static int comparadorCarta(Carta c1, Carta c2) {
        if (c1.equals(c2)) //Cartas son iguales
        return 0;
        else {
        if (c1.getPalo().equals(c2.getPalo())) { //Mismo palo, el orden dependerá de los números
        /*
        * El atributo "numero" de las Cartas es un String, no es un Integer.
        * Esto significa que no podemos comparar directamente esos atributos, porque en realidad
        * no son números, y necesitamos lograr un orden aritmético.
        *
        * Por suerte, la clase Baraja tiene un array público con los nombres de estos "números"
        * en el orden correcto.
        * Así que podemos usar la posición que ocupa cada "nombre de número" en el array para obtener
        * unos valores enteros con los que poder comparar de forma aritmética
        */
        int posiC1 = 0, posiC2 = 0;
        for (int i = 0; i < Baraja.numeros.length; i++) {
        if (c1.getNumero().equals(Baraja.numeros[i]))
        posiC1 = i;
        if (c2.getNumero().equals(Baraja.numeros[i]))
        posiC2 = i;
        }
        //Tenemos sus posiciones numéricas, podemos compararlas para decidir el orden.
        if (posiC1 == posiC2)
        return 0; //Número es igual
        else if (posiC1 < posiC2)
        return -1; //c1 es menor que c2
        else
        return 1; //c2 es menor que c1
        }
        else
        return c1.getPalo().compareTo(c2.getPalo());//Retornamos la comparación por defecto de Strings
        }

Ok, tenemos el método que dice como se han de compara las cartas.
Ahora hay que hacer el método ordena() que, valiéndose de estas reglas de comparación, ordene el List de Cartas.

Podemos aplicar el método de la burbuja para ordenar. Lo que haremos será comparar cartas según el algoritmo que hemos escrito antes.
Si el resultado de comparar resulta ser un valor mayor que 0, significa que la segunda carta es menor que la primera y por tanto han de intercambiar las posiciones.
Código: [Seleccionar]
@Override
    public void ordena(List listaCartas) {
        // Algoritmo de ordenación
for(int i = 0;i < listaCartas.size()-1;i++){
        for(int j = 0;j < listaCartas.size()-i-1;j++){
        int compara = comparadorCarta((Carta)listaCartas.get(j), (Carta)listaCartas.get(j+1));
        //Solo hay que intercambiar posiciones si la segunda carta es menor
        //es decir, si el valor de compara es positivo
        //System.out.println(compara);
        if (compara > 0) {
        //Intercambiamos posiciones
        Object aux = listaCartas.get(j+1);
        listaCartas.set(j+1, listaCartas.get(j));
        listaCartas.set(j, aux);
        }
        }
}
    }

Vale, pues en principio la clase OrdPalNumInc ya está completada. Habría que ponerla a prueba.
Para ello, primero hay que ir a la clase Mazo y completar un par de métodos.
Son muy sencillos, un setter para setear el algoritmo de ordenación que se quiere aplicar y el otro método es para ordenar que el algoritmo aplicado ordene las cartas:
Citar
public class Mazo {
   
       List cartas;
       private AlgoritmoOrdenacion algoritmo;

       public void setAlgoritmo(AlgoritmoOrdenacion algoritmo) {
           this.algoritmo = algoritmo;
       }

       public void ordena() {
          if (algoritmo == null)
             System.out.println(
"No se ha establecido ningún algoritmo de ordenación");
          else
             algoritmo.ordena(cartas);

       }

Y ahora sí, podemos poner a prueba el algortimo.
Primero podemos poner como comentario en la clase Main las líneas donde se aplicarían los algoritmos que aún no hemos escrito:
Citar
public class Main {

   public static void main(String[] args) {
      
      Baraja baraja = new Baraja();
        Mazo mazo = baraja.getMazo();
        System.out.println(mazo.toString());

        mazo.setAlgoritmo(new OrdPalNumInc());
        mazo.ordena();
        System.out.println(mazo.toString());

        /*
        mazo.setAlgoritmo(new OrdPalNumDec());
        mazo.ordena();
        System.out.println(mazo.toString());
       
        mazo.setAlgoritmo(new OrdNumIncPal());
        mazo.ordena();
        System.out.println(mazo.toString());*/

   }

}

Y ahora sí, al ejecutar el programa, veremos en pantalla las cartas del mazo original y a continuación las cartas ordenadas tal y como se esperaba.
Ordenadas primero por el palo, y luego por el número, en orden incremental.

Ahora faltaría completar la clase OrdPalNumDec, que es como la que hemos hecho pero invirtiendo el resultado de las comparaciones ya que el orden es decremental (de mayor a menor)

Y la clase OrdNumIncPal, que supongo que primero se han de ordenar por número, y luego por palo, en orden incremental.

En la clase AlgoritmoOrdenacion no hay que hacer nada de nada, ya que es una clase únicamente pensada para ser la "madre" de las otras tres clases de algoritmos.
De hecho, lo lógico habría sido declararla como una interface, en lugar de como una clase.
Pero bueno, este es el código que nos han dado y hay que respetarlo.  ;D

Otra cosa que no me gusta son todos esos List "sin tipar".
Código: [Seleccionar]
public void ordena(List listaCartas) {
}

Carajo, si ya sabemos el tipo de dato que van a contener estos List, pues pongámoslo para que todo quede bien parametrizado:
Citar
public void ordena(List<Carta> listaCartas) {
   }

Pero bueno, si no han querido ponerlo, pues nada...
Lo importante es que se entienda la lógica de estos ejercicios.

Intenta completar esas dos clases que faltan, y si te atascas o tienes dudas, avisa por aquí y te ayudamos a terminarlo.

Un saludo.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

drate

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 24
    • Ver Perfil
Re: Ejercicio cartas java
« Respuesta #2 en: 14 de Mayo 2023, 19:37 »
Buenas tardes.

Siguiendo los pasos que me indicabas he conseguido resolver los métodos de ordenación restantes salvo porque no sé cómo mostrar el método OrdNumIncPalo. Los otros dos métodos OrdPalNumInc y OrdPalNumDec funcionan correctamente. No tengo claro como modificar el toString() para que me muestre los tres métodos.
Si me puedes echar una mano. Muchas gracias, un saludo.


Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
Re: Ejercicio cartas java
« Respuesta #3 en: 14 de Mayo 2023, 21:06 »
El toString() pertenece a la clase Mazo y no hay que modificarlo.
Lo que hace es mostrar el mazo de cartas, sin importar si está ordenado o no.

Para completar la clase OrdPalNumDec, basta con copiar el código de OrdPalNumInc y, en el método ordena(), cambiamos el comparador de "mayor que" por el de "menor que".

Citar
   public void ordena(List listaCartas) {
      // Algoritmo de ordenación
      for(int i = 0;i < listaCartas.size()-1;i++){
         for(int j = 0;j < listaCartas.size()-i-1;j++){
            int compara = comparadorCarta((Carta)listaCartas.get(j), (Carta)listaCartas.get(j+1));
            if (compara < 0) {
               //Intercambiamos posiciones
               Object aux = listaCartas.get(j+1);
               listaCartas.set(j+1, listaCartas.get(j));
               listaCartas.set(j, aux);
            }
         }
      }
   }

De esta manera se invierte el orden, que es lo queremos, y si ahora modificamos el main para que también se muestre esta ordenación, veremos que el mazo se imprime de tres formas distintas sin tener que modificar el toString().
Citar
public class Main {

   public static void main(String[] args) {
      
      Baraja baraja = new Baraja();
        Mazo mazo = baraja.getMazo();
        System.out.println("Baraja original: ");
        System.out.println(mazo.toString());

        mazo.setAlgoritmo(new OrdPalNumInc());
        mazo.ordena();
        System.out.println("\nOrdenado por palo y numero incrementando: ");
        System.out.println(mazo.toString());

       
        mazo.setAlgoritmo(new OrdPalNumDec());
        mazo.ordena();
        System.out.println("\nOrdenado por palo y numero decrementando: ");
        System.out.println(mazo.toString());
       
        /*
        mazo.setAlgoritmo(new OrdNumIncPal());
        mazo.ordena();
        System.out.println(mazo.toString());*/

   }

}


Falta completar OrdNumIncPal, en este caso hay que cambiar más el código.
En los dos anteriores se ordenaba primero por palo, y luego por número.

En esta caso, se ordena primero por número(valor de carta) y luego los palos.
Es decir, primero se mostraran los ases de cada palo, luego el 2 de cada palo, el 3, etc...

Entonces, para esta clase, el método ordena() si es idéntico al de la clase OrdPalNumInc, porque se encarga de ordenar de manera incremental, sea lo que sea lo que determine el método comparadorCarta().

Así que es el método comparadorCarta() el que ha de cambiar el código, porque ahora hay que dar preferencia a ordenar por el número de carta. Y si los número de las cartas que se comparan son iguales, entonces se ordenará por palo.
Código: [Seleccionar]
    }

    public static int comparadorCarta(Carta c1, Carta c2) {
    if (c1.equals(c2)) //Cartas son iguales
        return 0;
    else {
    if (c1.getNumero() == c2.getNumero()) //Mismo número, se ordenará por palo
    return c1.getPalo().compareTo(c2.getPalo());
    else {//Distinto número de carta
    //Averiguamos el valor de estas cartas según posición en el array
    int posiC1 = 0, posiC2 = 0;
        for (int i = 0; i < Baraja.numeros.length; i++) {
        if (c1.getNumero().equals(Baraja.numeros[i]))
        posiC1 = i;
        if (c2.getNumero().equals(Baraja.numeros[i]))
        posiC2 = i;
        }
        //Tenemos sus posiciones numéricas, podemos compararlas para decidir el orden.
        if (posiC1 == posiC2)
        return 0; //Número es igual
        else if (posiC1 < posiC2)
        return -1; //c1 es menor que c2
        else
        return 1; //c2 es menor que c1
    }
   
    }
    }

Y ahora sí, en el Main activamos todo el código para mostrar la baraja sin ordenar y ordenada de tres formas distintas.
Es decir, se muestran 4 configuraciones distintas de la baraja, y repito, todas sin necesidad de alterar el método toString().


Solo han de cambiar los métodos ordena()(decide si el orden es incremental o decremental) y comparadorCarta()(decide si tiene preferencia ordenar por valor u ordenar por palo) de las tres clases que heredan de AlgoritmoOrdenacion

Espero se hayan aclarado tus dudas, si no, no dudes en repreguntar.

Saludos.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".