Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.


Mensajes - Kabuto

Páginas: 1 2 3 4 5 6 [7] 8 9 10 11 12 ... 50
121
Si ejecutas tu código, verás que no salen agrupados por ubicación.

La idea sería que primero se mostrasen por ejemplo los eventos Gold y el precio de cada evento. El precio se podría mostrar completo, con el impuesto y el descuento, que puede variar según si es temporada alta o baja.

Luego, lo mismo con los Platinum y por último los VIP.

Esto lo podríamos hacer con tres bucles, o tres métodos, donde cada uno se ocupe de mostrar los eventos de una ubicación concreta.

Pero si previamente ordenamos los eventos por ubicación, podremos hacerlo con un único bucle.

Para ordenarlos así, a la clase MisComparadores podemos añadir un nuevo Comparator, el cuál simplemente tiene que retornar el resultado de comparar el carácter que representa el código de ubicación de los eventos.

Citar
public class MisComparadores {
   
   public static final Comparator<Evento> TITULO_EVENTO_DESCENDENTE = new Comparator<Evento>() {
      @Override
      public int compare(Evento evento1, Evento evento2) {
         /*
          * Los titulos son cadenas String.
          * La clase String ya sabe como ha de compararse ella misma,
          * así que podemos retornar directamente el resultado de
          * comparar los títulos de los eventos.
          * Sin embargo, por defecto, la comparación de la clase String
          * nos daría un orden ASCENDENTE (de A a Z) y nosotros queremos
          * un orden DESCENDENTE (de Z a A).
          * Podemos revertir ese orden simplemente multiplicando por -1
          * el resultado que da la comparación de la clase String
          */
         return (evento1.getTitulo().compareTo(evento2.getTitulo())) * -1;
      }
   };
   
   public static final Comparator<Evento> UBICACION_ASCENDENTE = new Comparator<Evento>() {
      @Override
      public int compare(Evento evento1, Evento evento2) {
         return Character.compare(
evento1.getCodigoUbicacion(), evento2.getCodigoUbicacion());
      }
   };


}

Con este comparador, y sin necesidad de cambiar nada en la clase Evento ya podemos desarrollar la clase Prueba02 para que haga el listado.
Primero ordenaremos según ubicación.
Y luego al listar, haremos que el sistema detecte cuándo ha terminado con los eventos de una ubicación y va a comenzar con otros, para que lo muestre en pantalla.
Código: [Seleccionar]
package pruebas;

import java.util.ArrayList;

import entidades.Evento;
import util.MisComparadores;

public class Prueba02 {

private static ArrayList<Evento> eventos = new ArrayList<Evento>();

public static void main(String[] args) {
//Agregamos eventos para pruebas
        Evento.cargarDatosPruebas(eventos);

        //Listar los Eventos
        eventos.sort(MisComparadores.UBICACION_ASCENDENTE); //Ordenamos por ubicacion
        System.out.println("\n\t\tLISTADO DE EVENTOS AGRUPADOS POR UBICACION");
       
        char ubicacion = ' ';
        for (Evento even: eventos) {
        //Comprobamos si el evento actual es de distinta ubicacion, y por tanto comienza nuevo grupo
        if (even.getCodigoUbicacion() != ubicacion) { //Ubicacion distinta
        System.out.println(textoUbicacion(even.getCodigoUbicacion())); //Iniciamos nuevo grupo
        ubicacion = even.getCodigoUbicacion(); //Actualizamos la ubicacion actual
        }
        //Mostramos datos del evento
        System.out.printf("--> Titulo: %-35s --> Precio: %.2f\n",
        even.getTitulo(), even.getMontoTotal() - even.getDescuento());
     
        }

}

/*
* Devuelve un texto descriptivo para el codigo de ubicacion.
* Lo usaremos como cabecera para cada grupo de eventos.
*/
private static String textoUbicacion(char codigo) {
switch(codigo) {
case 'G':
return "\n\t---EVENTOS Gold---";
case 'P':
return "\n\t---EVENTOS Platinum---";
default:
return "\n\t---EVENTOS VIP---";
}
}

}

Al ejecutarlo, en pantalla vemos como los eventos quedan visiblemente agrupados.
Citar
      LISTADO DE EVENTOS AGRUPADOS POR UBICACION

   ---EVENTOS Gold---
--> Titulo: Recuperacion Fauna Iberica          --> Precio: 159,83
--> Titulo: Descifrando Codigo Ensamblador      --> Precio: 168,71

   ---EVENTOS Platinum---
--> Titulo: Impacto Guerra Ucrania              --> Precio: 265,77
--> Titulo: Presentacion Novela Historica       --> Precio: 265,77

   ---EVENTOS VIP---
--> Titulo: Arte Textil Africano                --> Precio: 106,49
--> Titulo: Nuevas Tecnicas Marketing           --> Precio: 106,49


En los precios vemos que solo hay variedad en los Gold, porque uno es "temporada alta" y el otro no.
En los otros no hay variación porque resulta que los hemos creado bajo la misma temporada.

Opcionalmente, podemos modificar el código de creación de estos eventos para que no coincidan sus temporadas, y así reflejar más variedad en los precios.
Citar
      LISTADO DE EVENTOS AGRUPADOS POR UBICACION

   ---EVENTOS Gold---
--> Titulo: Recuperacion Fauna Iberica          --> Precio: 159,83
--> Titulo: Descifrando Codigo Ensamblador      --> Precio: 168,71

   ---EVENTOS Platinum---
--> Titulo: Impacto Guerra Ucrania              --> Precio: 265,77
--> Titulo: Presentacion Novela Historica       --> Precio: 280,53

   ---EVENTOS VIP---
--> Titulo: Arte Textil Africano                --> Precio: 106,49
--> Titulo: Nuevas Tecnicas Marketing           --> Precio: 100,89



Venga, que ya queda menos.
Sigue adelante con la siguiente prueba:
Citar
clase Prueba03 que muestre la lista de eventos y el total recaudado por cada evento.
Para esta prueba, no será necesario ordenar los eventos de ninguna manera.
Solamente hacer una lista con los títulos de los eventos y el total recaudado.

El total recaudado sería el resultado de multiplicar el precio (monto - descuento) por la cantidad de asistentes a dicho evento. La cantidad de asistentes la sabemos por el tamaño que tenga el ArrayList, y esto nos lo dice su método size()

En este caso, si podrías hacer un nuevo método para la clase Evento que se ocupe de hacer el cálculo de la recaudación.

Un saludo.

122
La primera prueba tendría dos partes:
  • Creación de Eventos
  • Listar Eventos creados

Centrémonos en la primera parte.
Hay que pedir datos al usuario para crear eventos, los cuáles podemos añadirlos a un ArrayList para luego poder mostrar un listado.
Por cada evento, hay que crear además un expositor y uno o más asistentes.

Este proceso podemos separarlo en tres métodos:
  • para crear y retornar un Expositor
  • para crear y retornar un Asistente
  • para crear y retornar un Evento, donde invocaremos a los métodos que crean Expositores y Asistentes

Combinando esos tres métodos, podemos hacer un bucle while donde vayamos creando y añadiendo Eventos al ArrayList, hasta que el usuario decida terminar.

Código: [Seleccionar]
package pruebas;

import java.util.ArrayList;
import java.util.Scanner;

import entidades.*;

public class Prueba01 {

private static ArrayList<Evento> eventos = new ArrayList<Evento>();
private static Scanner teclado = new Scanner(System.in);

public static void main(String[] args) {

//Creacion de Eventos
char terminar = 'N';
while (terminar != 'S') {
eventos.add(crearEvento());
System.out.println("\nEvento añadido. ¿Desea TERMINAR?(S/N): ");
terminar = teclado.nextLine().toUpperCase().charAt(0);
}


}

private static Expositor crearExpositor() {
System.out.println("\n\tDATOS DEL EXPOSITOR");
System.out.print("Codigo: ");
String codigo = teclado.nextLine();
System.out.print("Nombre: ");
String nombre = teclado.nextLine();
System.out.print("Apellidos: ");
String apellidos = teclado.nextLine();
System.out.print("Sueldo: ");
double sueldo = Double.parseDouble(teclado.nextLine());
System.out.print("Correo: ");
String correo = teclado.nextLine();

return new Expositor(codigo, nombre, apellidos, sueldo, correo);
}

private static Asistente crearAsistente() {
System.out.println("\n\tDATOS DEL ASISTENTE");
System.out.print("Codigo: ");
String codigo = teclado.nextLine();
System.out.print("Nombre: ");
String nombre = teclado.nextLine();
System.out.print("Apellidos: ");
String apellidos = teclado.nextLine();
System.out.print("Correo: ");
String correo = teclado.nextLine();
System.out.print("Telefono: ");
String telef = teclado.nextLine();
System.out.print("Direccion: ");
String direcc = teclado.nextLine();

return new Asistente(codigo, nombre, apellidos, correo, telef, direcc);
}

private static Evento crearEvento() {
System.out.println("\n\tDATOS DEL EVENTO");
System.out.print("Titulo: ");
String titulo = teclado.nextLine();
System.out.print("Duracion(en minutos): ");
int duracion = Integer.parseInt(teclado.nextLine());
System.out.print("Hora ingreso: ");
String ingreso = teclado.nextLine();
System.out.print("Hora salida: ");
String salida = teclado.nextLine();
System.out.print("Temporada Alta?(S/N): ");
boolean temporadaAlta = teclado.nextLine().toUpperCase().charAt(0) == 'S';
System.out.println("Indique codigo ubicacion");
System.out.println("[P] -> Platinum / [G] -> Gold / [V] -> VIP");
System.out.print("Codigo: ");
char ubicacion = teclado.nextLine().toUpperCase().charAt(0);

//Necesitamos un Expositor
Expositor expo = crearExpositor();

//Podemos crear el Evento
Evento evento = new Evento(titulo, duracion, expo, ingreso, salida, temporadaAlta, ubicacion);

//Ahora hay que añadir Asistentes al Evento
char terminar = 'N';
while (terminar != 'S') {
Asistente nuevo = crearAsistente();
evento.addAsistente(nuevo);
System.out.println("\nAsistente añadido. ¿Desea TERMINAR?(S/N): ");
terminar = teclado.nextLine().toUpperCase().charAt(0);
}

return evento;
}

}

