Mostrando entradas con la etiqueta Clases. Mostrar todas las entradas
Mostrando entradas con la etiqueta Clases. Mostrar todas las entradas

domingo, 6 de noviembre de 2011

Ejercicio "Efemérides" (base de datos)

Crear una aplicación que permita gestionar una base de datos de efemérides. Todas las operaciones se realizarán mediante consola, ya que el tema de formularios lo hemos empezado a ver después del de acceso a bases de datos.

Para empezar creamos en Access la base de datos "efemerides", que contendrá una única entidad: "efemeride", con los siguientes atributos:
  • id. De tipo entero.
  • texto. De tipo texto.
  • fecha. De tipo fecha.
Una vez creada la base de datos, implementamos el puente JDBC-ODBC y empezamos a trabajar.

Dentro de nuestro proyecto, crearemos la clase "BaseDatos" y el fichero de configuración, que como vimos en la entrada anterior nos facilitan todas las gestiones que realicemos con respecto al acceso a bases de datos.

Además, para que todo sea más realista y más sencillo de entender para el programador, crearemos la clase "Efemeride", que tendrá los atributos propios de una efeméride y, como métodos, los correspondientes "getters" y "setters".

CLASE EFEMERIDE

public class Efemeride {
 private Integer id;
 private String texto;
 private Date fecha;

 public Integer getId() {
  return id;
 }

 public void setId(Integer id) {
  this.id = id;
 }

 public String getTexto() {
  return texto;
 }

 public void setTexto(String texto) {
  this.texto = texto;
 }

 public Date getFecha() {
  return fecha;
 }

 public void setFecha(Date fecha) {
  this.fecha = fecha;
 }
}

TRUCO: una vez que has especificado todos los atributos de una clase, en Eclipse es muy sencillo generar los métodos getAtributo() y setAtributo(Dato dato). Sólo tienes que hacer clic con el botón derecho y en "Source" elegir "Generate Getters and Setters". En el cuadro de diálogo que se abre eliges los atributos de los que quieres generar estos métodos, haces clic en "OK" y ¡listo!

Para controlar las excepciones de nuestra aplicación, crearemos nuestra propia excepción. En nuestro caso esta clase fue facilitada por el profesor, así como una interfaz ("IEfemerides") que debe implementar la clase "Efemerides". Esta clase es la encargada de realizar todas las gestiones con la base de datos (insertar datos, actualizar, recuperar, etc.).

CLASE EFEMERIDEEXCEPTION

public class EfemerideException extends Exception {
 private static final long serialVersionUID = 1L;

 public EfemerideException(String mensaje) {
  super(mensaje);
 }
 
}

CLASE EFEMERIDES

public class Efemerides implements IEfemerides {

 @Override
 public void insertar(Efemeride efemeride) throws EfemerideException {
  try {
   Connection conexion = BaseDatos.getConnection();
   String sql = "insert into efemerides (texto, fecha) values (?, ?)";
   PreparedStatement insertar = conexion.prepareStatement(sql);

   insertar.setString(1, efemeride.getTexto());
   insertar.setDate(2, DateUtils.convertir(efemeride.getFecha()));

   insertar.executeUpdate();
   insertar.close();

  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido insertar la efeméride.");
  }
 }

 @Override
 public void eliminar(Integer id) throws EfemerideException {
  try {
   int eliminado;
   Connection conexion = BaseDatos.getConnection();
   String sql = "delete from efemerides where id=?";
   PreparedStatement eliminar = conexion.prepareStatement(sql);

   eliminar.setInt(1, id);

   eliminado = eliminar.executeUpdate();
   if (eliminado == 0) {
    throw new EfemerideException("La efeméride no existe.");
   }
   eliminar.close();

  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido eliminar la efeméride.");
  }
 }

 @Override
 public void actualizar(Efemeride efemeride) throws EfemerideException {
  try {
   int actualizado;
   Connection conexion = BaseDatos.getConnection();
   String sql = "update efemerides set texto=?, fecha=? where id=?";
   PreparedStatement actualizar = conexion.prepareStatement(sql);

   actualizar.setString(1, efemeride.getTexto());
   actualizar.setDate(2, DateUtils.convertir(efemeride.getFecha()));
   actualizar.setInt(3, efemeride.getId());

   actualizado=actualizar.executeUpdate();
   if (actualizado == 0) {
    throw new EfemerideException("La efeméride no existe, por lo que no se ha podido actualizar.");
   }
   actualizar.close();

  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido actualizar la efeméride.");
  }

 }

 @Override
 public Efemeride recuperar(Integer id) throws EfemerideException {
  Efemeride efemeride = new Efemeride();
  try {
   Connection conexion = BaseDatos.getConnection();
   String sql = "select * from efemerides where id=?";
   PreparedStatement recuperar = conexion.prepareStatement(sql);

   recuperar.setInt(1, id);

   ResultSet resultado = recuperar.executeQuery();
   if (!resultado.next()) {
    throw new EfemerideException("La efeméride no se ha recuperado porque no existe.");
   } else {
    efemeride.setId(id);
    efemeride.setTexto(resultado.getString("texto"));
    efemeride.setFecha(resultado.getDate("fecha"));
   }
  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido recuperar la efeméride.");
  }
  return efemeride;
 }

 @Override
 public List<Efemeride> hoy() throws EfemerideException {
  Date hoy = new Date();

  return recuperarPorFecha(hoy);
 }

 @Override
 public List<Efemeride> recuperarTodas() throws EfemerideException {
  List<Efemeride> listado = new ArrayList<Efemeride>();
  try {
   Connection conexion = BaseDatos.getConnection();
   Statement recuperar = conexion.createStatement();

   ResultSet resultado;
   resultado = recuperar.executeQuery("select * from efemerides");

   while (resultado.next()) {
    Efemeride efemeride = new Efemeride();
    efemeride.setId(resultado.getInt("id"));
    efemeride.setTexto(resultado.getString("texto"));
    efemeride.setFecha(resultado.getDate("fecha"));
    listado.add(efemeride);
   }
  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se han podido recuperar las efemérides.");
  }
  return listado;
 }

 @Override
 public List<Efemeride> recuperarPorFecha(Date fecha)
   throws EfemerideException {
  List<Efemeride> listado = new ArrayList<Efemeride>();
  try {
   Connection conexion = BaseDatos.getConnection();
   String sql = "select * from efemerides where day(fecha)=? and month(fecha)=?";
   PreparedStatement recuperar = conexion.prepareStatement(sql);

   recuperar.setInt(1, DateUtils.dia(fecha));
   recuperar.setInt(2, DateUtils.mes(fecha));

   ResultSet resultado = recuperar.executeQuery();
   while (resultado.next()) {
    Efemeride efemeride = new Efemeride();
    efemeride.setId(resultado.getInt("id"));
    efemeride.setTexto(resultado.getString("texto"));
    efemeride.setFecha(resultado.getDate("fecha"));
    listado.add(efemeride);
   }
  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se han podido recuperar las efemérides.");
  }
  return listado;
 }

}

Finalmente, la aplicación con la que interactuará el usuario se creó utilizando varias clases proporcionadas por el profesor, que permitían crear menús y recoger los datos introducidos por el usuario.

CLASE MENUEFEMERIFE

public class MenuEfemeride {

 private static Efemerides efemerides = new Efemerides();
 
