Saltar al contenido principal

Práctica 7 - Diseño de clases

Esta práctica tiene como objetivo continuar familiarizándonos con los conceptos de POO que ya se aplicaron en la práctica anterior, esto es, el diseño de clases sencillas, sus componentes fundamentales (campos o atributos, constructores y métodos), el desarrollo de éstos y la creación de nuevas clases utilizando otras para resolver problemas más complejos.

En las soluciones desarrolladas se tendrá en cuenta lo siguiente:

Ejercicio 1

El objetivo de este ejercicio es diseñar una calculadora de fracciones con las operaciones básicas de suma, resta, multiplicación y división de fracciones. Para ello, se diseñarán las siguientes clases:

  • Fraccion, para representar fracciones de la forma a / b con a y b números enteros
  • Calculadora, para representar la máquina que realiza los cálculos sobre las fracciones
  • Interfaz, para realizar la comunicación entre el usuario y nuestra calculadora

La clase Fraccion contiene los campos que permiten representar una fracción mediante su numerador y denominador y los constructores por defecto, por parámetros y copia. Las fracciones se almacenarán en su forma normalizada (es decir, el signo de la fracción viene dado exclusivamente por el numerador, mientras que el denominador es un número estrictamente mayor que cero) e irreducible. Para ello, se dispondrá de sendos métodos para normalizar y simplificar fracciones, que se utilizarán siempre que exista la posibilidad de que el resultado de una de las operaciones de lugar a una fracción denormalizada o reducible.

Para simplificar una fracción, se dividirán numerador y denominador por el Máximo Común Divisor (MCD) de ambos, donde el MCD se calculará de forma recursiva mediante el algoritmo de Euclides, que, escrito en pseudocódigo tiene la siguiente forma:

Algoritmo mcd( a, b )
      Si b = 0
            mcd(a,b) = a
      en caso contrario
            mcd(a,b) = mcd(b, a % b)

Además, la clase Fracción deberá contener métodos para calcular la suma, resta, multiplicación y división de fracciones que realizarán las operaciones entre el objeto propietario y otra fracción pasada como parámetro. También será necesario implementar un método toString(), que construirá una representación de la fracción de la forma a / b.

flowchart LR
  INTERFAZ["Interfaz"] -->|"utiliza"| CALCULADORA["Calculadora"]
  CALCULADORA -->|"fracción 1"| F1["Fraccion"]
  CALCULADORA -->|"fracción 2"| F2["Fraccion"]

  classDef clase fill:#e6f5f3,stroke:#0f766e,color:#16324f,stroke-width:1.5px;
  class INTERFAZ,CALCULADORA,F1,F2 clase;

La clase Calculadora contiene dos campos de tipo fracción, que representan las fracciones entre las que se va a realizar la operación, y un campo de tipo carácter que representa la operación a realizar entre las fracciones (+, -, *, /). También debe contener los constructores necesarios.

La clase Interfaz se encargará de realizar la interacción con el usuario, que consistirá en pedirle dos fracciones y la operación que se desea realizar y le mostrará el resultado de dicha operación. La interfaz repetirá la petición y muestra de resultados mientras el usuario desee continuar con la ejecución del programa.

Ejemplo de ejecución:

Introduce el numerador:
> 5
Introduce el denominador:
> 8
Introduce el operador:
> *

Introduce el numerador:
> 2
Introduce el denominador:
> 4

El resultado de (5/8)*(2/4) es 5/16.
¿Desea realizar otra operación (S/N)?
> N

Ejercicio 2

El objetivo es implementar el juego de los “Chinos” entre el usuario y el computador. Es decir, habrá dos jugadores, de forma que uno será el usuario y el otro el computador. En cada jugada los jugadores sacarán un número de monedas entre 0 y 3 y dirán una cantidad entre 0 y 6, ganando el jugador que acierte la cantidad de monedas totales de la jugada. La ejecución del programa desarrollará una partida a 5 victorias; es decir, ganará el primer jugador que obtenga ese número de victorias.

Juego de los “Chinos”

Los campos de un jugador permitirán almacenar el nombre, la puntuación (el número de jugadas que ha ganado) y la jugada en cada turno (que son dos valores, el número de monedas que saca y el número de monedas que dice). El nombre del usuario se preguntará al inicio del juego, mientras que el del ordenador será simplemente “Ordenador”.

El constructor de un jugador establecerá los valores adecuados que permitan iniciar la partida.

Los métodos de un jugador permitirán:

  • Mostrar su jugada elegida
  • Mostrar la puntuación
  • Saber si su jugada gana a la de otro jugador (sumando los números de monedas sacadas y si coincide con la elección efectuada)
  • Incrementar su puntuación
  • Elegir su jugada. Observa que la jugada del usuario y la del ordenador han de obtenerse de forma diferente. Al usuario hay que preguntársela mientras que para el ordenador hay que calcularla aleatoriamente.

Adicionalmente, hay que definir una última clase que permita desarrollar una partida entre un usuario y un ordenador. Los atributos permitirán representar a los dos jugadores. El constructor tendrá que crear los jugadores para poder iniciar la partida. Los métodos permitirán:

  • Saber si la partida ha terminado (es decir, alguno de los jugadores ha alcanzado el número de victorias objetivo)
  • Actualizar la puntuación de los jugadores
  • Mostrar el marcador de la partida
  • Desarrollar una partida conforme al siguiente esquema: Mientras no acaba la partida, se repite que el usuario hace su jugada, después lo hace el computador, se muestran las jugadas elegidas por ambos jugadores, se actualizan sus puntuaciones y se muestra el marcador actual. Al finalizar se mostrará un mensaje indicando quién ha sido el ganador.

Ejemplo de ejecución:

Introduce un nombre de usuario:
> Salvador

Introduce tu número de monedas:
> 2
Introduce tu predicción:
> 6

El ordenador ha sacado 2 monedas y ha predicho que se sacarían 4 en total.
Ha ganado la jugada el ordenador.
Puntos del ordenador: 1. Puntos del usuario: 0

...

El ordenador ha ganado tras alcanzar 5 puntos.