Con esto tendríamos la primera parte.
Ahora hay que ver cómo hacemos la segunda parte.
Nos piden un listado de los Eventos, incluyendo su Expositor(que es uno) y Asistentes(que pueden ser muchos)
Y además el listado ha de estar ordenado por título y de manera descendente, es decir, de Z a A.

Bien, para facilitar esto, primero deberíamos añadir un nuevo método a la clase Evento que se encargue de mostrar detalladamente todos sus datos, incluyendo expositor y asistentes.
Código: [Seleccionar]

public void mostrarEvento() {
System.out.println("\n\t\t" + titulo.toUpperCase());
System.out.print("\t\t");
for (int i = 0; i < titulo.length(); i++)
System.out.print("-");
System.out.printf("\nExpositor: %s %s", expositor.getNombre(), expositor.getApellidos());
System.out.printf("\nDuracion: %d Ingreso: %s Salida: %s\n", duracion, horaIngreso, horaSalida);
System.out.println("Temporada: " + (esTemporadaAlta?"Alta":"Baja"));
System.out.print("Ubicacion: ");
switch(codigoUbicacion) {
case 'P':
System.out.println("Platinum");
break;
case 'G':
System.out.println("Gold");
break;
default:
System.out.println("VIP");
}

System.out.println("\n\t---Lista de Asistentes---\n");
for (Asistente asis: asistentes)
System.out.printf("-> %s %s\n", asis.getNombre(), asis.getApellidos());
}

Con esto ya podemos volver a la clase Prueba01 y añadir código para mostrar un listado tras la creación de los eventos:
Citar
   public static void main(String[] args) {
      
      //Creacion de Eventos
      char terminar = 'N';
      while (terminar != 'S') {
         eventos.add(crearEvento());
         System.out.println("\nEvento añadido. ¿Desea TERMINAR?(S/N): ");
         terminar = teclado.nextLine().toUpperCase().charAt(0);
      }
      
      //Listar los Eventos
      System.out.println("\n\t\tLISTADO DE EVENTOS");
      System.out.println("\t\t------- -- -------\n");
      for (Evento even: eventos) {
         System.out.println("\n\n\t\t*************************\n");
         even.mostrarEvento();
      }


   }


Bien, con esto listamos los eventos, pero aún no están ordenados como nos han solicitado.
Para poder ordenar a nuestro gusto los eventos contenidos en el ArrayList, podríamos implementarle la interfaz Comparable a la clase Evento y sobre escribir el método compareTo() para indicarle cómo se han de ordenar.

Pero, viendo lo que están solicitando en las siguientes clases de "pruebas", parece que nos va a convenir poder ordenar los eventos al menos de dos formas distintas.
Así que en lugar de usar la interfaz Comparable, podemos crear una serie de objetos Comparator, donde cada uno establecerá distintas reglas de ordenamiento y así podremos llamarlos según lo que necesitemos.

Parecido a lo que habíamos hecho con la clase MisConstantes, podemos hacer una clase MisComparadores donde definir unos objetos Comparator como unas constantes que puedan ser utilizadas en cualquier momento para decirle al ArrayList de Eventos cómo ha de ordenarse.

De momento, escribimos un comparador que permita ordenar por "título descendente".
Código: [Seleccionar]
package util;

import java.util.Comparator;

import entidades.Evento;

public class MisComparadores {

public static final Comparator<Evento> TITULO_EVENTO_DESCENDENTE = new Comparator<Evento>() {
@Override
public int compare(Evento evento1, Evento evento2) {
/*
* Los titulos son cadenas String.
* La clase String ya sabe como ha de compararse ella misma,
* así que podemos retornar directamente el resultado de
* comparar los títulos de los eventos.
* Sin embargo, por defecto, la comparación de la clase String
* nos daría un orden ASCENDENTE (de A a Z) y nosotros queremos
* un orden DESCENDENTE (de Z a A).
* Podemos revertir ese orden simplemente multiplicando por -1
* el resultado que da la comparación de la clase String
*/
return (evento1.getTitulo().compareTo(evento2.getTitulo())) * -1;
}
};

}

Con esto, en la clase Prueba01 podemos ordenar el ArrayList antes de mostrar el listado en pantalla.
Para ello, llamamos al método sort() que posee el ArrayList y le pasamos entre paréntesis el comparador que acabamos de escribir:
Citar
   public static void main(String[] args) {
      
      //Creacion de Eventos
      char terminar = 'N';
      while (terminar != 'S') {
         eventos.add(crearEvento());
         System.out.println("\nEvento añadido. ¿Desea TERMINAR?(S/N): ");
         terminar = teclado.nextLine().toUpperCase().charAt(0);
      }
      
      //Listar los Eventos
      eventos.sort(MisComparadores.TITULO_EVENTO_DESCENDENTE);
      System.out.println("\n\t\tLISTADO DE EVENTOS");
      System.out.println("\t\t------- -- -------\n");
      for (Evento even: eventos) {
         System.out.println("\n\n\t\t*************************\n");
         even.mostrarEvento();
      }

   }


Y con esto ya habríamos cumplido con lo que pide Prueba01: creación de eventos y mostrar listado ordenado descendente por título.


Antes de terminar, vamos a añadir una cosa.
Es tedioso, más bien terrible...., tener que crear eventos por teclado para poder comprobar si el listado sale ordenado o no.
Con las siguientes clases "pruebas", va a ocurrir lo mismo. Nos piden una serie de operaciones que para poder comprobar si funcionan, primero necesitamos tener eventos.

En lugar de estar creando eventos por teclado cada vez que ejecutamos una prueba, lo ideal es crear mediante código una serie de datos ya predefinidos para poder iniciar las pruebas con datos ya disponibles, sin tener que depende de introducirlos por teclado.

Para esto, en la clase Evento, podemos crear un método estático que reciba un ArrayList y lo cargue con una serie de datos: Expositores, Asistentes y Eventos listos para ser utilizados en las pruebas.
Código: [Seleccionar]


/*
* El siguiente método estático es para facilitar el "entorno de pruebas".
* Añade al ArrayList recibido por argumentos unos cuántos Eventos, con sus
* Expositores y Asistentes, para que las clases de prueba puedan comenzar
* con una serie de datos cargados con los que poder trabajar sin tener
* que introducirlos a mano
*/
public static void cargarDatosPruebas(ArrayList<Evento> eventos) {
//Expositores
Expositor ex1 = new Expositor("EXPO001", "Pedro", "Baños Lopez", 15000, "pedro@balo.com");
Expositor ex2 = new Expositor("EXPO002", "Ines", "Felisa Sanchez", 17000, "ines@fesa.com");
Expositor ex3 = new Expositor("EXPO003", "Ramon", "Lobo Maturana", 12000, "ramon@loma.com");
Expositor ex4 = new Expositor("EXPO004", "Luis", "Salvat Cami", 11000, "luis@saca.com");
Expositor ex5 = new Expositor("EXPO005", "Carmen", "Robledo Velez", 20000, "carmen@rove.com");
Expositor ex6 = new Expositor("EXPO006", "Felipe", "Moreno Reina", 16000, "feli@more.com");
//Asistentes
Asistente as1 = new Asistente("ASI001", "Jorge", "Morales Garcia", "jor@moga.com", "646578090", "C/Peru");
Asistente as2 = new Asistente("ASI002", "Laura", "Juan Moragas", "lalaura@jumo.com", "634588190", "C/Lima");
Asistente as3 = new Asistente("ASI003", "Sara", "Pelaez Tuna", "sarita@petu.com", "646578090", "C/Madrid");
Asistente as4 = new Asistente("ASI004", "Guadalupe", "Flores Flores", "lupe@floflo.com", "646578090", "C/Avestruz");
Asistente as5 = new Asistente("ASI005", "Antonio", "Paz Garcia", "toni@paga.com", "646578090", "C/Pelicano");
Asistente as6 = new Asistente("ASI006", "Antonia", "Perez Castillo", "anto@peca.com", "646578090", "C/Nutria");
Asistente as7 = new Asistente("ASI007", "Alicia", "Aloy Sanchez", "ali@alsa.com", "646578090", "C/Ibice");
Asistente as8 = new Asistente("ASI008", "Javier", "Barbudo Lopez", "javi@balo.com", "646578090", "C/Muflon");
Asistente as9 = new Asistente("ASI009", "Carla", "Bella Zapata", "carla@beza.com", "646578090", "C/Alce");
Asistente as10 = new Asistente("ASI010", "Federico", "Martin Vela", "fredy@mave.com", "646578090", "C/Ecuador");
Asistente as11 = new Asistente("ASI011", "Eva", "Santamaria Lopez", "eva@salo.com", "646578090", "C/Quito");
Asistente as12 = new Asistente("ASI011", "Mario", "Moreno Cantinflas", "mario@moca.com", "646578090", "C/Mexico");
//Eventos
Evento ev1 = new Evento("Impacto Guerra Ucrania", 90, ex1, "10:00", "11:30", true, 'P');
ev1.addAsistente(as1); ev1.addAsistente(as2);
Evento ev2 = new Evento("Arte Textil Africano", 60, ex2, "12:00", "13:00", false, 'V');
ev2.addAsistente(as3); ev2.addAsistente(as4);
Evento ev3 = new Evento("Recuperacion Fauna Iberica", 90, ex3, "14:00", "15:30", true, 'G');
ev3.addAsistente(as5); ev3.addAsistente(as6);
Evento ev4 = new Evento("Nuevas Tecnicas Marketing", 45, ex4, "10:00", "10:45", false, 'V');
ev4.addAsistente(as7); ev4.addAsistente(as8);
Evento ev5 = new Evento("Presentacion Novela Historica", 60, ex5, "17:00", "18:", true, 'P');
ev5.addAsistente(as9); ev5.addAsistente(as10);
Evento ev6 = new Evento("Descifrando Codigo Ensamblador", 120, ex6, "18:00", "20:00", false, 'G');
ev6.addAsistente(as11); ev6.addAsistente(as12);
//Añadimos los eventos creados
eventos.add(ev1); eventos.add(ev2); eventos.add(ev3);
eventos.add(ev4); eventos.add(ev5); eventos.add(ev6);
}

