Estás escribiendo código directamente en el cuerpo de la clase
Sala.
Esto no es correcto.
Sala es una clase, una entidad, que va a representar algo y que tiene determinadas funcionalidades.
Estas funcionalidades, por ejemplo vender una entrada/boleto de cine, solo ha de ejecutarse cuando se lo pidamos. Por lo tanto, esta parte del código ha de estar escrita en un método, para que solo se ejecute cuando invoquemos a este metodo.
Es decir, esta clase ha de tener unos atributos, un constructor y los métodos que pueda necesitar para cumplir con su cometido
Pensemos en los atributos. ¿Que propiedades tiene una sala? Mejor dicho, ¿que propiedades de una sala son las que nos interesan?
Porque una sala tiene unas dimensiones, tiene cierta cantidad de puertas de emergencia, tiene una moqueta de un determinado color.... pero todo esto no nos interesa.
También tiene una película en proyección. Esto sí nos interesa, queremos un atributo que guarde el
nombre de la película que está proyectando. Este atríbuto es el que permite diferenciar una sala de otra. Porque nuestro ejercicio final va a trabajar de hecho con 3 salas distintas al mismo tiempo. Y cada una tendrá sus clientes, sus ventas y su propia recaudación.
Tiene una
cantidad determinada de asientos. 20 asientos para ser más exactos.
Esto también nos interesa. Otro atributo más.
Luego además, la sala tiene
clientes. Esto también nos interesa contarlos, para poder hacer una estadística de clientes. Hay tres tipos de clientes distintos, así que como atributos usaremos tres contadores distintos, uno para cada tipo de cliente.
Por último, la sala tiene una
recaudación que va aumentando con cada entrada/boleto que se vende. Esto también nos interesa contabilizarlo.
Así pues, estos podrían ser los atributos de nuestra clase
Sala private String nombrePelicula;
private int asientosLibres = 20;
private int contJubilados = 0;
private int contAdultos = 0;
private int contMenores = 0;
private double recaudacion = 0;
El contador de asientos lo he llamado asientosLibres y lo he iniciado en 20.
También podríamos haberlo llamado asientosOcupados e iniciarlo con valor 0.
Ambas opciones serían válidas, es cuestión de gustos.
Ya tenemos atributos. Pensemos en un constructor.
No hay mucho que pensar la verdad. El valor de los atributos siempre van a ser los mismos al crear un objeto
Sala. Da igual si creamos 500 objetos
Sala, todos empezarán con el contador de asientos en 20 y el resto de contadores en 0.
El único atributo que será distinto para cada objeto
Sala, sería el nombre de la película que va a proyectar. Ergo, este es el único valor que queremos recibir mediante el constructor.
public Sala(String nombre) {
nombrePelicula = nombre;
}
De este modo, cuando instanciemos objetos
Sala desde otra clase con metodo main, le indicaremos a cada una el nombre de la pelicula que proyecta.
Y ahora viene lo "complicado". Los métodos para esta clase.
Se podría empezar poniendo los típicos
setters y
getters. Pero lo cierto es que en principio no los vamos a necesitar ya que la mayoría de los atributos se van a gestionar dentro de la clase, no van a ser solicitados(get) y mucho menos modificados(set) desde otras clases. Así que podemos ahorrarlos.
Como mucho, un get para el nombre de la película. Así cada objeto
Sala podrá indicar que película está proyectando:
public String getNombrePelicula() {
return nombrePelicula;
}
Pasemos a los métodos importantes. Necesitaremos uno que lleve a cabo la gestión de la venta de entradas.
Y otro que nos muestre estadísticas de venta de la sala.
Centrémonos, únicamente en el de la venta.
El código que habías escrito pinta bastante bien. Uno de los errores que te da es cuando preguntas por el valor de la variable metodoPago casi al final.
Esta variable solo la declaras si hay suficientes asientos libres para cubrir la demanda del cliente.
Si no hay asientos,
no declaro variable metodoPago;
si hay asientos
sí la declaro;Esto es correcto.
Pero luego intentas acceder a esta variable desde un punto del programa que da por hecho que la variable está declarada independientemente de si hay asientos o no.
Es decir, "te has salido del alcance de esta variable"
Te marco en verde el "alcance" (scope) de la variable metodoPago.
Y en rojo la parte donde intentas acceder a ella, estando ya fuera de su alcance.
if (asientosLibres == 0) {
System.out.println("NO HAY ASIENTOS LIBRES");
} else {
System.out.println("Indique tipo cliente: J - Jubilado o adulto mayor (mayor a 55) / A - Adulto / M - Menor (menores de 12)");
String tipoCliente = cine.nextLine();
System.out.println("Indique cuantas entradas desea: ");
int cantidadEntradas = cine.nextInt();
if (cantidadEntradas > asientosLibres) {
System.out.println("NO HAY ASIENTOS LIBRES");
} else {
System.out.println("Elija metodo de pago: E - Efectivo / T - Tarjeta");
String metodoPago = cine.nextLine();
if (tipoCliente.equalsIgnoreCase("J")) {
precio = 15;
}
if (tipoCliente.equalsIgnoreCase("A")) {
precio = 30;
}
if (tipoCliente.equalsIgnoreCase("M")) {
precio = 10;
}
}
}
if (metodoPago.equalsIgnoreCase("T")) {
precio = (int) (precio + precio*0.18);
System.out.println("VENTA REALIZADA. PRECIO FINAL: " + precio);
}
cont ++;
if (cont <= asientosLibres) {
cont = asientosLibres;
System.out.println("QUEDAN " + (int) (asientosLibres - cont) + "asientos.");
}
La variable metodoPago solo "existe" en la porción marcada en verde, ese es el límite de su alcance.
Esta porción verde, solo se ejecutaría si se cumple una determinada condición (que haya suficientes asientos libres)
Por lo tanto es posible que no se ejecute.
Si no se ejecuta, no se declara la variable metodoPago. Y si no se declara, no puedes preguntar por ella.
Y esto es lo que estás haciendo en la porción marcada en rojo, estás preguntando por una variable que
posiblemente NO se ha declarado.
Por eso el compilador Java muestra un
warning. Si permitiese ejecutarse el código tal y como está escrito, cuando ocurriese que alguien pide más asientos de los que quedan libres, se produciría un error fatal porque el programa preguntaría por una varaible que no se ha llegado a declarar.
Para corregir esto, tienes dos opciones.
Una, declarar la variable al principio del método, para asegurarte de que va a existir siempre, ante cualquier posibilidad.
Esto aumentaría el alcance de la variable a todo el método completo. Marco en verde todo su alcance, vamos, el método al completo
String metodoPago;
if (asientosLibres == 0) {
System.out.println("NO HAY ASIENTOS LIBRES");
} else {
System.out.println("Indique tipo cliente: J - Jubilado o adulto mayor (mayor a 55) / A - Adulto / M - Menor (menores de 12)");
String tipoCliente = cine.nextLine();
System.out.println("Indique cuantas entradas desea: ");
int cantidadEntradas = cine.nextInt();
if (cantidadEntradas > asientosLibres) {
System.out.println("NO HAY ASIENTOS LIBRES");
} else {
System.out.println("Elija metodo de pago: E - Efectivo / T - Tarjeta");
metodoPago = cine.nextLine();
if (tipoCliente.equalsIgnoreCase("J")) {
precio = 15;
}
if (tipoCliente.equalsIgnoreCase("A")) {
precio = 30;
}
if (tipoCliente.equalsIgnoreCase("M")) {
precio = 10;
}
}
}
if (metodoPago.equalsIgnoreCase("T")) {
precio = (int) (precio + precio*0.18);
System.out.println("VENTA REALIZADA. PRECIO FINAL: " + precio);
}
cont ++;
if (cont <= asientosLibres) {
cont = asientosLibres;
System.out.println("QUEDAN " + (int) (asientosLibres - cont) + "asientos.");
}
}
Segunda opcion.
Más correcta a mi entender. Introducir la porción de código que antes habíamos marcado en rojo, dentro de la parte que solo se ejecuta si hay suficientes asientos.
Es más correcta porque lo cierto es que, si no hay suficientes asientes, no haremos ninguna venta. Y si no hacemos ninguna venta, no necesitamos preocuparnos del método de pago, ya que no ha habido ningún pago en realidad.
if (asientosLibres == 0) {
System.out.println("NO HAY ASIENTOS LIBRES");
} else {
System.out.println("Indique tipo cliente: J - Jubilado o adulto mayor (mayor a 55) / A - Adulto / M - Menor (menores de 12)");
String tipoCliente = cine.nextLine();
System.out.println("Indique cuantas entradas desea: ");
int cantidadEntradas = cine.nextInt();
if (cantidadEntradas > asientosLibres) {
System.out.println("NO HAY ASIENTOS LIBRES");
} else {
System.out.println("Elija metodo de pago: E - Efectivo / T - Tarjeta");
String metodoPago = cine.nextLine();
if (tipoCliente.equalsIgnoreCase("J")) {
precio = 15;
}
if (tipoCliente.equalsIgnoreCase("A")) {
precio = 30;
}
if (tipoCliente.equalsIgnoreCase("M")) {
precio = 10;
}
if (metodoPago.equalsIgnoreCase("T")) {
precio = (int) (precio + precio*0.18);
System.out.println("VENTA REALIZADA. PRECIO FINAL: " + precio);
}
}
Otra cosa importante que hay corregir. La parte final donde contabilizamos los asientos que quedan libres (o que están ocupados).
Esto que has puesto:
cont++;
if (cont <= asientosLibres) {
cont = asientosLibres;
System.out.println("QUEDAN " + (int) (asientosLibres - cont) + "asientos.");
}
No tiene mucho sentido. Parece que cuentas los asientos de uno en uno. Cada oper acion de venta, un asiento (cont++);
Pero no es así, porque en una operación de venta el usuario puede pedir 5 asientos, 10 asientos, incluso los 20 asientos de toda la sala, para el solito.
No necesitas ninguna varaible cont, porque ya sabemos gracias a la variable cantidadEntradas, cuantos asientos tenemos que restar del atributo
asientosLibres.Y esto, además, solo ha de hacerse en el caso de que se haya completado la venta.
Por lo tanto, también iría en la misma parte de código que hemos modificado antes.
El metodo quedaría así, ahora ya sí, libre de
errores de compilación.
Y subrayo lo de compilación, porque el método aún tiene fallos y carencias, las menciono despues.
public void venderEntrada() {
Scanner cine = new Scanner (System.in);
int precio = 0;
if (asientosLibres == 0) {
System.out.println("NO HAY ASIENTOS LIBRES");
} else {
System.out.println("Indique tipo cliente: J - Jubilado o adulto mayor (mayor a 55) / A - Adulto / M - Menor (menores de 12)");
String tipoCliente = cine.nextLine();
System.out.println("Indique cuantas entradas desea: ");
int cantidadEntradas = cine.nextInt();
if (cantidadEntradas > asientosLibres) {
System.out.println("NO HAY ASIENTOS LIBRES");
} else {
System.out.println("Elija metodo de pago: E - Efectivo / T - Tarjeta");
String metodoPago = cine.nextLine();
if (tipoCliente.equalsIgnoreCase("J")) {
precio = 15;
}
if (tipoCliente.equalsIgnoreCase("A")) {
precio = 30;
}
if (tipoCliente.equalsIgnoreCase("M")) {
precio = 10;
}
if (metodoPago.equalsIgnoreCase("T")) {
precio = (int) (precio + precio*0.18);
System.out.println("VENTA REALIZADA. PRECIO FINAL: " + precio);
}
asientosLibres = asientosLibres - cantidadEntradas;
System.out.println("QUEDAN " + asientosLibres + "asientos.");
}
}
cine.close();
}
Como decía, este método ya compila. Pero hay alguna cosilla por corregir:
- Hay que
contar los tipos de cliente. Es decir, una vez finalizada la venta, hay que aumentar el contador asignado a cada tipo de cliente según la cantidad de entradas que acaba de comprar.
Si un jubilado ha comprado entradas --> contJubilados = contJubilados + cantidadEntradas;
-
El cálculo de precios no es correcto. Aunque se le pregunta la cantidadEntradas que quiere, luego en el precio siempre se le cobra el valor de una sola entrada.
Hay que multiplicar el precio por la cantidadEntradas que ha pedido el usuario.
-El
calculo de suplemento e impuestos no es correcto Si paga el usuario con tarjeta, se le carga un 3.5% de suplemento extra.
Y ya luego, se le añade el 18% de impuestos, sea cual sea el método de pago.
-
No estamos usando el tipo de dato double para el calculo del precio.
Puesto que estamos trabajando con "tantos por ciento", divisiones y decimales... y además el dinero del mundo real es fraccionable (30$ no es lo mismo que 30.75$ ) lo correcto sería usar el tipo
double para calcular el precio y no el
int.
Es cierto que el tipo
double tiene el inconveniente de que luego en pantalla pueden salirnos número muy feos, con un montón de decimales que no necesitamos.
Y que bueno, esto es un ejercicio de aprendizaje y tampoco es demasiado importante.
El inconveniente este de los decimales en pantalla en realidad es fácil de corregir, usando el metodo format() de la clase String.
Pero yo propongo que esto de momento lo dejemos de lado. Si quieres, seguimos haciendo casting a
int como has hecho aquí:
precio = (int) (precio + precio*0.18);
y ya luego al final, cuando el programa ya esté funcionando, si quieres lo cambiamos para usar el tipo
double y vemos como formatear el resultados para que solo nos muestre dos decimales en pantalla.
Dejo aquí la clase al completo tal y como la tenemos ahora. Falta corregir estas cosas que he mencionado. Y luego añadir otro método más que se encargue de mostrar estadísticas.
package boleteria_cine;
import java.util.Scanner;
public class Sala {
//Atributos
private String nombrePelicula;
private int asientosLibres = 20;
private int contJubilados = 0;
private int contAdultos = 0;
private int contMenores = 0;
private double recaudacion = 0;
//Constructor
public Sala(String nombre) {
nombrePelicula = nombre;
}
//Metodos
public String getNombrePelicula() {
return nombrePelicula;
}
public void venderEntrada() {
Scanner cine = new Scanner (System.in);
int precio = 0;
if (asientosLibres == 0) {
System.out.println("NO HAY ASIENTOS LIBRES");
} else {
System.out.println("Indique tipo cliente: J - Jubilado o adulto mayor (mayor a 55) / A - Adulto / M - Menor (menores de 12)");
String tipoCliente = cine.nextLine();
System.out.println("Indique cuantas entradas desea: ");
int cantidadEntradas = cine.nextInt();
if (cantidadEntradas > asientosLibres) {
System.out.println("NO HAY ASIENTOS LIBRES");
} else {
System.out.println("Elija metodo de pago: E - Efectivo / T - Tarjeta");
String metodoPago = cine.nextLine();
if (tipoCliente.equalsIgnoreCase("J")) {
precio = 15;
}
if (tipoCliente.equalsIgnoreCase("A")) {
precio = 30;
}
if (tipoCliente.equalsIgnoreCase("M")) {
precio = 10;
}
if (metodoPago.equalsIgnoreCase("T")) {
precio = (int) (precio + precio*0.18);
System.out.println("VENTA REALIZADA. PRECIO FINAL: " + precio);
}
asientosLibres = asientosLibres - cantidadEntradas;
System.out.println("QUEDAN " + asientosLibres + "asientos.");
}
}
cine.close();
}
}