 public static void main(String[] args) {

  Menu principal = new Menu("Menú principal. Efemérides");
  Menu consultar = new Menu("Consultar");
  
  Accion insertarEfemeride = new Accion("Insertar efeméride") {
   public void accion() { onInsertarEfemeride(); }
  };
  Accion eliminarEfemeride = new Accion("Eliminar efeméride") {
   public void accion() { onEliminarEfemeride(); }
  };
  Accion actualizarEfemeride = new Accion("Actualizar efeméride") {
   public void accion() { onActualizarEfemeride(); }
  };
  Accion buscarPorId = new Accion("Buscar efeméride por identificador") {
   public void accion() { onBuscarPorId(); }
  };
  Accion buscarPorFecha = new Accion("Buscar efeméride por fecha") {
   public void accion() { onBuscarPorFecha(); }
  };
  Accion efemeridesHoy = new Accion("Efemérides de hoy") {
   public void accion() { onEfemeridesHoy(); }
  };
  Accion todas = new Accion("Todas las efemérides") {
   public void accion() { onTodas(); }
  };
  
  consultar.agregar(buscarPorId);
  consultar.agregar(buscarPorFecha);
  consultar.agregar(efemeridesHoy);
  consultar.agregar(todas);
  consultar.agregar(new OpcionSalir("Volver"));
  
  principal.agregar(insertarEfemeride);
  principal.agregar(eliminarEfemeride);
  principal.agregar(actualizarEfemeride);
  principal.agregar(consultar);
  principal.agregar(new OpcionSalir("Salir"));
  
  principal.ejecutar();
  
  BaseDatos.desconectar();

 }