Así, en el main de nuestras pruebas, lo primero que haremos será invocar este método y pasarle nuestro ArrayList de eventos para que lo cargue con datos sin tener que hacerlo nosotros por teclado:
Citar
   
   private static ArrayList<Evento> eventos = new ArrayList<Evento>();
   private static Scanner teclado = new Scanner(System.in);

   public static void main(String[] args) {
      
      //Agregamos eventos para pruebas
      Evento.cargarDatosPruebas(eventos);

      
      //Creacion de Eventos
      char terminar = 'N';
      while (terminar != 'S') {
         eventos.add(crearEvento());
         System.out.println("\nEvento añadido. ¿Desea TERMINAR?(S/N): ");
         terminar = teclado.nextLine().toUpperCase().charAt(0);
      }
      
      //Listar los Eventos
      eventos.sort(MisComparadores.TITULO_EVENTO_DESCENDENTE);
      System.out.println("\n\t\tLISTADO DE EVENTOS");
      System.out.println("\t\t------- -- -------\n");
      for (Evento even: eventos) {
         System.out.println("\n\n\t\t*************************\n");
         even.mostrarEvento();
      }

   }

Y con esto ya podemos seguir con el resto de pruebas
Intenta Prueba02.

Recuerda que ya no tienes que introducir eventos por teclado, podemos cargar un ArrayList con eventos automáticamente llamando al método correspondiente.

Una vez cargado, haz un listado del arraylist mostrando:
- titulo del evento
- ubicación
- precio

Cuanto tengas el listado, ahora hay que ver como agrupar esos eventos por ubicación.
Para ello, intenta crear un nuevo comparador que se encargue de ordenar los eventos según la ubicación.
Una vez ordenados, ya podemos hacer una salida por pantalla en tres grupos

Inténtalo, llega hasta donde puedas, no importa si no lo consigues.
Atascarse en el intento es la mejor forma de aprender.
Comparte aquí lo que logres hacer y lo completamos.

Saludos

123
A ver, lo primero es identificar las principales entidades que intervienen.

Aquí se organizan Eventos.
En un Evento interviene un Expositor y van a acudir una cantidad indefinida de Asistentes

Evento, Expositor y Asistente serían las principales entidades.

Esta podría ser la clase Asistente
Código: [Seleccionar]
package entidades;

public class Asistente {

private String codigo;
private String nombre;
private String apellidos;
private String correo;
private String telefono;
private String direccion;

public Asistente(String codigo, String nombre, String apellidos, String correo,
String telefono, String direccion) {
this.codigo = codigo;
this.nombre = nombre;
this.apellidos = apellidos;
this.correo = correo;
this.telefono = telefono;
this.direccion = direccion;
}

public String getCodigo() {
return codigo;
}

public void setCodigo(String codigo) {
this.codigo = codigo;
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}

public String getApellidos() {
return apellidos;
}

public void setApellidos(String apellidos) {
this.apellidos = apellidos;
}

public String getCorreo() {
return correo;
}

public void setCorreo(String correo) {
this.correo = correo;
}

public String getTelefono() {
return telefono;
}

public void setTelefono(String telefono) {
this.telefono = telefono;
}

public String getDireccion() {
return direccion;
}

public void setDireccion(String direccion) {
this.direccion = direccion;
}

}

Esta la clase Expositor
Código: [Seleccionar]
package entidades;

public class Expositor {

private String codigo;
private String nombre;
private String apellidos;
private double sueldo;
private String correo;

public Expositor(String codigo, String nombre, String apellidos, double sueldo, String correo) {
this.codigo = codigo;
this.nombre = nombre;
this.apellidos = apellidos;
this.sueldo = sueldo;
this.correo = correo;
}

public String getCodigo() {
return codigo;
}

public void setCodigo(String codigo) {
this.codigo = codigo;
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}

public String getApellidos() {
return apellidos;
}

public void setApellidos(String apellidos) {
this.apellidos = apellidos;
}

public double getSueldo() {
return sueldo;
}

public void setSueldo(double sueldo) {
this.sueldo = sueldo;
}

public String getCorreo() {
return correo;
}

public void setCorreo(String correo) {
this.correo = correo;
}

}

Y esta la clase Evento.
Además de los atributos que indica el enunciado, yo le he añadido un ArrayList para contener a los asistentes que acudirán a este evento.

Además incluye los métodos que pide el enunciado. Aunque no me queda claro si el descuento según la temporada, debería ir aplicado en el resultado que calcula el "monto total".

Código: [Seleccionar]
package entidades;

import java.util.ArrayList;
import util.MisConstantes;

public class Evento {

private String titulo;
private int duracion;
private Expositor expositor;
private String horaIngreso;
private String horaSalida;
private boolean esTemporadaAlta;
private char codigoUbicacion;
private ArrayList<Asistente> asistentes;

public Evento(String titulo, int duracion, Expositor expositor, String horaIngreso, String horaSalida,
boolean esTemporadaAlta, char codigoUbicacion) {
this.titulo = titulo;
this.duracion = duracion;
this.expositor = expositor;
this.horaIngreso = horaIngreso;
this.horaSalida = horaSalida;
this.esTemporadaAlta = esTemporadaAlta;
this.codigoUbicacion = codigoUbicacion;
asistentes = new ArrayList<Asistente>();
}

public String getTitulo() {
return titulo;
}

public void setTitulo(String titulo) {
this.titulo = titulo;
}

public int getDuracion() {
return duracion;
}

public void setDuracion(int duracion) {
this.duracion = duracion;
}

public Expositor getExpositor() {
return expositor;
}

public void setExpositor(Expositor expositor) {
this.expositor = expositor;
}

public String getHoraIngreso() {
return horaIngreso;
}

public void setHoraIngreso(String horaIngreso) {
this.horaIngreso = horaIngreso;
}

public String getHoraSalida() {
return horaSalida;
}

public void setHoraSalida(String horaSalida) {
this.horaSalida = horaSalida;
}

public boolean isEsTemporadaAlta() {
return esTemporadaAlta;
}

public void setEsTemporadaAlta(boolean esTemporadaAlta) {
this.esTemporadaAlta = esTemporadaAlta;
}

public char getCodigoUbicacion() {
return codigoUbicacion;
}

public void setCodigoUbicacion(char codigoUbicacion) {
this.codigoUbicacion = codigoUbicacion;
}

public void addAsistente(Asistente asis) {
asistentes.add(asis);
}

public double getCostoIngreso() {
switch(codigoUbicacion) {
case 'P':
return MisConstantes.COSTO_P;
case 'G':
return MisConstantes.COSTO_G;
default:
return MisConstantes.COSTO_V;
}
}

public double getMontoTotal() {
double ingreso = getCostoIngreso();
return ingreso + (ingreso*MisConstantes.IGV/100);
}

public double getDescuento() {
return esTemporadaAlta?getMontoTotal()*10/100:getMontoTotal()*5/100;
}

}

Para dichos cálculos, se usan una constantes que el enunciado pide declarar en un package separado:
Código: [Seleccionar]
package util;

public class MisConstantes {
//Costos de ubicacion
public final static double COSTO_P = 250.25;
public final static double COSTO_G = 150.5;
public final static double COSTO_V = 95;
//Impuesto general de ventas
public final static int IGV = 18; //% sobre precio base
}

Bien, esas podrían ser las clases. Luego puede que queramos añadir algún método más o modificar algo.

Pero en principio, con esto ya se podría comenzar a hacer las distintas clases de "prueba" que pide el enunciado.

Intenta comenzar tú la primera.
Se necesitará un ArrayList para almacenar los distintos Eventos que se vayan creando.
Estos eventos se tendrán que crear dentro de un bucle, pidiendo datos al usuario.
Y por cada Evento, habrá que crear también un Expositor y varios Asistentes (en un segundo bucle anidado)

Inténtalo y comparte por aquí lo que consigas.
Un saludo.

124
Me alegro.
Siempre que podamos ayudarte, aquí estaremos.

Saludos.

125
¡Estupenda noticia!

Me alegra que hayas logrado trabajar de lo que te apasiona.
No dejes de visitarnos de vez en cuando, quizás puedas ayudar a otros que están empezando. Y los comienzos en esto pueden ser durillos sin el apoyo de otros, como tú mismo habrás comprobado.

Un saludo.

126
Hola Rocka.

Las clases Alumno y Materia bien, lo único que yo cambiaría son los constructores sin parámetros.
Código: [Seleccionar]


public Alumno() {

}
Nunca me ha gustado dejarlos vacíos sin código, de hecho, para dejarlos vacíos entonces no hace falta ni ponerlos.

Ya que los ponemos, interesa inicializar los atributos a unos valores por defecto.
Esto es especialmente importante para los atributos que sean clases, como por ejemplo el nombre del alumno que es clase String.
Si no los inicializamos, se quedan con valor nulo (null) y esto deja abierta la posibilidad de que pueda ocurrir una excepción(ya aprenderás más adelante qué son las excepciones) por intentar acceder al valor de un atributo..., que en realidad no tiene valor, porque es null

Así que mejor dar a los atributos unos valores iniciales, los que sean, aunque sea una cadena vacía para los String y un 0 para los valores numéricos como la edad.
Código: [Seleccionar]

public Alumno() {
nombre = "";
edad = 0;
}
Y lo mismo para la clase Materia

Pero bueno, al margen de este detalle, ambas clases estarían bien.

Sin embargo, la clase Nota, ya no me parece tan bien.
Para empezar, creo que el nombre correcto para esta entidad debería ser Asignacion

Y lo más importante, nos dicen que:
Citar
Una asignación corresponde a la relación de una materia con un alumno
Pues esa "relación" no ha quedado modelada en tu clase.
Además de las 3 notas, esta clase debería tener dos atributos más: un objeto Materia y un objeto Alumno

De esta manera, alumno y materia quedan relacionados.

Yo escribiría dicha clase de la siguiente manera.
Cambio nombres de algunos atributos y métodos, por gusto mío, pero en realidad son casi iguales a los que habías escrito tú.
El método toString() si lo he hecho más elaborado, para que sea él quien nos de toda la info que necesitamos presentar en pantalla, y que salga más o menos presentable.
Código: [Seleccionar]
public class Asignacion {

private Materia materia;
private Alumno alumno;
private int parcial1;
private int parcial2;
private int practico;

public Asignacion() {
materia = new Materia();
alumno = new Alumno();
parcial1 = 0;
parcial2 = 0;
practico = 0;
}

public Asignacion(Materia materia, Alumno alumno, int parcial1, int parcial2, int practico) {
this.materia = materia;
this.alumno = alumno;
this.parcial1 = parcial1;
this.parcial2 = parcial2;
this.practico = practico;
}

public Materia getMateria() {
return materia;
}

public void setMateria(Materia materia) {
this.materia = materia;
}

public Alumno getAlumno() {
return alumno;
}

public void setAlumno(Alumno alumno) {
this.alumno = alumno;
}

public int getParcial1() {
return parcial1;
}

public void setParcial1(int parcial1) {
this.parcial1 = parcial1;
}

public int getParcial2() {
return parcial2;
}

public void setParcial2(int parcial2) {
this.parcial2 = parcial2;
}

public int getPractico() {
return practico;
}

public void setPractico(int practico) {
this.practico = practico;
}

public double calcularPromedio(){
return (parcial1 + parcial2 + practico) / 3;
}

public boolean estaAprobada() {
return calcularPromedio() >= 6;
}

public String estadoAsignacion() {
return estaAprobada()?"Aprobada":"Reprobada";
}

@Override
public String toString() {
StringBuilder cadena = new StringBuilder();
cadena.append("-Nombre Alumno: " + alumno.getNombre());
cadena.append("\n-Nombre Materia: " + materia.getNombre());
cadena.append("\n-Cuatrimestre: " + materia.getCuatrimestre());
cadena.append("\n-Notas:");
cadena.append("\n\tParcial 1: " + parcial1);
cadena.append("\n\tParcial 2: " + parcial2);
cadena.append("\n\tPractico: " + practico);
cadena.append(String.format("\n-Promedio: %.2f", calcularPromedio()));
cadena.append("\n-Estado: " + estadoAsignacion());

return cadena.toString();
}
}

Ya luego solo queda hacer la clase EscuelaTest.
Tres alumnos, tres materias y seis asignaciones.

Las asignaciones las colecciono en un ArrayList.
No se si los conoces ya, si no es así, también se pueden hacer en un arreglo "primitivo".

Pero es importante coleccionarlos de una manera u otra, porque así luego se pueden presentar todas en pantalla usando un simple bucle.
Código: [Seleccionar]
public class EscuelaTest {

public static void main(String[] args) {
Materia materia1 = new Materia("Matematicas", 2);
Materia materia2 = new Materia("Filosofia", 1);
Materia materia3 = new Materia("Economia", 3);
Alumno alumno1 = new Alumno("Felipe Reyes", 17);
Alumno alumno2 = new Alumno("Sara Pelaez", 16);
Alumno alumno3 = new Alumno("Laura Juan", 17);
//Lista asignaciones
ArrayList<Asignacion> lista = new ArrayList<Asignacion>();
lista.add(new Asignacion(materia1, alumno1, 7, 4, 5));
lista.add(new Asignacion(materia1, alumno3, 9, 6, 7));
lista.add(new Asignacion(materia2, alumno2, 5, 5, 6));
lista.add(new Asignacion(materia2, alumno3, 4, 8, 8));
lista.add(new Asignacion(materia3, alumno1, 8, 5, 8));
lista.add(new Asignacion(materia3, alumno2, 9, 0, 5));

System.out.println("\t\tLISTADO ASIGNACIONES\n");

for (Asignacion asig: lista) {
System.out.println(asig);
System.out.println("\n\t--------------------\n");
}
}

}

No dudes en preguntar si algo no lo entiendes o piensas que debería hacerse de otra manera.

Un saludo.

127
Haz tú primero un intento y compartelo por aquí.
Si no consigues al solución, te ayudamos a corregir/completar lo que sea.

Tienes que pedir un dato de tipo char al usuario.
Con un objeto Scanner, puedes pedirlo con el método nextLine(), el cuál te devuelve un String, pero si además le encadenas el método charAt(0) obtendrás un char.
nextLine().charAt(0);

Sin embargo, como hay que contemplar la posibilidad de que el caracter recibido sea mayúscula o minúscula, en estos casos lo ideal es transformar directamente a uno o a otro.
Como nos dice que al final hay que mostrar la ficha elegida y ha de mostrarse en mayúscula, pues así lo vamos a convertir.
Podemos hacerlo con el método toUpperCase(), aplicándolo al String que nos devuelve nextLine(), antes de pedir que lo convierta a char
nextLine().toUpperCase().charAt(0);


Esta petición de dato al usuario, se hace dentro de un bucle while que se ha de repetir mientras la ficha introducida sea distinto de 'X' y de 'O'

Inténtalo.
Un saludo.

128
Gracias por el aporte.
Un caballero en Moscú hace tiempo que lo tengo en la lista de pendientes de leer.

129
Aprender a programar desde cero / Re: Ayuda con pseudocodigo
« en: 12 de Octubre 2022, 12:09 »
Hola.

Pues de momento parece que vas bien.
El siguiente paso sería comprobar si la posición que ha indicado el usuario, está libre u ocupada antes de asignársela.
Y después de eso, otro paso será comprobar si el lote A está ya al 50%, para ver si hay que derivarlo a los otros lotes.

130
Aprender a programar desde cero / Re: java swing ventana gráfica
« en: 09 de Octubre 2022, 01:30 »
et es "etiqueta" (label)
Son nomenclaturas mías que suelo usar. Cada uno usa las que le parece mejor, no hay ninguna "norma" o costumbre común respecto a esto.

Usar nomenclaturas es muy cómodo. Cuando por ejemplo llega el momento de escribir el código para que funcione el botón de borrar, me preguntaré ¿qué nombre le puse?
Pues en lugar de tener que desplazarme por el código buscando la línea donde lo declaré, puedo adivinar que probablemente lo habré llamado btBorrar ya que es mi costumbre habitual, así que no tengo que buscarlo.


Lo que mencionas sobre el tamaño de fuente, lo de decidir el tamaño según las características del ordenador donde se está ejecutando, es algo que yo mismo he pensado muchas veces pero no lo he investigado.
Sí se puede hacer, desde luego, pero...¿cómo decidir cuál es la fuente adecuada para cada caso?
No se si habrá un consenso sobre esto, sería interesante que algún profesional que se dedique a la programación de verdad nos comentara sobre este asunto.