 protected static void onInsertarEfemeride() {

  Efemeride efemeride = new Efemeride();
  
  String texto = Entrada.leerCadena("Introduzca el texto de la efeméride");
  String fechaTexto = Entrada.leerCadena("Introduzca la fecha (dd/mm/aaaa)");
  String[] partes = fechaTexto.split("/");
  
  GregorianCalendar fecha = new GregorianCalendar(Integer.parseInt(partes[2]), (Integer.parseInt(partes[1])-1), Integer.parseInt(partes[0]));

  efemeride.setTexto(texto);
  efemeride.setFecha(fecha.getTime());
  
  try {
   efemerides.insertar(efemeride);
   System.out.println("**EFEMÉRIDE INSERTADA CON ÉXITO**");
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
  
 }
 
 protected static void onEliminarEfemeride() {

  Integer id = Entrada.leerEntero("Introduzca el identificador de la efeméride a eliminar");
  
  try {
   efemerides.eliminar(id);
   System.out.println("**EFEMÉRIDE ELIMINADA**");
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
  
 }

 protected static void onActualizarEfemeride() {

  Efemeride efemeride = new Efemeride();
  Integer id = Entrada.leerEntero("Introduzca el identificador de la efeméride a actualizar");
  try {
   Efemeride recuperada = efemerides.recuperar(id);
   System.out.println("Datos de la efeméride a actualizar:");
   System.out.println("Id: "+id+" - Texto: "+recuperada.getTexto()+" - Fecha: "+DateUtils.formatear(recuperada.getFecha()));
   
   String texto = Entrada.leerCadena("Introduzca el nuevo texto de la efeméride");
   String fechaTexto = Entrada.leerCadena("Introduzca la nueva fecha (dd/mm/aaaa)");
   
   String[] partes = fechaTexto.split("/");
   GregorianCalendar fecha = new GregorianCalendar(Integer.parseInt(partes[2]), (Integer.parseInt(partes[1])-1), Integer.parseInt(partes[0]));

   efemeride.setId(id);
   efemeride.setTexto(texto);
   efemeride.setFecha(fecha.getTime());
   
   efemerides.actualizar(efemeride);
   System.out.println("**EFEMÉRIDE ACTUALIZADA CON ÉXITO**");
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
 }
 
 protected static void onBuscarPorId() {

  Integer id = Entrada.leerEntero("Introduzca el identificador de la efeméride a buscar");
  try {
   Efemeride efemeride = efemerides.recuperar(id);
   System.out.println("DATOS DE LA EFEMÉRIDE:");
   System.out.println("Id: "+id+" - Texto: "+efemeride.getTexto()+" - Fecha: "+DateUtils.formatear(efemeride.getFecha()));
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
 }
 
 protected static void onBuscarPorFecha() {

  String fechaTexto = Entrada.leerCadena("Introduzca la fecha (dd/mm) de las efemérides a buscar");
  String[] partes = fechaTexto.split("/");
  
  GregorianCalendar fecha = new GregorianCalendar(1999, (Integer.parseInt(partes[1])-1), Integer.parseInt(partes[0]));
  
  try {
   List <Efemeride> listado = efemerides.recuperarPorFecha(fecha.getTime());
   if (listado.isEmpty()) {
    System.out.println("**NO HAY EFEMÉRIDES PARA EL DÍA ESPECIFICADO**");
   }
   else {
    System.out.println("LISTADO DE LAS EFEMÉRIDES:");
    for (Efemeride efemeride : listado) {
     System.out.println("Id: "+efemeride.getId()+" - Texto: "+efemeride.getTexto()+" - Fecha: "+DateUtils.formatear(efemeride.getFecha()));
    }
   }
   Entrada.pausa();
   
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
  
 }
 
 protected static void onEfemeridesHoy() {
  
  try {
   List <Efemeride> listado = efemerides.hoy();
   if (listado.isEmpty()) {
    System.out.println("**NO HAY EFEMÉRIDES PARA EL DÍA DE HOY**");
   }
   else {
    System.out.println("LISTADO DE LAS EFEMÉRIDES DE HOY:");
    for (Efemeride efemeride : listado) {
     System.out.println("Id: "+efemeride.getId()+" - Texto: "+DateUtils.formatear(efemeride.getFecha()));
    }
   }
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
 }
 
 protected static void onTodas() {
  try {
   List <Efemeride> listado = efemerides.recuperarTodas();
   if (listado.isEmpty()) {
    System.out.println("**NO HAY EFEMÉRIDES ALMACENADAS**");
   }
   else {
    System.out.println("LISTADO DE TODAS LAS EFEMÉRIDES:");
    for (Efemeride efemeride : listado) {
     System.out.println("Id: "+efemeride.getId()+" - Texto: "+efemeride.getTexto()+" - Fecha: "+DateUtils.formatear(efemeride.getFecha()));
    }
   }
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }  
 }

}

También se creó una clase con utilidades para trabajar con las fechas, debido a que nos veíamos en la obligación de utilizar por una parte la clase java.util.Date y por otra java.sql.Date. Esta clase, como la clase "BaseDatos", se puede reutilizar cada vez que tengamos que trabajar con fechas en el acceso a bases de datos.

CLASE DATEUTILS

public class DateUtils {
 
 public static java.util.Date crearFecha(int dia, int mes, int anyo) {
  GregorianCalendar calendario = new GregorianCalendar(anyo, mes-1, dia);
  return calendario.getTime();
 }
 
 public static java.sql.Date convertir(java.util.Date fecha) {
  return new java.sql.Date(fecha.getTime());
 }
 
 public static int dia(java.util.Date fecha) {
  GregorianCalendar calendario = new GregorianCalendar();
  calendario.setTime(fecha);
  
  return calendario.get(Calendar.DAY_OF_MONTH);
 }
 
 public static int mes(java.util.Date fecha) {
  GregorianCalendar calendario = new GregorianCalendar();
  calendario.setTime(fecha);
  
  return calendario.get(Calendar.MONTH)+1;
 }
 
 public static int anyo(java.util.Date fecha) {
  GregorianCalendar calendario = new GregorianCalendar();
  calendario.setTime(fecha);
  
  return calendario.get(Calendar.YEAR);
 }
 
 public static String formatear(java.util.Date fecha) {
  SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
  return formatter.format(fecha);
 }

}

viernes, 9 de septiembre de 2011

Ejercicio "Figuras geométricas"

Este ejercicio lo realizamos a lo largo de varias semanas, añadiendo funciones, creando clases nuevas y realizando algunos ejercicios con las figuras que se añadirán en entradas posteriores.

Dada la clase abstracta* "Figura", añadirle varias funciones de desplazamiento, una función que permita consultar su posición y dos funciones que permitan modificar directamente las coordenadas.

public abstract class Figura implements Serializable {
    protected  Point posicion;
    public Figura(int a, int b) {
    posicion= new Point(a,b);}
    public abstract float area();
    public abstract float perimetro();
    public abstract int alto();
    public abstract int ancho();
    public abstract void dibujar(Graphics g);
    public abstract void guardar(OutputStream out) throws IOException;
    public abstract void cargar(InputStream in) throws IOException;
    public void arr(int incremento){
        this.posicion.y -= incremento;
    }
    public void abj(int incremento){
        this.posicion.y += incremento;
    }
    public void izq(int incremento){
        this.posicion.x -= incremento;
    }
    public void der(int incremento){
        this.posicion.x += incremento;
    }
    public Point posicion(){
        Point aux = new Point(posicion);
        return aux;
    }
    public void set_y(int pos_y){
        this.posicion.y = pos_y;
    }
    public void set_x(int pos_x){
        this.posicion.x = pos_x;
    }
}

Crear la clase (excepción) "FiguraFormatException", que hereda de "IllegalArgumentException" y se lanzará si en la función Cargar, se lee del flujo una figura que no es la indicada.

public class FiguraFormatException extends IllegalArgumentException{
    public FiguraFormatException() {
    }
    public FiguraFormatException(String string) {
        super(string);
    }
}

Dadas las clases "Triangulo", "Elipse", "Circulo", "Rectangulo" y "Cuadrado", que heredan de la clase abstracta "Figura", añadir un constructor que reciba un InputStream, que tendrá los datos adecuados para inicializar la figura. Además, se sobreescribirán las funciones abstractas de la clase "Figura".

CLASE Triangulo

public class Triangulo extends Figura {
    protected int lado1, lado2, lado3;
    private int lx, altura;
    public Triangulo(int a, int b, int c, int d, int e) {
        super(a, b);
        int elMayor = (c > d & c > e) ? c : ((d > e) ? d : e);
        if (elMayor >= (c + d + e - elMayor)) {
            throw new IllegalArgumentException("Los lados del triangulo son imposibles");
        }
        lado1 = c;
        lado2 = d;
        lado3 = e;
        lx = (lado2 * lado2 - lado3 * lado3 - lado1 * lado1) / (2 * lado1);
        altura = (int) Math.sqrt(lado3 * lado3 - lx * lx);
    }
    public Triangulo(InputStream in) throws IOException {
        super(0, 0);
        cargar(in);
    }
    public void guardar(OutputStream out) throws IOException {
        DataOutputStream escribir = new DataOutputStream(out);
        escribir.writeUTF("figuras.Triangulo");
        escribir.writeInt(posicion.x);
        escribir.writeInt(posicion.y);
        escribir.writeInt(lado1);
        escribir.writeInt(lado2);
        escribir.writeInt(lado3);
        escribir.flush();
    }
    public void cargar(InputStream in) throws IOException {
        DataInputStream leer = new DataInputStream(in);
        String figura;
        figura = leer.readUTF();
        if (!figura.equals("figuras.Triangulo")) {
            throw new FiguraFormatException();
        }
        posicion.x = leer.readInt();
        posicion.y = leer.readInt();
        lado1 = leer.readInt();
        lado2 = leer.readInt();
        lado3 = leer.readInt();
        lx = (lado2 * lado2 - lado3 * lado3 - lado1 * lado1) / (2 * lado1);
        altura = (int) Math.sqrt(lado3 * lado3 - lx * lx);
    }
    public float area() {
        return (lado1 * altura) / 2;
    }
    public float perimetro() {
        return lado1 + lado2 + lado3;
    }
    public int alto() {
        return altura;
    }
    public int ancho() {
        return lado1;
    }
    public void dibujar(Graphics g) {
        Color cActual = g.getColor();
        int[] xPuntos = {posicion.x,
            posicion.x + lado1,
            posicion.x + lado1 + lx};
        int[] yPuntos = {posicion.y,
            posicion.y,
            posicion.y + altura};
        g.fillPolygon(xPuntos, yPuntos, 3);
        g.setColor(Color.white);
        g.drawPolygon(xPuntos, yPuntos, 3);
        g.setColor(cActual);
    }
}

CLASE Elipse

public class Elipse extends Figura {
    public final static float PI = 3.1415F;
    protected int dMenor, dMayor;
    public Elipse(int a, int b, int c, int d) {
        super(a, b);
        dMenor = c;
        dMayor = d;
    }
    public Elipse(InputStream in) throws IOException {
        super(0, 0);
        this.cargar(in);
    }
    public void guardar(OutputStream out) throws IOException {
        DataOutputStream escribir = new DataOutputStream(out);
        escribir.writeUTF("figuras.Elipse");
        escribir.writeInt(posicion.x);
        escribir.writeInt(posicion.y);
        escribir.writeInt(dMenor);
        escribir.writeInt(dMayor);
        escribir.flush();
    }
    public void cargar(InputStream in) throws IOException {
        DataInputStream leer = new DataInputStream(in);
        if (!leer.readUTF().equals("figuras.Elipse")) {
            throw new FiguraFormatException();
        }
        posicion.x = leer.readInt();
        posicion.y = leer.readInt();
        dMenor = leer.readInt();
        dMayor = leer.readInt();
    }
    public float area() {
        return PI * dMenor * dMayor;
    }
    public float perimetro() {
        return PI * (dMenor + dMayor);
    }
    public int alto() {
        return dMayor;
    }
    public int ancho() {
        return dMenor;
    }
    public void dibujar(Graphics g) {
        Color cActual = g.getColor();
        g.fillOval(posicion.x, posicion.y, dMenor, dMayor);
        g.setColor(Color.white);
        g.drawOval(posicion.x, posicion.y, dMenor, dMayor);
        g.setColor(cActual);
    }
}

CLASE Circulo

public class Circulo extends Elipse {
    public Circulo(int a, int b, int d) {
        super(a, b, d, d);
    }
    public Circulo(InputStream is) throws IOException {
        super(0, 0, 0, 0);
        //Si se produce una IOException, se borrarán los datos del objeto Circulo
        cargar(is);
    }
    @Override
    public void guardar(OutputStream os) throws IOException {
        DataOutputStream dos = new DataOutputStream(os);
        dos.writeUTF("figuras.Circulo");
        dos.writeInt(posicion.x);
        dos.writeInt(posicion.y);
        dos.writeInt(dMayor);
        dos.flush();
    }
    @Override
    public void cargar(InputStream is) throws IOException {
        DataInputStream dis = new DataInputStream(is);

        if (!dis.readUTF().equals("figuras.Circulo")) {
            throw new FiguraFormatException();
        }
        posicion = new Point(dis.readInt(), dis.readInt());
        dMayor = dis.readInt();
        dMenor = dMayor;
    }
}

CLASE Rectangulo

public class Rectangulo extends Figura {
    protected int lado1, lado2;
    public Rectangulo(int a,int b,int c,int d) {
        super(a,b);
        lado1=c;
        lado2=d; }
    public Rectangulo(InputStream in) throws IOException {
        super(0,0);
        this.cargar(in);
    }
    public float area() {
        return lado1*lado2;
    }
    public float perimetro() {
        return lado1*2+lado2*2;
    }
    public int alto() {
        return lado2;
    }
    public int ancho() {
        return lado1;
    }
    public void dibujar(Graphics g) {
        Color cActual=g.getColor();
        g.fillRect(posicion.x,posicion.y,lado1,lado2);
        g.setColor(Color.white);
        g.drawRect(posicion.x,posicion.y,lado1,lado2);
        g.setColor(cActual);
    }
    public void guardar (OutputStream out) throws IOException{
        DataOutputStream dos = new DataOutputStream(out);
        dos.writeUTF("figuras.Rectangulo");
        dos.writeInt((int) super.posicion().getX());
        dos.writeInt((int) super.posicion().getY());
        dos.writeInt(lado1);
        dos.writeInt(lado2);
        dos.flush();
    }
    public void cargar (InputStream in) throws IOException{
        DataInputStream dis = new DataInputStream(in);
        if(!dis.readUTF().equals("figuras.Rectangulo")) {
            throw new FiguraFormatException("La figura no es un rectángulo.");
        }
        super.set_x(dis.readInt());
        super.set_y(dis.readInt());
        lado1=dis.readInt();
        lado2=dis.readInt();
    }
}

CLASE Cuadrado

public class Cuadrado extends Rectangulo {
    public Cuadrado(int a, int b, int c) {
        super(a, b, c, c);
    }
    public Cuadrado(InputStream in) throws IOException {
        super(0, 0, 0, 0);
        cargar(in);
    }
    @Override
    public void guardar(OutputStream out) throws IOException {
        DataOutputStream escribe = new DataOutputStream(out);
        escribe.writeUTF("figuras.Cuadrado");
        escribe.writeInt(posicion.x);
        escribe.writeInt(posicion.y);
        escribe.writeInt(this.alto());
        escribe.flush();
    }
    @Override
    public void cargar(InputStream in) throws IOException {
        DataInputStream lee = new DataInputStream(in);
        if (!lee.readUTF().equals("figuras.Cuadrado")) {
            throw new FiguraFormatException();
        }
        posicion.x = lee.readInt();
        posicion.y = lee.readInt();
        lado1 = lee.readInt();
        lado2 = lado1;
    }
}

Crear las clases "TEquilatero" que hereda de "Triangulo" y "Coche" que hereda de "Figura".

La clase "TEquilatero":
  • Es un triángulo con los tres lados iguales.

La clase "Coche":

  • Estará formada por dos círculos (ruedas) y un rectángulo.
  • Su posición la indicará la esquina superior izquierda.
  • Los círculos tendrán el mismo tamaño que la altura del rectángulo.
    • Si la suma de los dos diámetros es mayor a la longitud del rectángulo, entonces el diámetro será la mitad de la longitud.
CLASE TEquilatero

public class TEquilatero extends Triangulo {
    public TEquilatero(int a, int b, int c) {
        super(a, b, c, c, c);
    }
    public TEquilatero(InputStream in) throws IOException {
        super(0, 0, 0, 0, 0);
        cargar(in);
    }
    @Override
    public void cargar(InputStream into) throws IOException {
        DataInputStream di = new DataInputStream(into);
        if (!di.readUTF().equals("figuras.TEquilatero")) {
            throw new FiguraFormatException();
        }
        posicion.x = di.readInt();
        posicion.y = di.readInt();
        lado1 = di.readInt();
    }
    @Override
    public void guardar(OutputStream o) throws IOException {
        DataOutputStream out = new DataOutputStream(o);
        out.writeUTF("figuras.TEquilatero");
        out.writeInt(posicion.x);
        out.writeInt(posicion.y);
        out.writeInt(lado1);
        out.flush();
    }
}

CLASE Coche

public class Coche extends Figura {
    private Rectangulo chasis;
    private Circulo rueda1, rueda2;
    public Coche(int a, int b, int alto, int ancho) {
        super(a, b);
        if (alto <= ancho) {
            chasis = new Rectangulo(a, b, ancho, alto / 2);
            rueda1 = new Circulo(a, b + chasis.alto(), alto / 2);
            rueda2 = new Circulo(a + ancho - alto / 2, b + chasis.alto(), alto / 2);
        } else {
            chasis = new Rectangulo(a, b, ancho, alto - (ancho / 2));
            rueda1 = new Circulo(a, b + chasis.alto(), ancho / 2);
            rueda2 = new Circulo(a + ancho / 2, b + chasis.alto(), ancho / 2);
        }
    }
    public Coche(InputStream in)throws IOException{
        super(0,0);
        this.cargar(in);
    }
    @Override
    public float area() {
        return chasis.area() + rueda1.area() + rueda2.area();
    }
    @Override
    public float perimetro() {
        return chasis.perimetro() + rueda1.perimetro() + rueda2.perimetro();
    }
    @Override
    public int alto() {
        return chasis.alto() + rueda1.alto();
    }
    @Override
    public int ancho() {
        return chasis.ancho();
    }
    @Override
    public void dibujar(Graphics g) {
        chasis.dibujar(g);
        rueda1.dibujar(g);
        rueda2.dibujar(g);
    }
    @Override
    public void arr(int incremento) {
        super.arr(incremento);
        chasis.arr(incremento);
        rueda1.arr(incremento);
        rueda2.arr(incremento);
    }
    @Override
    public void abj(int incremento) {
        super.abj(incremento);
        chasis.abj(incremento);
        rueda1.abj(incremento);
        rueda2.abj(incremento);
    }
    @Override
    public void izq(int incremento) {
        super.izq(incremento);
        chasis.izq(incremento);
        rueda1.izq(incremento);
        rueda2.izq(incremento);
    }
    @Override
    public void der(int incremento) {
        super.der(incremento);
        chasis.der(incremento);
        rueda1.der(incremento);
        rueda2.der(incremento);
    }
    @Override
    public void set_y(int pos_y) {
        super.set_y(pos_y);
        chasis.set_y(pos_y);
        rueda1.set_y(pos_y + chasis.alto());
        rueda2.set_y(pos_y + chasis.alto());
    }
    @Override
    public void set_x(int pos_x) {
        super.set_x(pos_x);
        chasis.set_x(pos_x);
        rueda1.set_x(pos_x);
        rueda2.set_x(pos_x + chasis.ancho() - rueda2.ancho());
    }
    public void guardar(OutputStream out) throws IOException {
        DataOutputStream escribe = new DataOutputStream(out);
        escribe.writeUTF("figuras.Coche");
        escribe.writeInt(posicion.x);
        escribe.writeInt(posicion.y);
        escribe.flush();
        rueda1.guardar(out);
        rueda2.guardar(out);
        chasis.guardar(out);

    }
    public void cargar(InputStream in) throws IOException {
        DataInputStream leer = new DataInputStream(in);
        String clase;
        if (!(clase=leer.readUTF()).equals("figuras.Coche")) {
            throw new FiguraFormatException("La figura no es un coche. Se ha leído: "+clase);
        }
        posicion.x = (leer.readInt());
        posicion.y = (leer.readInt());
        rueda1 = new Circulo(in);
        rueda2 = new Circulo(in);
        chasis = new Rectangulo(in);
    }
}

* Una clase será abstracta cuando no queremos que se puedan crear objetos de esa clase. Sus funciones pueden ser abstractas, en este caso, las clases que hereden de una abstracta pueden sobreescribir esas funciones o dejarla abstracta (la clase hija será también abstracta). Una clase abstracta también puede tener funciones no abstractas, es decir, que tengan código.

lunes, 29 de agosto de 2011

Ejercicio "Conjunto"

Crear la clase Conjunto<T>, que implementará la interfaz Set<T>. No se pondrá código a todas las funciones de Set<T>, tan sólo aquellas que nos interesan de momento.
Para almacenar todos los objetos que forman parte del conjunto, se empleará un ArrayList. Además, se creará la clase privada ParaRecorrerMiConjunto, alojada dentro de la clase Conjunto<T>, que implementa Iterator<T> y nos permite recorrer todos los elementos que forman parte del conjunto.

public class Conjunto<T> implements Set<T> {
    private ArrayList<T> datos;
    private class ParaRecorrerMiConjunto implements Iterator<T> {
        private int actual = -1;
        public boolean hasNext() {
            return actual < datos.size() - 1;
        }
        public T next() {
            if (!hasNext()) {
                throw new java.util.NoSuchElementException();
            }
            actual++;
            return datos.get(actual);
        }
        public void remove() {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }
    public Conjunto() {
        datos = new ArrayList<T>();
    }
    public void clear() {
        datos.clear();
    }
    @SuppressWarnings("element-type-mismatch")
    public boolean contains(Object o) {
        return datos.contains(o);
    }
    public int size() {
        return datos.size();
    }
    public boolean isEmpty() {
        return datos.isEmpty();
    }
    public boolean add(T e) {
        if (!datos.contains(e)) {
            return datos.add(e);
        }
        return false;
    }
    @SuppressWarnings("element-type-mismatch")
    public boolean remove(Object o) {
        return datos.remove(o);
    }
    @Override
    public String toString() {
        return datos.toString();
    }
    @Override
    public boolean equals(Object o) throws ClassCastException {
        Conjunto<T> aux = (Conjunto<T>) o;
        return this.datos.containsAll(aux.datos) & aux.datos.containsAll(this.datos);
    }
    public Iterator<T> iterator() {
        return new ParaRecorrerMiConjunto();
    }
    public Object[] toArray() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public Object[] toArray(Object[] a) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean containsAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean addAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean retainAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean removeAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

MODIFICACIÓN
Para que funcione realmente como un conjunto de cosas, modificaremos la clase ParaRecorrerMiConjunto, de manera que cada vez que se instancie un iterador para recorrer los elementos del conjunto, lo haga en orden aleatorio.

public class Conjunto3<T> implements Set<T> {
    private ArrayList<T> datos;
    private class ParaRecorrerMiConjunto implements Iterator<T>{
        private int actual=-1;
        private ArrayList<T> aux;
        ParaRecorrerMiConjunto(){
            aux = new ArrayList<T>(datos);
            Collections.shuffle(aux);
        }
        public boolean hasNext() {
            return !aux.isEmpty();
        }
        public T next() {
            if(!hasNext())
                throw new java.util.NoSuchElementException();
            actual++;
            return aux.get(actual);
        }
        public void remove() {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }
    public Conjunto3() {
        datos = new ArrayList<T>();
    }
    public void clear() {
        datos.clear();
    }
    @SuppressWarnings("element-type-mismatch")
    public boolean contains(Object o) {
        return datos.contains(o);
    }
    public int size() {
        return datos.size();
    }
    public boolean isEmpty() {
        return datos.isEmpty();
    }
    public boolean add(T e) {
        if (!datos.contains(e)) {
            return datos.add(e);
        }
        return false;
    }
    @SuppressWarnings("element-type-mismatch")
    public boolean remove(Object o) {
        return datos.remove(o);
    }
    @Override
    public String toString() {
        return datos.toString();
    }
    @Override
    public boolean equals(Object o) throws ClassCastException {
        Conjunto3<T> aux = (Conjunto3<T>) o;
        return this.datos.containsAll(aux.datos) & aux.datos.containsAll(this.datos);
    }
    public Iterator<T> iterator() {
        return new ParaRecorrerMiConjunto();
    }
    public Object[] toArray() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public Object[] toArray(Object[] a) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean containsAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean addAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean retainAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean removeAll(Collection c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

sábado, 27 de agosto de 2011

Ejercicio "Fracción" (modificación)

Modificar la clase Fraccion, de manera que implemente las interfaces Comparable y Reseteable, es decir, debe poner código a las funciones de esas interfaces. Como las interfaces se encuentran en otro paquete distinto a la clase Fraccion, se deben importar.
Además, se creará la excepción FraccionException, que se lanzará en el constructor de la clase Fraccion cuando el denominador sea 0.

EXCEPCIÓN: FraccionException

public class FraccionException extends ArithmeticException {
    public FraccionException(){
    }
    public FraccionException(String mensaje){
        super(mensaje);
    }
}

Las excepciones se programan normalmente con dos constructores:
  • Uno por defecto, que no recibe nada.
  • Otro que recibe un String, con el texto que queremos que se muestre si se lanza esa excepción.
Las excepciones pueden heredar de las existentes en Java, siempre que tenga sentido que así sea. Si queremos que la excepción no sea marcada, heredará de RuntimeException o de alguna de las que están dentro de ese conjunto.

CLASE: Fraccion

import interfaces.Comparable;
import interfaces.Reseteable;

public class Fraccion implements Comparable, Reseteable {
    private int numerador;
    private int denominador;
    public Fraccion(int num){
        this(num, 1);
    }
    public Fraccion(int num, int den){
        if (den == 0)
            throw new FraccionException();
        numerador = num;
        denominador = den;
    }
    public Fraccion inversa() {
        Fraccion aux;
        aux = new Fraccion(denominador, numerador);
        return aux;
    }
    public Fraccion producto(Fraccion f) {
        Fraccion resultado;
        int numRes, denRes;
        numRes = f.numerador * numerador;
        denRes = f.denominador * denominador;
        resultado = new Fraccion(numRes, denRes);
        return resultado;
    }
    @Override
    public String toString() {
        return numerador+"/"+denominador;
    }
    public Fraccion opuesta() {
        Fraccion aux;
        aux = new Fraccion(-numerador, denominador);

        return aux;
    }
    public static int mcd(int num1, int num2) {
        int aux;
        //Algoritmo de Euclides
        while (num2 != 0){
            aux = num1;
            num1 = num2;
            num2 = aux % num2;
        }
        return num1;
    }
    public static int mcm(int num1, int num2) {
        int mcm;
        int a=num1, b=num2;

        while (num1 != num2){
            if (num1>num2)
                num1 = num1-num2;
            else
                num2 = num2-num1;
        }
        mcm = a*b/num2;
        return mcm;
    }
    public Fraccion suma(Fraccion f2) {
        Fraccion resultado;
        int minimo, num;
        minimo = mcm(denominador, f2.denominador);
        num = (minimo/denominador)*numerador + (minimo/f2.denominador)*f2.numerador;
        resultado = new Fraccion(num, minimo);
        return resultado;
    }
    public boolean equals(Fraccion f2) {
        return numerador==f2.numerador & denominador==f2.denominador;
    }
    public Fraccion simplificar() {
        int divisor;
        divisor = mcd(numerador, denominador);
        numerador = numerador/divisor;
        denominador = denominador/divisor;
        return this;
    }
    public int comparadoCon(Object obj) throws ClassCastException {
        Fraccion f2 = (Fraccion) obj;
        double prim, segun;
        int res;
        prim = numerador/(double)denominador;
        segun = f2.numerador/(double)f2.denominador;
        if (prim < segun)
            res = -1;
        else if (prim > segun)
            res = 1;
        else
            res = 0;
        return res;
    }
    public void reset() {
        numerador = 0;
        denominador = 1;
    }
}

Ejercicio "Dado" (modificación)

Modificar la clase Dado, añadiéndole varias funciones estáticas que se definen a continuación:
  • String lanzamientos (Dado d, int v). Lanza el dado "d" tantas veces como se le indique y retorna un String con los resultados de las tiradas.
  • int lanzamientos (Dado d1, Dado d2). Lanza los dos dados y devuelve la suma de las tiradas.
  • Dado[] factoria (int d, int c). Construye tantos dados como se le indique en "d" y con las caras indicadas en "c". Devuelve una tabla con los dados creados.
  • String[] lanzamientos (Dado[] t). Lanza cada uno de los dados de la tabla y los guarda en una tabla de String.
  • String[] lanzamientos (Dado[], int v). Lanza cada dado de la tabla el número de veces que se indica y se guardan las tiradas de cada dado en la misma casilla de la tabla de String.
public class Dado {
    protected int caras;
    public Dado(int lados) {
        caras = lados;
    }
    public int tirarDado() {
        int aux;
        aux = (int) (Math.random()*caras+1);
        return aux;
    }
    public static String lanzamientos(Dado d, int veces){
        StringBuffer aux = new StringBuffer("");
        int i;
        for(i=0; i<veces; i++)
            aux.append(d.tirarDado());
        return aux.toString();
    }
    public static int lanzamientos(Dado d1, Dado d2){
        return d1.tirarDado()+d2.tirarDado();
    }
    public static Dado[] factoria(int cuantos, int caras){
        Dado[] caja= new Dado[cuantos];
        int i;
        for (i=0; i<caras; i++)
            caja[i]=new Dado(caras);
        return caja;
    }
    public static String[] lanzamientos(Dado[] caja){
        int i;
        String[] res= new String[caja.length];
        for (i=0; i<caja.length; i++)
            res[i]=Integer.toString(caja[i].tirarDado());
        return res;
    }
    public static String[] lanzamientos(Dado[] caja, int veces){
        int i, j;
        String[] res= new String[caja.length];
        for (i=0; i<caja.length; i++){
            res[i]=Dado.lanzamientos(caja[i], veces);
        }
        return res;
    }
}

Crear ahora la clase DadoConMemoria, que herede de la anterior.

La clase DadoConMemoria funcionará de manera similar a la clase Dado, pero tendrá un historial en el que irá almacenando todas las tiradas realizadas.
Además, esta clase tendrá dos constructores:
  1. Un constructor por defecto, que construirá un dado con 6 caras.
  2. Un constructor que recibe el número de lados que tendrá el dado.
Se añadirán un atributo para guardar el historial de tiradas y las siguientes funciones:
  • void reset(). Borra la memoria.
  • Integer[] historico(). Retorna un listado de todos los valores obtenidos, desde la última tirada a la primera.
  • Integer[] historico(int n). Retorna un listado de los últimos "n" valores obtenidos.
Además, se modificarán las funciones heredadas si se cree necesario, para que funcione como debe, es decir, para almacenar el historial.

public class DadoConMemoria extends Dado {
    private ArrayList<Integer> historico=new ArrayList<Integer>();
    public DadoConMemoria() {
        this(6);
    }
    public DadoConMemoria(int lados) {
        super(lados);
    }
    @Override
    public int tirarDado() {
        int aux;
        aux = (int) (Math.random()*caras+1);
        historico.add(0, aux);
        return aux;
    }
    public void reset() {
        historico = null;
    }
    public Integer[] historico() {
        Integer[] aux = new Integer[0];
        aux=historico.toArray(aux);
        return aux;
    }
    public Integer[] historico(int ult) {
        Integer[] aux = new Integer[0];
        aux=historico.subList(0, ult).toArray(aux);
        return aux;
    }
}

Ejercicio clase "PuntoGordo"

Dada la clase PuntoPoli:

public class PuntoPoli {
    private int x, y;
    public PuntoPoli() {
        y = x = 30;
    }
    public PuntoPoli(int px, int py) {
        x = px;
        y = py;
    }
    public float distancia() {
        System.out.println("EJECUTANDO LA FUNCION DISTANCIA DE PuntoPoli");
        return (float) Math.sqrt(x * x + y * y);
    }
    public void izq(){
        x=x-1;
    }
    public void der(){
        x=x+1;
    }
    public void arr(){
        y=y-1;
    }
    public void aba(){
        y=y+1;
    }
}

Crear la clase PuntoGordo, que heredará de la anterior. Además de las coordenadas, se debe almacenar su diámetro y se modificarán las funciones de movimiento del punto, para que en el caso del PuntoGordo, en vez de moverse de uno en uno, se muevan el tamaño del diámetro.

public class PuntoGordo extends PuntoPoli{
    private int diametro;
    public PuntoGordo(int a, int b, int c) {
        super(a, b);
        diametro = c;
    }
    @Override
    public float distancia() {
        System.out.println("EJECUTANDO LA FUNCION DISTANCIA DE PuntoGordo");
        return super.distancia() - diametro / 2.0f;
    }
    @Override
    public void izq(){
        int i;
        for (i=0; i<diametro; i++)
            super.izq();
    }
    @Override
    public void der(){
        int i;
        for (i=0; i<diametro; i++)
            super.der();
    }
    @Override
    public void arr(){
        int i;
        for (i=0; i<diametro; i++)
            super.arr();
    }
    @Override
    public void aba(){
        int i;
        for (i=0; i<diametro; i++)
            super.aba();
    }
}

Ejercicio "Pila" con ArrayList

Crear la clase PilaString, que tendrá las siguientes funciones:
  • apilar. Recibe el objeto a colocar en la pila (un String).
  • desapilar. Elimina el último objeto de la pila y lo retorna como dato.
  • vacia. Retorna un boolean indicando si la pila está o no vacía.
Para almacenar los objetos se utilizará la clase ArrayList de Java. El atributo será privado para que no se pueda acceder a él directamente.

public class PilaString {
    private ArrayList<String> pila = new ArrayList<String>();
    public void apilar(String frase) {
        pila.add(frase);
    }
    public String desapilar() {
        return pila.remove(pila.size()-1);
    }
    public boolean vacia() {
        return pila.isEmpty();
    }
}

jueves, 14 de julio de 2011

Ejercicio "Dado"

Crear la clase Dado. Al constructor se le pasará el número de caras que tendrá el dado. Además, tendrá una función tirarDado(), que devuelve un número aleatorio que debe estar entre 1 y el número de caras del dado, para que funciones como cualquier dado.

public class Dado {
    private int caras;
    public Dado(int lados) {
        caras = lados;
    }
    public int tirarDado() {
        int aux;
        aux = (int) (Math.random()*caras+1);
        return aux;
    }
}

Ejercicio "Fracción"

Crear la clase Fraccion, que tendrá los atributos y funciones necesarios para realizar las operaciones básicas que se pueden realizar con fracciones.

public class Fraccion {
    private int numerador;
    private int denominador;
    public Fraccion(int num){
        this(num, 1);
    }
    public Fraccion(int num, int den){
        if (den == 0)
            throw new RuntimeException();
        numerador = num;
        denominador = den;
    }
    public Fraccion inversa() {
        Fraccion aux;
        aux = new Fraccion(denominador, numerador);
        return aux;
    }
    public Fraccion producto(Fraccion f) {
        Fraccion resultado;
        int numRes, denRes;
        numRes = f.numerador * numerador;
        denRes = f.denominador * denominador;
        resultado = new Fraccion(numRes, denRes);
        return resultado;
    }
    @Override
    public String toString() {
        return numerador+"/"+denominador;
    }
    public Fraccion opuesta() {
        Fraccion aux;
        aux = new Fraccion(-numerador, denominador);
        return aux;
    }
    public static int mcd(int num1, int num2) {
        int aux;
        //Algoritmo de Euclides
        while (num2 != 0){
            aux = num1;
            num1 = num2;
            num2 = aux % num2;
        }
        return num1;
    }
    public static int mcm(int num1, int num2) {
        int mcm;
        int a=num1, b=num2;
        while (num1 != num2){
            if (num1>num2)
                num1 = num1-num2;
            else
                num2 = num2-num1;
        }
        mcm = a*b/num2;
        return mcm;
    }
    public Fraccion suma(Fraccion f2) {
        Fraccion resultado;
        int minimo, num;
        minimo = mcm(denominador, f2.denominador);
        num = (minimo/denominador)*numerador + (minimo/f2.denominador)*f2.numerador;
        resultado = new Fraccion(num, minimo);
        return resultado;
    }
    public boolean equals(Fraccion f2) {
        return numerador==f2.numerador & denominador==f2.denominador;
    }
    public int compareTo(Fraccion f2) {
        double prim, segun;
        int res;
        prim = (double)numerador/denominador;
        segun = (double)f2.numerador/f2.denominador;
        if (prim < segun)
            res = -1;
        else if (prim > segun)
            res = 1;
        else
            res = 0;
        return res;
    }
    public Fraccion simplificar() {
        int divisor;
        divisor = mcd(numerador, denominador);
        numerador = numerador/divisor;
        denominador = denominador/divisor;
        
        return this;
    }
}

Ejercicio "Potenciómetro"

Crear la clase Potenciómetro, que tendrá varias clases y atributos, de manera que funcione como cualquier potenciómetro, por ejemplo, como los de una vitrocerámica.

public class Potenciometro {
    private int[] valores;
    private int actual;
    public Potenciometro(int[] tabla) {
        valores = tabla;
        actual = 0;
    }
    public void apagar() {
        actual = 0;
    }
    public void subir() {
        if (actual < valores.length-1)
            actual++;
    }
    public void bajar() {
        if (actual > 1)
            actual--;
    }
    public int consultar() {
        return valores[actual];
    }
    @Override
    public String toString() {
        StringBuffer aux = new StringBuffer();
        int i;
        for (i=0; i

Ejercicio "Pasajeros al tren"

Implementar las siguientes clases: 

Pasajero que representa un pasajero del tren. Sólo se almacenará su nombre y tendrá las funciones: constructora (que lo inicializa) y getNombre() que devuelve el nombre del pasajero.

VagonPasajeros que representa un vagón de pasajeros,tendrá información sobre los pasajeros que transporta o podría transportar.
Tiene como atributo, una tabla asientos que representa los asientos del tren, de modo que cada elemento de la tabla puede estar libre u ocupada por un objeto pasajero. 
Sus métodos serán:
  • VagonPasajeros(int capacidad)
es el único constructor y recibe el número de asientos para crear la tabla que inicialmente esta vacía.
  • void subir(Pasajero pasajero)
acomoda al pasajero en el vagón, los asientos se llenan en orden según lleguen pasajeros, si no hay asientos libres debe lanzarse una excepción (RuntimeException).
  • Pasajero bajar(String nombre)
recibe el nombre del pasajero que debe apearse, lo elimina del vagón y devuelve el objeto correspondiente.

Tranvia, que tendrá información sobre los pasajeros que transporta o podría transportar en cada uno de sus vagones.
Tiene un atributo privado... una tabla vagones, de modo que cada elemento de la tabla debe contener un objeto VagonPasajeros.
Sus métodos serán:
  • Tranvia()
para construir un tranvía de cuatro vagones.
  • Tranvia(int numVagones)
para construir un tranvía con numVagones vagones
  • Pasajero bajar(String nombre, int vagon)
para eliminar al pasajero indicado, del vagón indicado y retornarlo como resultado.
Si no existe ningún pasajero con el nombre indicado, se retornará null.
nota.- los vagones se numeran desde uno en adelante.
  • int subir(Pasajero p,int vagon)
Para intentar subir al pasajero indicado, en el vagón indicado.
Si este vagón está lleno, se intentará en los siguientes.
Si no quedan más vagones detrás, se continuará intentando desde el primer vagón.
Si finalmente no se consigue subir al pasajero a ningún vagón, se lanzará una excepción RuntimeException indicando en un texto el problema.
Si el vagón solicitado no existe, se lanzará una excepción RuntimeException indicando en un texto el problema.
La función retornará el número del vagón al que haya conseguido subir al pasajero.

CLASE PASAJERO

public class Pasajero {
    private String nombre;
    Pasajero (String s){
        nombre = s;
    }
    public String getNombre(){
        return nombre;
    }
}

CLASE VAGONPASAJEROS

public class VagonPasajeros {
    private Pasajero[] asientos;
    private Nodo primero = null;
    private Nodo ultimo = null;
    private class Nodo {
        public int asiento;
        public Nodo sig;
    }
    VagonPasajeros (int capacidad){
        asientos = new Pasajero[capacidad];
        for (int i=0; i < asientos.length; i++){
            Nodo nuevo = new Nodo();
            nuevo.asiento = i;
            nuevo.sig = null;
            if (primero == null)
                primero = nuevo;
            else
                ultimo.sig = nuevo;
            ultimo = nuevo;
        }
    }
    public void subir (Pasajero pasajero){
        if (lleno()){
            throw new RuntimeException("El vagón está lleno");
        }
        asientos[primero.asiento] = pasajero;
        primero = primero.sig;
    }
    public Pasajero bajar (String nombre){
        int i=0;
        boolean encontrado = false;
        Nodo nuevo;
        Pasajero aux = null;
        while (i<asientos.length & !encontrado){
            if (asientos[i] != null && nombre.equalsIgnoreCase(asientos[i].getNombre())){
                aux = new Pasajero(asientos[i].getNombre());
                asientos[i] = null;
                nuevo = new Nodo();
                nuevo.asiento = i;
                nuevo.sig = null;
                if (primero == null)
                    primero = nuevo;
                else
                    ultimo.sig = nuevo;
                ultimo = nuevo;
                encontrado = true;
            }
            i++;
        }
        return aux;
    }
    private boolean lleno(){
        return primero == null;
    }
}

CLASE TRANVIA

public class Tranvia {
    private VagonPasajeros[] tranvia;
    Tranvia(){
        this(4);
    }
    Tranvia (int numVagones){
        tranvia = new VagonPasajeros[numVagones];
        for (int i=0; i<tranvia.length; i++){
            tranvia[i] = new VagonPasajeros(2);
        }
    }
    public int subir (Pasajero p, int vagon){
        vagon = vagon-1;
        int contador = 0;
        boolean sentado = false;
        if (vagon<0 || vagon>=tranvia.length){
            throw new RuntimeException("El vagón no existe.");
        }
        while (contador<tranvia.length & !sentado){
            try{
                sentado = true;
                tranvia[vagon].subir(p);
            }
            catch(RuntimeException e){
                sentado = false;
            }
            vagon=(vagon+1)%tranvia.length;
            contador++;
        }
        if (!sentado)
            throw new RuntimeException("El tranvía está lleno.");
        if (vagon == 0)
            vagon = tranvia.length;
        return vagon;
    }
    public Pasajero bajar (String nombre, int vagon){
        vagon = vagon-1;
        return tranvia[vagon].bajar(nombre);
    }
}

martes, 12 de julio de 2011

Ejercicio "Cola dinámica"

Crear la clase ColaFrasesDin. Se tratará de una cola dinámica, es decir, que no tendrá un tamaño fijo, sino que éste irá variando según se añadan o eliminen objetos de la cola.
Para poder realizar la cola dinámica, emplearemos un objeto Nodo, que contendrá el dato a almacenar en cada lugar de la cola y la referencia al siguiente nodo que le sigue.

public class ColaFrasesDin {
    private Nodo primero = null;
    private Nodo ultimo = null;
    private class Nodo {
        public String dato;
        public Nodo sig;
    }
    public void acolar (String frase){
        Nodo nuevo = new Nodo();
        nuevo.dato = frase;
        nuevo.sig = null;
        if (primero == null)
            primero = nuevo;
        else
            ultimo.sig = nuevo;
        ultimo = nuevo;
    }
    public String desacolar (){
        String aux;
        aux = primero.dato;
        primero = primero.sig;
        return aux;
    }
    public boolean vacia (){
        return primero == null;
    }
}

Ejercicio "Pila" y "Cola"

Crear las clases "PilaFrases" y "ColaFrases", que permitan crear, como su nombre indica, una pila y una cola, respectivamente, de String. Cada clase tendrá los atributos necesarios y las funciones que permitan trabajar con los objetos PilaFrases y ColaFrases, modificándolos o, simplemente, consultando determinados datos.

PilaFrases

public class PilaFrases {
    private String[] frases;
    private int cima;
    PilaFrases(){
        frases = new String[10];
        cima = -1;
    }
    PilaFrases(int numero){
        frases = new String[numero];
        cima = -1;
    }
    public void push (String frase){
        if (cima < frases.length){
            cima++;
            frases[cima] = frase;
        }
    }
    public String pop (){
        cima--;
        return frases[cima+1];
    }
    public boolean empty(){
        /*boolean vacia;
        if (cima == -1)
            vacia = true;
        else
            vacia = false;*/
        return cima == -1;
    }
    public boolean full(){
        /*boolean llena;
        if (cima == (frases.length-1))
            llena = true;
        else
            llena = false;*/
        return cima == (frases.length-1);
    }
}

ColaFrases

public class ColaFrases {
    private String[] tabla;
    private int primero, ultimo;
    ColaFrases(){
        this(10);
    }
    ColaFrases(int tamaño){
        tabla = new String[tamaño+1];
        primero = 0;
        ultimo = -1;
    }
    public boolean llena(){
        return sig(sig(ultimo)) == primero;
    }
    public boolean vacia(){
        return sig(ultimo) == primero;
    }
    private int sig(int actual){
        return (actual+1)%tabla.length;
    }
    public void acolar(String frase){
        if (this.llena())
            throw new IndexOutOfBoundsException("La cola está llena");
        ultimo = sig(ultimo);
        tabla[ultimo] = frase;
    }
    public String desacolar(){
        String aux;
        if (this.vacia())
            throw new IndexOutOfBoundsException("La cola está vacía");
        
        aux = tabla[primero];
        primero = sig(primero);
        return aux;
    }
}

Ejercicio crear clase "BotellaLitro"

Crear la clase BotellaLitro, con varios atributos que indican su estado y diferentes funciones que permiten modificar su estado, consultar su estado y realizar otras operaciones.

public class BotellaLitro {
    public static final float CAPACIDAD = 1.0F;
    public static final int MEDIA = 6;
    public static final int NORMAL = 12;
    public static final int EXTRA = 24;
    private boolean estaCerrada;
    private float contenido;
    public static String unidad = "litros";
    public void abrir(){
        estaCerrada = false;
    }
    public void cerrar(){
        estaCerrada = true;
    }
    public float contenido(){
        return contenido;
    }
    public boolean estaCerrada(){
        return (estaCerrada);
    }
    @Override
    public String toString(){
        String aux;
        if (!estaCerrada)
            aux="abierta";
        else
            aux="cerrada";
        return ("La botella está "+aux+" y tiene "+contenido+" "+unidad);
    }
    public void vaciar(){
        if (!estaCerrada)
            contenido = 0;
    }
    public void llenar(){
        if (!estaCerrada)
            contenido = CAPACIDAD;
    }
    public float añadir(float cantidad){
        float sobra;
        if (!estaCerrada){
            sobra = cantidad - (CAPACIDAD - contenido);
            if (sobra >=0)
                contenido = CAPACIDAD;
            else{
                sobra = 0;
                contenido = contenido + cantidad;
            }
        }
        else
            sobra = cantidad;
        return (sobra);
    }
    public float extraer(float cantidad){
        float extraido;
        if (!estaCerrada){
            if (cantidad <= contenido){
                extraido = cantidad;
                contenido = contenido - extraido;
            }
            else{
                extraido = contenido;
                contenido = 0;
            }   
        }
        else
            extraido = 0F;
        return (extraido);
    }
    public static BotellaLitro[] cajaDeBotellas(int unidades){
        BotellaLitro[] caja = new BotellaLitro[unidades];
        int i;
        if (!(unidades == MEDIA | unidades == NORMAL | unidades == EXTRA))
            caja = null;
        else
            for(i=0; i<caja.length; i++){
                caja[i] = new BotellaLitro();
                caja[i].llenar();
                caja[i].cerrar();
            }
        return (caja);
    }
    public float diferencia(BotellaLitro bot2){
        float diferencia;
        if (contenido < bot2.contenido)
            diferencia = bot2.contenido - contenido;
        else
            diferencia = contenido - bot2.contenido;
        return diferencia;
        //OTRA FORMA:
        //return Math.abs(contenido - bot2.contenido);
    }
    public boolean equals(BotellaLitro bot2){
        boolean iguales;
        if (contenido == bot2.contenido)
            iguales = true;
        else
            iguales = false;
        return iguales;
        //OTRA FORMA:
        //return contenido == bot2.contenido;
    }
    public int compareTo(BotellaLitro bot2){
        int a;
        if (contenido < bot2.contenido)
            a = -1;
        else if (contenido == bot2.contenido)
            a = 0;
        else
            a = 1;
        return a;
    }
}

jueves, 16 de junio de 2011

Ejercicio crear clase "Coordenada"

Crear la clase Coordenada que tendrá como atributos dos float para indicar la posición y un atributo estático que será la unidad de medida.
Además tendrá funciones para poder desplazarse, una función toString() y una función distancia, que recibe otro objeto Coordenada y devuelve la distancia entre las dos coordenadas.

public class Coordenada {
    public float x;
    public float y;
    public static String unidad;
    @Override
    public String toString() {
        return("("+x+" "+unidad+", "+y+" "+unidad+")");
    }
    public float distancia(){
        float dist;
        dist = (float)Math.sqrt((x*x)+(y*y));
        return(dist);
    }
    public void arr(){
        y = y+1;
    }
    public void abj(){
        y = y-1;
    }
    public void der(){
        x = x+1;
    }
    public void izq(){
        x = x-1;
    }
}

Ejercicio crear clase "Ficha"

Crear una clase llamada Ficha, con los siguientes atributos:
  • HOMBRE. De tipo char, estático y constante (público).
  • MUJER. De tipo char, estático y constante (público).
  • nombre. De tipo String (público).
  • edad. De tipo entero (público).
  • sexo. De tipo char (público).
  • dni. De tipo long (público).

public class Ficha {
    public static final char HOMBRE = 'H';
    public static final char MUJER = 'M';
    public String nombre;
    public int edad;
    public char sexo;
    public long dni; //sin letra
}

Realizar un programa para probar la clase anterior que pida los datos de varias fichas (utilizando una tabla de Ficha) al usuario. Además, el programa tendrá dos funciones estáticas:
  1. ordenar(Ficha[] f). Recibe una tabla de objetos Ficha y la ordena por edad.
  2. mostrar(Ficha f). Muestra los datos que contiene el objeto Ficha que recibe.

public class PruebaFicha {
    public static void main(String[] args) {
        Scanner entrada = new Scanner(System.in);
        Ficha[] f = new Ficha[3];
        String aux;
        int pos;
        for (pos=0; pos<f.length; pos++){
            System.out.println("FICHA "+(pos+1));
            f[pos] = new Ficha();
            System.out.print("Nombre: ");
            f[pos].nombre = entrada.nextLine();
            System.out.print("Edad: ");
            f[pos].edad = entrada.nextInt();
            System.out.print("DNI: ");
            f[pos].dni = entrada.nextLong();
            entrada.nextLine();
            System.out.print("Sexo (H/M): ");
            aux = entrada.nextLine();
            if(aux.equals("H"))
                f[pos].sexo=Ficha.HOMBRE;
            else
                f[pos].sexo=Ficha.MUJER;
        }
        ordenar(f);
        System.out.println();
        for (pos=0; pos<f.length; pos++){
            mostrar(f[pos]);
        }
    }
    public static void ordenar(Ficha[] f) {
        int ini, fin, i;
        boolean intercambio;
        Ficha aux; //no hace falta iniciarlo
        ini=0;
        fin=f.length - 1;
        intercambio = true;
        while (ini<fin & intercambio){
            intercambio=false;
            for(i=ini; i<fin; i++){
                if (f[i].edad > f[i+1].edad){
                    aux = f[i];
                    f[i] = f[i+1];
                    f[i+1] = aux;
                    intercambio = true;
                }
            }
            fin--;
            if (intercambio){
                intercambio = false;
                for(i=fin-1; i>=ini; i--){
                    if (f[i].edad > f[i+1].edad){
                        aux = f[i];
                        f[i] = f[i+1];
                        f[i+1] = aux;
                        intercambio = true;
                    }
                }
            }
            i++;
        }
    }
    public static void mostrar(Ficha f1) {
        System.out.print("Nombre: "+f1.nombre);
        System.out.println();
        System.out.print("Edad: "+f1.edad);
        System.out.println();
        System.out.print("DNI: "+f1.dni);
        System.out.println();
        if (f1.sexo == Ficha.MUJER)
            System.out.print("Sexo: MUJER");
        else
            System.out.print("Sexo: HOMBRE");
        System.out.println();
        System.out.println();
    }
}

Ejercicio crear clase "TipoTexto"

Crear una nueva clase llamada TipoTexto, cuyos atributos serán:
  • frase. Tipo String (Público).
  • numLetras. Tipo entero (Público).

public class TipoTexto {
    public String frase;
    public int numLetras;

}

Realizar un programa que cree un objeto de la clase "TipoTexto" y que le asigne una frase cualquiera a su atributo "frase". El programa tendrá una función que contará las letras de la frase y guardará ese número en el atributo "numLetras".

public class PruebaTipoTexto {
    public static void main(String[] args) {
        TipoTexto t = new TipoTexto();
        t.frase = "Pepe vive en la ciudad de La Laguna...";
        cuentaLetras(t);
        System.out.println(t.numLetras);
    }
    public static void cuentaLetras(TipoTexto text) {
        int pos, contador=0;
        for (pos=0; pos<text.frase.length(); pos++){
            if (Character.isLetter(text.frase.charAt(pos)))
                contador++;
        }
        text.numLetras = contador;
    }
}