Yo tengo un monitor de alta resolución, 2560x1440 px, y diría que NO ES COSTUMBRE adaptar el tamaño de fuentes, porque yo todos los programas que uso en mi día a día: navegadores web, Steam, Eclipse, Libre Office, Filmora...,, sea el que sea, me encuentro con que las fuentes son demasiado pequeñas para la resolución de mi pantalla.

Puedo configurar Windows para que automáticamente amplíe las fuentes un determinado porcentaje, pero no siempre consigue unos tamaños acertados.
Así que por lo general uso las opciones de configuración de cada programa (si las tiene) para ampliar fuentes, o bien acepto tener que dejarme la vista  :o

Pero NINGÚN programa hace una adaptación de fuentes apropiada a mi pantalla. Así que parece que no suele hacerse en el mundo profesional.
Supongo que no es fácil, ya que cada dispositivo es un mundo. Hay pantallas de móvil con la misma resolución que la de mi monitor, pero obviamente los tamaños de pantalla (mi monitor es 27") son muy distintos.

Así que los programas, si quisieran determinar una fuente de texto adecuada, tendrían que valorar la resolución en pixeles, el tamaño en pulgadas, la relación de aspecto (16:9, 4:3, 16:10,....), la orientación (vertical, apaisada..),....
Son demasiadas variables a tener en cuenta, demasiado difícil acertar..., y luego al final seguramente tendrá más peso las dioptrías 8) de cada persona que todo lo antes mencionado.
Así que mejor dejar una fuente única, y en todo caso, dar opciones para que el propio usuario elija un tamaño de fuente a su gusto.

Por otro lado, la fuente que puse para este programa es exageradamente grande.
Al tratarse de un formulario con tan pocos elementos, pero que ocupa toda la pantalla (y mi pantalla es muy grande), puse una fuente gigante que parece más un título que no un texto.


Sobre la cantidad de paneles, es para conseguir que los elementos queden lo mejor maquetados posibles.
Los elementos Swing, no siempre ocupan los espacios dentro de un panel de manera que queden centrados y/o repartidos de forma simétrica.
Combinando paneles y con los layout adecuados, se puede llegar a conseguir.

Por ejemplo, vamos a suponer que quiero dos botones que queden repartidos y centrados simétricamente en un formulario.
Si los añado en el contenedor base, con un FlowLayout

Código: [Seleccionar]
public class Prueba extends JFrame {

private JButton btUno;
private JButton btDos;

public Prueba() {
btUno = new JButton("Botón 1");
btDos = new JButton("Botón 2");

setLayout(new FlowLayout());

add(btUno);
add(btDos);

setTitle("Prueba");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 300);
setLocationRelativeTo(null);
setVisible(true);
}


public static void main(String[] args) {
new Prueba();
}

}

No queda como yo quiero, están ahí rejuntado en el centro, con un montón de panel vacío alrededor.
Además, están pegados arriba, no están centrados verticalmente.


¿Y si pruebo con un BoxLayout que ponga los elementos en el eje X(horizontal)?
Código: [Seleccionar]
public class Prueba extends JFrame {

private JButton btUno;
private JButton btDos;

public Prueba() {
btUno = new JButton("Botón 1");
btDos = new JButton("Botón 2");

setLayout(new BoxLayout(getContentPane(), BoxLayout.X_AXIS));

add(btUno);
add(btDos);

setTitle("Prueba");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 300);
setLocationRelativeTo(null);
setVisible(true);
}


public static void main(String[] args) {
new Prueba();
}

}

Vaya, ahora están centrados en la vertical, pero no la horizontal. Y siguen pegados el uno al otro...


¿Probamos a darle paneles propios a cada botón?
Código: [Seleccionar]
public class Prueba extends JFrame {

private JButton btUno;
private JButton btDos;

public Prueba() {
btUno = new JButton("Botón 1");
btDos = new JButton("Botón 2");

setLayout(new BoxLayout(getContentPane(), BoxLayout.X_AXIS));
JPanel pnUno = new JPanel();
pnUno.add(btUno);
JPanel pnDos = new JPanel();
pnDos.add(btDos);
add(pnUno);
add(pnDos);

setTitle("Prueba");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 300);
setLocationRelativeTo(null);
setVisible(true);
}


public static void main(String[] args) {
new Prueba();
}

}

Humm. se parece un poco más a lo que busco. El espacio horizontal está bien repartido.
Pero no el vertical, están pegados arriba, yo los quisiera en el centro.




A ver.., vamos a recurrir a la clase Box, la cuál nos permite crear una "caja" y añadir elementos "invisibles" para que ocupen espacios y así situar nuestro elemento "visible".
Haremos dos "cajas", con dos objetos invisibles verticales y entre ellos, nuestro panel con botón.
Código: [Seleccionar]
public class Prueba extends JFrame {

private JButton btUno;
private JButton btDos;

public Prueba() {
btUno = new JButton("Botón 1");
btDos = new JButton("Botón 2");

setLayout(new BoxLayout(getContentPane(), BoxLayout.X_AXIS));

JPanel pnUno = new JPanel();
pnUno.add(btUno);
Box cajaVertical1 = Box.createVerticalBox();
cajaVertical1.add(Box.createVerticalGlue());
cajaVertical1.add(pnUno);
cajaVertical1.add(Box.createVerticalGlue());
JPanel pnDos = new JPanel();
pnDos.add(btDos);
Box cajaVertical2 = Box.createVerticalBox();
cajaVertical2.add(Box.createVerticalGlue());
cajaVertical2.add(pnDos);
cajaVertical2.add(Box.createVerticalGlue());

add(cajaVertical1);
add(cajaVertical2);

setTitle("Prueba");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 300);
setLocationRelativeTo(null);
setVisible(true);
}


public static void main(String[] args) {
new Prueba();
}

}

Ahora sí, esto sería lo que busco.
Parece que por abajo hay más espacio que por arriba, pero yo lo daría por bueno.


Como ves, si nos ponemos caprichosos con las posiciones que queremos que ocupen los elementos, incluso para una interfaz simplona compuesta de solo dos botones, pues es muy posible que necesitemos "envolver" algunos elementos en su propio JPanel y así además poder combinar distintos layouts.


Hay un layout que nos permite evitar tener que usar tanto JPanel para situar los componentes a nuestros gusto. Es el GridBagLayout, tan útil y sofisticado... como complejo y enfarragoso de utilizar.

Si tienes curiosidad busca tutoriales por Google, cualquiera que encuentres seguro que sabe explicarlo mejor que yo  :P

Un saludo.

131
Aprender a programar desde cero / Re: java swing ventana gráfica
« en: 04 de Octubre 2022, 00:45 »
Sí, pero ponerlo como atributo de Main tiene una ventaja.

Por ejemplo, la clase ActionListener para el botón de "Borrar", necesita tener acceso al campo de texto:

Citar
   private class AccionBorrar implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         etMensajes.setText(null);
         campoTexto.setText(null);
      }
   }

Al ponerlo como atributo de Main, entonces es visible en todos los ámbitos del programa y este ActionListener puede acceder directamente a ese campo.

Si lo hubiéramos puesto como atributo de la clase PanelCampoTexto, entonces su ámbito se queda limitado al interior de esta clase.
El resto de clases ya no pueden acceder a él, porque no pueden "verlo" al ser un atributo privado de otra clase.
Aunque eso tendría otras soluciones:
- Declararlo como atributo public en lugar de private.
- Proporcionar a la clase PanelCampoTexto un gettter y un setter que de acceso a su atributo privado.
- O proporcionar a PanelCampoTexto un método que se encargue de borrar el campo, ya que en realidad es la única interacción que necesitamos hacer con él.
Este método sería publico y por tanto visible para otras clases.

Aunque para aplicar estas soluciones, tendremos que declarar a la propia clase PanelCampoTexto como atributo del Main.

Siempre hay distintas formas de hacer una misma cosa, ya cada programador decide cuál emplear.

Yo, cuando se trata de programas así sencillos como este, suelo declarar los campos de texto, etiquetas, botones, etc.. como atributos del Main. Al menos los que sé que otras clases van a necesitar poder acceder a ellos.

En un programa más complejo, donde fácilmente pueden haber 30 campos de texto, 12 botones, 40 etiquetas,.... hacerlo así puede resultar caótico y poco elegante tener medio centenar de atributos declarados en el Main.
En estos casos, ya sí prefiero que cada clase JPanel tenga sus propios atributos, con los setters/getters y métodos que hagan falta para que sus elementos puedan comunicarse con otras clases.
Y además, prefiero que cada una de estas clases estén escritas en su propio archivo .java.

Es curioso, pero cuánto más complejo es el programa, menos código acabo poniendo en el Main ;D
Porque prefiero "modularlo" en distintos archivos  .java.

Así es más fácil de desarrollar, comprobar y mantener el programa.
Si detecto un fallo en un panel en concreto, me voy a su archivo correspondiente a ver que está ocurriendo.
Es más cómodo ir mirando archivos sueltos de apenas un centenar de líneas, que no tener que revisar un único archivo kilométrico con miles y miles de líneas de código.

132
Aprender a programar desde cero / Re: java swing ventana gráfica
« en: 02 de Octubre 2022, 22:45 »
Sí, esa es la idea.

Por otro lado, muchas veces el programador ya es capaz de prever que una determinada tarea puede ser lenta y requerir cierto tiempo de computación, así que intentará programarla de forma que se ejecute en un hilo separado para que no interfiera con el programa principal.

En cualquier caso, la cuestión es que siempre que hagamos una aplicación con GUI Swing, mejor ejecutarla en el hilo del despachador de eventos que no en el principal.

133
Aprender a programar desde cero / Re: Ayuda Ejercicio Java
« en: 30 de Septiembre 2022, 01:08 »
Le he entendido bastante bien con tu explicación, muchas gracias!

Me he dado cuenta que estaba enfocando mal el problema ya que pensaba que el programa tenia que resolver la ecuación con solo introducir la estructura de esta, por así decirlo.

Muchas gracias de nuevo, un saludo!

Puff.. eso que dices se puede hacer claro, pero ya es algo bastante más avanzado.
Yo tampoco sabría bien como hacerlo...

Si tienes curiosidad, esta página web sí lo hace.

En su campo de texto escribes la ecuación, usando letras como a, b, c,... y no C2 (ya que pensará que es  c * 2), la analiza y te indica los pasos a seguir para solucionarla.

Bueno, no se si las analiza y resuelve...,  o que tiene pregrabadas las soluciones. En cualquier caso es interesante.

Un saludo.

134
Aprender a programar desde cero / Re: Ayuda Ejercicio Java
« en: 29 de Septiembre 2022, 01:39 »
Hola.

Lo primero, es asegurarnos de que sabemos resolver la ecuación mentalmente, sin Java ni nada...

Tenemos que C1x + C2 = 0
O sea, dos coeficientes (c1 y c2) y una incógnita, que es la x.

Para resolver la incógnita, hay que pasar los coeficientes al otro lado del =

El segundo coeficiente, que está sumando, pasará restando. O sea, con signo negativo.
El 0 desaparece, porque 0 no es nada...

C1x = -C2

Ahora hay que pasar el primer coeficiente, que como está multiplicando, ha de pasar dividiendo:
x = -C2 / C1

Y ya tenemos la operación que hay que hacer para despejar la x.
Hay que hacer una división negativa, de C2 entre C1.

Y eso es lo que nos dará el valor de x.
Solo hay que tener en cuenta que para que haya solución, C1 ha de ser distinto de 0.
Porque no podemos dividir un número entre 0, así que si C1 tuviera valor 0, entonces la ecuación no tendría solución.

Bien, pues todo esto, es lo que tenemos que programar en Java.

Así que, tras pedir los valores de los dos coeficientes, lo primero es comprobar con un IF si C1 tiene valor 0, en cuyo caso informamos de que no hay solución y se acabó.

Si no, si C1 es distinto de 0, entonces hacemos la división negativa y mostramos el resultado.

Para que el resultado salga con 4 decimales, podemos usar el método printf().
Esa "f" es de "formato", es decir, podemos indicar que formato queremos que tenga un determinado texto en pantalla.

Con el "comodín" %.4f podemos indicar que queremos que un valor float (o double) se muestre siempre con cifras después del punto decimal.

Bien, ha tu mismo un intento de resolverlo con los pasos que he dicho.
Olvida de momento lo de los 4 decimales si no conoces printf(), esto es lo de menos.

Cuando lo hayas hecho, compara con el código que pongo a continuación, a ver si hemos seguido la misma lógica:
Código: [Seleccionar]
public class Ecuacion {

public static void main(String[] args) {

double c1, c2, x;
Scanner teclado = new Scanner(System.in);

System.out.println("\t\tECUACION  C1x + C2 = 0");

System.out.print("\nIndique valor C1: ");
c1 = teclado.nextDouble();
System.out.print("Indique valor C2: ");
c2 = teclado.nextDouble();

if (c1 == 0)
//Si coeficiente 1 es 0, no hay solución, ya que no podemos dividir entre 0
System.out.println("\nNo hay solución");
else {
x = -c2 / c1;
System.out.printf("\nValor de x: %.4f", x);
}

System.out.println("\n\n\t\tFIN DE PROGRAMA");
teclado.close();
}

}


Cualquier duda que tengas, solo tienes que preguntar.
Un saludo.

135
Aprender a programar desde cero / Re: java swing ventana gráfica
« en: 25 de Septiembre 2022, 00:16 »
Citar
En el primer codigo, donde creas el panel principal con la toolkit veo una clase Main con el constructor Main(), una clase privada PanelPrincipal y el método main()
Aquí cuando se crea el objeto con new Main() entiendo que se crea "el marco" que es el JFrame y que sería transparente y dentro de este "el lienzo" que seria el JPanel y que sería opaco.

Sí, más o menos esa sería la explicación.
Nuestra clase Main es un JFrame, un "marco". Ahora se requiere de un "contenedor" (clase Container) que será el relleno opaco para el marco.

En este caso (hay otras formas de inicializar la propiedad "contenedor" de un JFrame), establecemos como "contenedor" un objeto que hereda de la clase JPanel, que a su vez es hija (nieta más bien) de la clase Container.
Código: [Seleccionar]
setContentPane(new PanelPrincipal());
Citar
Una primera duda es con pack(); si comento esta instrucción la ventana no se despliega sino que aparece minimizada. ¿Por que si ya se ha establecido dimensiones con setPreferredSize?

pack() autocalcula el tamaño del marco para ajustarse a los elementos y/o dimensiones que tenga el "contenedor".
Si no lo invocamos, no se calcula ningún tamaño para el marco y por eso solo aparece la barra de botones de la ventana.
Supongo que al pulsar el botón "maximizar", equivale a llamar a pack() y ahora sí aparece la interfaz.

El preferredSize se lo hemos dado al JPanel que hace de contenedor. Esta dimensión que le damos al JPanel, solo sirve si le pedimos al JFrame que calcule su propio tamaño. Y para eso invocamos a pack().

Citar
setLocationRelativeTo(null); creo que posiciona en el centro de la pantalla pero si lo comento me sale igual porque ya estamos ocupando toda la pantalla entonces entiendo que ¿aqui podriamos quitarlo sin perjuicio para el resultado?
Sí, podemos quitarlo.
Lo puse por costumbre, la verdad. Normalmente casi nunca hago ventanas que se ajusten a todo el ancho de pantalla, así que siempre pongo el setLocationRelativeTo().
Esta vez no caí en la cuenta de que no iba a ser necesario.

Citar
Otra duda es el por que declarar la clase PanelPrincipal como privada de la clase Main en lugar de hacerlo como clase independiente ¿Cual seria la ventaja?

Bueno, cuando son clases pequeñas que apenas superan las 20 líneas (PanelPrincipal es una decena de líneas) prefiero escribirlas dentro de la clase principal. No vale la pena crear un archivo .java separado para ellas.
Si fueran clases más extensas, con más elementos y funcionalidades que pudieran requerir mucho código, entonces si prefiero escribirlas como clases separadas.

De todos modos, sí tenemos una pequeña ventaja al escribirlas dentro de la clase principal.
Y la ventaja es que de esta manera comparten el mismo ámbito, y además lo comparten con los atributos de la clase Main principal.
Así hay total visibilidad entre ellas y los atributos y pueden combinarse facilmente.

Por ejemplo, fíjate en la clase PanelCampoTexto
Esta clase utiliza el objeto "campoTexto"
Citar
   
   private class PanelCampoTexto extends JPanel {
      
      public PanelCampoTexto() {
         campoTexto = new JTextArea();
         campoTexto.setFont(new Font("Verdana", Font.PLAIN, 44));
         setLayout(new GridLayout(1,1));
         JScrollPane scroll = new JScrollPane(campoTexto);
         add(scroll);
      }
   }

Pero este objeto, en realidad es un atributo de la clase Main:
Citar
public class Main extends JFrame {
   
   private JTextArea campoTexto;
   private JLabel etMensajes;
   private JButton btProcesar;
   private JButton btBorrar;
   

Como la clase PanelCampoTexto está declarada DENTRO de la clase Main, y lo mismo pasa con el atributo campoTexto, estos dos elementos son visibles entre ellos y por eso la clase PanelCampoTexto puede usarlo sin problemas.

Si esta clase la hubiéramos escrito como una clase separada, entonces estaría FUERA de la clase Main.
Cada clase tendría su propio ámbito individual y entonces PanelCampoTexto no podría usar los atributos de Main, porque no podría verlos.

En ese caso, tendríamos que declarar el JTextArea llamado campoTexto dentro de la clase PanelCampoTexto.
Pero entonces el botón "Borrar" no podría ver ese campo de texto para borrarlo.
Así que además a la clase PanelCampoTexto habría que darle también un método public que se encargue de borrar, método que ya sí podría ver el botón "Borrar" e invocarlo.


O bien, hacer que el  JTextArea de la clase Main llegue hasta la clase individual PanelCampoTexto mediante el constructor, o con un método set, algo como:
Código: [Seleccionar]
public void setCampoTexto(JTextArea campoDelMain) {
    campoTexto = campoDelMain;
}

Como ves, si se escriben por separado ya no comparten ámbito y hay que usar un poco más de código para hacer que las clases y elementos se comuniquen entre ellas.

Así que si son clases pequeñas, no pasa nada por escribirlas juntas dentro de la clase principal, y además se facilitan las cosas al compartir el mismo ámbito.

Pero si fuera un programa más grande y complejo, donde cada panel es tan complicado o más que este programa completo, entonces mejor escribirlas por separado. Aunque luego haya que andar pasando referencias por constructores o por setters para establecer comunicaciones entre las distintas clases.


Sobre esto:
Código: [Seleccionar]
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Main();
}
});
En programas sencillos como este, el 99% de las veces va funcionar igual si simplemente hacemos un new Main()
Código: [Seleccionar]
public static void main(String[] args) {
new Main();
}

Pero en programas Swing que sean un poco más complejos, pueden surgir problemas si no lo hacemos de la otra forma.

Todos los eventos Swing: eventos de ratón, de teclado, repintado de ventanas, etc... son gestionados por un hilo de ejecución (thread) separado que se llama EDT o Event dispatch Thread, o sea, el "despachador de eventos".

El problema es que el "hilo de ejecución principal" digamos que tiene preferencia sobre el EDT, el hilo de Swing.
Entonces, si en un momento dado ejecutamos una tarea que requiere de unos segundos, por ejemplo hacer una consulta a una base de datos que es muy grande, el hilo principal se mantendrá ocupado realizando esta tarea y el EDT no podrá hacer nada. Así que veremos cómo la interfaz se queda congelada durante unos segundos, sin responder ni el teclado, ni el ratón ni cualquier animación en la ventana.

Para evitar esto, con invokeLater() le estamos pidiendo que todos los procesos de la aplicación se ejecuten en el EDT. Así este hilo no se ve supeditado al principal y él solito ya se encarga de repartir los recursos para que los procesos de computación no afecten a los eventos de la interfaz.

Como digo, para programas sencillos nos va a dar igual ponerlo de una forma o de otra.
Pero aún así no está de más acostumbrarnos a ponerlo siempre

136
Ok, pues hagamos una interfaz completa.

Podemos comenzar preguntando con un JOptionPane cuántos alumnos se van a ingresar, igual que hemos hecho en el programa anterior.


Solo que esta vez no vamos a hacer ningún bucle, ya que con una interfaz gráfica no podemos usar un bucle como hicimos en las dos versiones anteriores.

Lo que haremos será mostrar tres campos de texto para las tres notas y un botón para aceptar y computar esas notas.



Al computar las notas, calcularemos y mostraremos el promedio de ese alumno en un área de texto que servirá como si fuera un listado, ya que para cada alumno se agregará una línea a esa lista.



Cada vez que computamos notas, aumentaremos un contador y cuando alcance el mismo valor que la cantidad de alumnos escogida, entonces desactivaremos los campos de texto para que el usuario sepa que ha terminado la inserción y mostraremos en otro campo de texto, el promedio total de todas los promedios calculados de los alumnos.



Y ahí terminaría el programa

Para construir esa interfaz, que es muy sencilla, lo que hago es usar un BorderLayout que nos permite dividir el marco JFrame en 5 zonas: norte, sur, este, oeste y centro.

De esas 5 zonas, solo voy a usar 4, donde colocaré distintos JPanel, cada uno escritos como una clase.
Así en lugar de dar forma a una interfaz completa de una sola vez, puedo hacerlo escribiendo códigos más pequeños para cada zona.
Así cada zona podrá tener sus propios layouts, según nos convenga.

Este sería el código. Parecen muchas líneas, pero es fácil de leer. Ya verás que cada una de las 4 zonas que componen toda la ventana, están escritas como clases individuales.
Así que para entender como se ha hecho el área de texto, o los campos de texto con el botón, no hay que leer el código entero. Solo la parte que corresponde a su clase.

La acción del botón también está escrito como una clase individual, que es donde ocurre lo interesante. Ahí se capturan los datos introducidos, se comprueba que son datos válidos, se computan, se actualizan contadores y acumuladores, etc...

Espero que te sirva. Pregunta lo que no entiendas o lo que creas que debería ser distinto.
Un saludo.

Código: [Seleccionar]
package promedioAlumnos;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class PromedioSwing extends JFrame {

private int na, contador;
private double sumaPromedios;
//Componentes
private JLabel etiqNorte;
private JTextField notaExFin, notaExPar, notaTrabFinal, promedFinal;
private JTextArea promedAlumnos;
private JButton btComputar;
//Paneles
private PanelNorte pnNorte;
private PanelCentral pnCentro;
private PanelSur pnSur;
private PanelEste pnEste;

public PromedioSwing() {

na = Integer.parseInt(
JOptionPane.showInputDialog(this, "¿Cuántos alumnos va a introducir?",
"Cantidad Alumnos", JOptionPane.QUESTION_MESSAGE));
sumaPromedios = 0;
contador = 0;

iniciarComponentes();

pnNorte = new PanelNorte();
pnCentro = new PanelCentral();
pnSur = new PanelSur();
pnEste = new PanelEste();
setLayout(new BorderLayout());
add(pnNorte, BorderLayout.NORTH);
add(pnCentro, BorderLayout.CENTER);
add(pnSur, BorderLayout.SOUTH);
add(pnEste, BorderLayout.EAST);

setTitle("Promedios Alumnos");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}

private void iniciarComponentes() {
etiqNorte = new JLabel();
notaExFin = new JTextField(5);
notaExPar = new JTextField(5);
notaTrabFinal = new JTextField(5);
promedFinal = new JTextField(5);
promedFinal.setHorizontalAlignment(JTextField.CENTER);
promedFinal.setEditable(false);
promedAlumnos = new JTextArea(8,5);
promedAlumnos.setEditable(false);
btComputar = new JButton("Computar");
btComputar.addActionListener(new AccionComputar());
}

//Clases para modelar paneles
private class PanelNorte extends JPanel {

public PanelNorte() {

etiqNorte.setForeground(Color.BLUE);
etiqNorte.setFont(new Font("Arial", Font.BOLD, 30));
add(etiqNorte);
actualizaContador();
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(15, 25, 10, 25),
BorderFactory.createLoweredSoftBevelBorder()));

}
public void actualizaContador() {
contador++;
etiqNorte.setText("NOTAS DE ALUMNO #" + contador + "/" + na);
}
}

private class PanelCentral extends JPanel {
public PanelCentral() {

JPanel panelesNotas = new JPanel();
panelesNotas.setLayout(new GridLayout(1,3,10,0));
panelesNotas.add(new PanelNota(new JLabel("Nota Examen Final:"), notaExFin));
panelesNotas.add(new PanelNota(new JLabel("Nota Examen Parcial:"), notaExPar));
panelesNotas.add(new PanelNota(new JLabel("Nota Trabajo Final:"), notaTrabFinal));

JPanel pnBoton = new JPanel();
btComputar.setFont(new Font("Arial", Font.BOLD, 25));
pnBoton.add(btComputar);

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(panelesNotas);
add(pnBoton);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(25, 25, 25, 25),
BorderFactory.createRaisedSoftBevelBorder()));
}

public void limpiarCampos() {
notaExFin.setText(null);
notaExPar.setText(null);
notaTrabFinal.setText(null);
}
}

private class PanelSur extends JPanel {
public PanelSur() {
JLabel etiq = new JLabel("Promedio Total Alumnos:");
etiq.setFont(new Font("Arial", Font.PLAIN, 25));
add(etiq);

promedFinal.setFont(new Font("Arial", Font.BOLD, 25));
promedFinal.setForeground(Color.BLUE);
add(promedFinal);

setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(10,25,15,25),
BorderFactory.createRaisedSoftBevelBorder()));
}
}

private class PanelEste extends JPanel {
public PanelEste() {

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(new JLabel("Promedios Alumnos"));
JScrollPane scroll = new JScrollPane(promedAlumnos);
add(scroll);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(10, 10, 25, 25),
BorderFactory.createLoweredSoftBevelBorder()),
BorderFactory.createEmptyBorder(10, 10, 10, 10)
));
}
}

private class PanelNota extends JPanel {
public PanelNota(JLabel texto, JTextField campo) {
add(texto);
add(campo);
}
}


//Clase Listener
private class AccionComputar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String nota1 = notaExFin.getText();
String nota2 = notaExPar.getText();
String nota3 = notaTrabFinal.getText();

if (nota1.isBlank() || nota2.isBlank() || nota3.isBlank())
JOptionPane.showMessageDialog(null, "Ha de completar los tres campos",
"Computar notas", JOptionPane.WARNING_MESSAGE);
else {
try {
//Parseamos notas
double valor1 = Double.parseDouble(nota1);
double valor2 = Double.parseDouble(nota2);
double valor3 = Double.parseDouble(nota3);
//Calculamos promedio
double promedio = (((valor1*0.55)+(valor2*0.3)+(valor3*0.15)));
//Acumulamos para luego scar promedio final
sumaPromedios += promedio;
//Actualizamos lista de promedios
promedAlumnos.append(String.format("Alumno #%d: %.2f\n", contador, promedio));
//Limpiamos campos
pnCentro.limpiarCampos();
//Comprobamos si hemos terminado
if (contador == na) { //Hemos terminado
//Desactivamos interfaz
btComputar.setEnabled(false);
notaExFin.setEnabled(false);
notaExPar.setEnabled(false);
notaTrabFinal.setEnabled(false);
//Calculamos promedio final y mostramos
double promFin = sumaPromedios / na;
promedFinal.setText(String.format("%.2f", promFin));
//Anunciamos fin de proceso
JOptionPane.showMessageDialog(null, "Fin de inserción de datos",
"Fin", JOptionPane.INFORMATION_MESSAGE);
}
else //No hemos terminado
pnNorte.actualizaContador(); //Pasamos al siguiente alumno
}
catch(NumberFormatException ex) {
JOptionPane.showMessageDialog(null, "Introduzca solo valores numéricos",
"Computar notas", JOptionPane.WARNING_MESSAGE);
}
}

}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new PromedioSwing();
}
});
}
}

137
Vale, para poder calcular el promedio final de TODOS los alumnos, has de ir acumulando el promedio de cada alumno en la variable promediofinal.
Para ya luego al final, dividir por el total de alumnos y obtener el promedio.

Y la variable na donde preguntamos el "número de alumnos", es más correcta declararla como int y no como double.
Citar
   public static void main(String[] args) {
       
      Scanner teclado=new Scanner(System.in);
      int na;
        double nota1, nota2, nota3, promedio = 0, promediofinal = 0;
       
        System.out.println("Ingrese el numero de alumnos: ");
        na=teclado.nextInt();
       
        for (int i=0; i<na;i++)
        {
            System.out.println("Ingrese la nota del Examen Final del Alumno " + (i+1) +":");
            nota1=teclado.nextInt();
            System.out.println("Ingrese la nota del Examen Parcial del Alumno " + (i+1) +":");
            nota2=teclado.nextInt();
            System.out.println("Ingrese la nota del Trabajo Final del Alumno " + (i+1) +":");
            nota3=teclado.nextInt();
           
            promedio= (((nota1*0.55)+(nota2*0.3)+(nota3*0.15)));
           
            System.out.println("Su promedio final es : "+promedio);
            //Acumulamos promedios
            promediofinal += promedio;

        }
     
        System.out.println("El promedio de los: "+na+" alumnos es: "+ promediofinal/na);

   }

Bien, con esto queda solucionada la lógica del programa.
Sobre la interfaz gráfica, sigo sin saber si es usando JOptionPane o bien usando una interfaz gráfica completa

JOptionPane parece más adecuado por el planteamiento que nos piden, por lo de preguntar primero cuántos alumnos se van a introducir, ya que la duración del programa dependerá de esa cantidad de alumnos.

Una interfaz gráfica "completa" requiere bastante más código y no suele usarse para ese tipo de planteamientos. Normalmente el programa dura hasta que el usuario decida cerrar la ventana de aplicación y la entrada de datos no depende de un bucle, los campos de texto están disponibles para que el usuario vaya introduciendo cuando quiera, y cuanto quiera...

Con JOptionPane la estructura del programa sigue siendo igual a cuando se hace un programa para consola, solo que ya no se usa Scanner para leer datos ni System.out.print para mostrarlos.

Se usa la clase JOptionPane, que se encarga de abrir distintas ventanas de dialogo "pop-up" según necesitemos.
Unas son para mostrar datos, como los MessageDialog.
Otras son para solicitar datos, como los InputDialog. Los datos que solicitamos, SIEMPRE los recibimos como String, aunque pidamos números.
Así que tendremos que parsearlos a Integer o a Double, según necesitemos.

Citar
import javax.swing.JOptionPane;

public class Promedios {

   public static void main(String[] args) {
       
      int na;
        double nota1, nota2, nota3, promedio = 0, promediofinal = 0;
       
        na = Integer.parseInt(JOptionPane.showInputDialog("Ingrese el numero de alumnos:"));
       
        for (int i=0; i<na;i++)
        {

            nota1=Double.parseDouble(JOptionPane.showInputDialog("Ingrese la nota del Examen Final del Alumno " + (i+1) +":"));
            nota2=Double.parseDouble(JOptionPane.showInputDialog("Ingrese la nota del Examen Parcial del Alumno " + (i+1) +":"));
            nota3=Double.parseDouble(JOptionPane.showInputDialog("Ingrese la nota del Trabajo Final del Alumno " + (i+1) +":"));

           
            promedio= (((nota1*0.55)+(nota2*0.3)+(nota3*0.15)));
           
            JOptionPane.showMessageDialog(null, "Su promedio final es : "+promedio);
            //Acumulamos promedios
            promediofinal += promedio;
        }
     
        JOptionPane.showMessageDialog(null, "El promedio de los: "+na+" alumnos es: "+ promediofinal/na);
   }
}


Creo que eso es lo que están pidiendo.

No creo que sea una interfaz gráfica completa, porque insisto en que requiere de muchos más conocimientos: clases JFrame, JPanel, JTextField, JButton, ActionListeners...
Y por supuesto nociones de programación orientada a objetos, porque la estructura del programa cambia radicalmente.... no tendría nada que ver con lo que hemos escrito hasta ahora.

138
Vale, ¿y cuál es la duda? ¿Dónde te atascas?
¿En hacer los cálculos de porcentajes? ¿En pedir datos con interfaz gráfica?

Por cierto, sobre la interfaz gráfica. Por el planteamiento del ejercicio, supongo que lo que se espera es que se pidan datos usando JOptionPane, ¿no?

No parece que quieran que se construya un marco completo desde cero, con paneles, campos de texto, botones,...

Por el planteamiento, eso de preguntar primero cuántos alumnos se van a introducir y luego pedir datos..., suena a programación lineal estructurada, solo que en lugar de pedir datos por consola se piden con JOptionPane.

Confírmanos si es usando JOptionPane, e intenta comenzar tú un código.

Si lo que se te complica es hacer los cálculos de porcentajes, pues de momento no los hagas. Haz un programa que solo pida los datos con JOptionPane pero que de momento no se computen.

Si lo que no tienes claro es lo del JOptionPane, pues de momento pide los datos por consola e intentar hacer los cálculos de porcentajes.

La cuestión es que hagas tú un intento de solucionarlo, aunque sea parcialmente. Y lo compartas por aquí para que podamos corregir, completar, aclarar dudas concretas..., lo que sea.


139
Hola Damián, bienvenido al foro.

Sobre este asunto, nada puedo aportar desde el punto de vista profesional porque no soy programador ni nada que se le parezca.
Algo he aprendido de programación por gusto y afición, e intento compartirlo con otros de la forma más sencilla posible.

Pero como no ejerzo profesionalmente, desconozco costes de licencias ni tampoco se cómo enfocan este asunto los profesionales del sector: si pagan religiosamente la licencia, si buscan alternativas "open source", si deciden seguir programando con JDK's antiguos que no están sujetos a ninguna licencia...

Sería interesante que pase por aquí alguien que si ejerza y nos pueda comentar cómo es la situación a este respecto.

He leído este artículo y me ha parecido muy interesante y clarificador.

Oracle impone licencia de pago ha partir de Java 11, pero no a las versiones anteriores, que posiblemente puedan seguir siendo igual de productivas en la mayoría de los casos.

Así mismo, la propia Oracle impulsó la versión libre OpenJDK para ponerla a la altura de la versión de pago, así ningún tipo de programador se verá impedido o perjudicado por este cambio.
El programador freelance, o grupos de pequeña escala y con pocos recursos, pueden recurrir al OpenJDK, siendo gratuito pero sin dispone del soporte de Oracle, aunque podrán apoyarse en la comunidad "open source" y otros medios.

Empresas o programadores de más alto nivel, pueden permitirse pagar los costes de licencia y obtener ventajas como soporte directo por parte de Oracle.


Por otra parte, si aún estás en proceso de aprendizaje, el tema de las licencias de Oracle debería ser la menor de tus preocupaciones.
Tu preocupación ahora debería ser aprender programación y el lenguaje Java. Este aprendizaje no te va a limitar a solo Java, y por tanto, un futuro laboral sujeto a pagar licencias.

Como tú mismo decías, ya vendrán otros lenguajes. Sabiendo Java y programación, ya luego es muy fácil ponerse a dominar otros lenguajes, pues aunque cambie la sintaxis y las instrucciones, la lógica de la programación es común en todos ellos.
Así que llegado el momento, podrás elegir otros lenguajes si realmente las licencias de Oracle resultan un obstáculo (que no lo son, pues ya hemos comentado que hay alternativas)

Un saludo.

140
No conozco el lenguaje Python.
Pero la metodología de programación es la misma sin que importe el lenguaje.

¿Estás haciéndolo usando programación orientada a objetos?
En ese caso, puedes hacer una clase "Avion", con los atributos: código vuelo, origen, destino y precio asiento.
Otro atributo sería un arreglo que represente los asientos disponibles. Puedes usar valor 0 para los asientos libres y valor 1 para los que ya están ocupados.
Así puedes evitar ofrecer dos veces el mismo asiento, porque los que tengan valor 1 estarán ocupados.

Luego ya a esta clase le añades métodos que devuelvan el valor de esos atributos, que puedan recorrer el arreglo para determinar si hay asientos libres o no, para cambiar el valor de un asiento ha "ocupado" cuando se formalice la venta del boleto,...

Intenta escribir esta clase y compartir el código que tengas hecho.
La gente que conozca Python, se animará más ayudarte si muestras un código ya empezado, en lugar de que tengan ellos que empezar uno desde cero.

Un saludo.

Páginas: 1 2 3 4 5 6 [7] 8 9 10 11 12 ... 50

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".