You are on page 1of 71

lica de Chile

Pontificia Universidad Cato


Escuela de Ingeniera
n
Departamento de Ciencia de la Computacio
IIC1103 Introducci
on a la Programaci
on

Captulo 4: Clases
Resumen te
orico
Todos los objetos del mundo real comparten dos caractersticas: tienen un estado y un comportamiento.
Las bicicletas, por ejemplo, tienen un estado (el cambio actual, velocidad de pedaleo y velocidad) y un
comportamiento (pasar un cambio, cambiar velocidad de pedaleo y aplicar frenos). Identificar el estado
y comportamiento de objetos del mundo real es el primer paso para empezar a pensar en terminos de
programaci
on orientada a objetos.
Los objetos de software son conceptualmente similares a los objetos del mundo real: ellos tambi
en tienen
un estado y un comportamiento. Un objeto guarda su estado en variables y expone su comportamiento en
metodos. Los metodos operan en el estado interno de un objeto (sus variables) y sirven como mecanismo
primario para comunicaci
on entre objetos.
Al atribuirles estado (velocidad, cambio actual, tama
no, etc.) y proveer metodos para cambiar este estado,
el objeto se mantiene en control de c
omo el mundo puede usarlo. Por ejemplo, si la bicicleta tiene s
olo 6
cambios, un metodo que cambio los cambios, podra solo aceptar cambios entre 1 y 6 y rechazar los que
estan fuera de ese rango.

Para definir un objeto necesitamos identificar ambas caractersticas. Estas


varan en complejidad de objeto
a objeto. Por ejemplo: consideremos el objeto Auto, tiene dos estados: estacionado y en movimiento, esto
implica que puede realizar las siguientes acciones: encender, y frenar, entre otras. Adem
as podemos agregarle
algunas caractersticas para distinguirlo, como color y patente.

IIC1103 Captulo 4: Clases

Los objetos pueden estar relacionados e interactuar entre ellos, permitiendo as una programaci
on m
as real.
Tambien, podemos crear m
as de un objeto del mismo tipo y utilizarlos (cada uno por separado, modificando
uno sin afectar al otro) sin necesitar saber exactamente como esta definido internamente del c
odigo.

Y la forma concreta de realizarlo? este objeto que hemos creado, debe implementarse en una nueva clase
que NO CONTIENE MAIN.
La clase se define de la siguiente manera:
import IIC1103Packag e .*; // Los paquetes necesarios , puede no haber ninguno
public class Objeto {
// Atributos de la clase
public Objeto (){ // Constructor de la clase
// Inicializac io n de atributos
}
// Metodos de la clase Objeto
}

Aplic
andolo al ejemplo anterior obtendremos algo as como:
public class Auto {
private int color ;
private String patente ;
private boolean andando ;
public Auto () // C o n s t r u c t o r de la clase {
color =1; // Sea 1 un color predeterminado , por ejemplo blanco
patente = Usuario . texto ( " Ingrese la patente de la forma NN -1234 " );
andando = false ; // Su estado inicial es reposo por defecto
}
public void pintar ( int n u e v o _ c o l o r){ // C a m b i a m o s el atributo color
color = n u e v o _ c o l o r;
}
public void mover (){ // C a m b i a m o s el atributo del estado m o v i m i e n t o
andando = true ;
}
public String m o s t r a r D a t o s(){
String texto = " El color es : " + color + " Patente : " + patente ;
return texto ;
}
}

IIC1103 Captulo 4: Clases

Luego en la clase main necesitamos crear el objeto auto para usarlo. Para crearlo lo hacemos de la siguiente
manera:
<tipo obj> <nombre obj> = new <tipo obj> (<par
ametros del constructor>);
Para usar los metodos de la clase auto necesitamos llamarlos por medio de un objeto de esa clase, por ejemplo:
<nombre objeto>.<m
etodos>(<par
ametros del m
etodo>);
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l{
public static void main ( String [] args ){
Auto autito = new Auto ();
int color = Usuario . entero ( " 1 Blanco \ n2 Azul \ n3 Rojo \ n 4 Verde " );
autito . pintar ( color );
autito . mover ();
Usuario . Mensaje ( autito . m o s t r a r D a t o s ());
}
}

El juntar el c
odigo dentro de objetos provee un n
umero de beneficios:
Modularidad: el c
odigo de un objeto puede ser mantenido independientemente de el c
odigo de otros
objetos. En otras palabras si cambia la forma en que se pasan los cambios en nuestra bicicleta eso no
va a afectar a programas que ocupan nuestro objeto.
Reutilizar c
odigo: si un objeto ya existe, se puede ocupar en otro programa sin necesidad de saber
exactamente como funciona internamente.
F
acil reparaci
on: si un objeto en particular funciona mal, se le cambia por otro sin muchos problemas.
Esto es an
alogo al mundo real donde si falla un perno en una maquina se cambia solo el perno y no la
maquina entera.

IIC1103 Captulo 4: Clases

Ejemplos
Problema 1: Reescribiendo C
odigo
Enunciado
Este codigo est
a escrito de manera sucia, para limpiarlo debe reescribir el c
odigo orientado a lenguaje de
objetos (con clases). Debe mantener la misma funcionalidad.
import i i c 1 1 0 3 P a c k a g e .*;
public class Original {
/* *
* Este codigo esta escrito de manera " sucia " , para l i m p i r a l o debe
* r e e s c r i b i r el codigo o r i e n t a d o a lenguaje de objetos ( con clases ). Debe
* mantener la misma f u n c i o n a l i d a d.
*/
public static void main ( String [] args ) {
String auto = " auto " ;
String b i c i c l e t a = " b i c i c l e t a" ;
int v e l o c i d a d A u t o = 5;
int p a s a j e r o s A u t o = 4;
boolean r u e d a P i n c h a d a A u t o = true ;
int v e l o c i d a d B i c i c l e t a = 2;
int p a s a j e r o s B i c i c l e t a = 1;
boolean r u e d a P i n c h a d a B i c i c l e t a = false ;
Usuario . mensaje ( " La v e l o c i d a d del vehiculo " + auto + " es "
+ v e l o c i d a d A u t o + " .\ nAdemas lleva " + p a s a j e r o s A u t o
+ " p a s a j e r o s" );
if ( r u e d a P i n c h a d a A u t o) {
Usuario . mensaje ( " El vehiculo " + auto + " tiene una rueda pinchada " );
}
Usuario . mensaje ( " La v e l o c i d a d del vehiculo " + b i c i c l e t a + " es "
+ v e l o c i d a d B i c i c l e t a + " .\ nAdemas lleva " + p a s a j e r o s B i c i c l e t a
+ " p a s a j e r o s" );
if ( r u e d a P i n c h a d a B i c i c l e t a) {
Usuario . mensaje ( " El vehiculo " + b i c i c l e t a
+ " tiene una rueda pinchada " );
}
}
}

Criterios de soluci
on
Se puede ver que todas las variables corresponden a una caracterstica de un auto o de una bicicleta y se
le hacen cambios a estas mismas. Se podran hacer dos objetos, uno bicicleta y uno auto, pero tambien se
puede notar que las variables relacionadas con la bicicleta y con el auto son las mismas por lo que es mas
pr
actico hacer dos objetos (por ejemplo el objeto vehculo) y crear dos instancias del mismo, una bicicleta y
un auto.

IIC1103 Captulo 4: Clases

Posible Soluci
on
// CLASE VEHICULO
import i i c 1 1 0 3 P a c k a g e .*;
public class Vehiculo {
private String nombre ;
private int v e l o c i d a d;
private int p a s a j e r o s;
private boolean r u e d a P i n c h a d a;
public Vehiculo ( String nombreAux , int velAux , int pasajAux , boolean ruedaAux ) {
nombre = n o m b r e A u x;
v e l o c i d a d = velAux ;
p a s a j e r o s = pasajAux ;
r u e d a P i n c h a d a = ruedaAux ;
Usuario . mensaje ( " Un objeto del tipo vehiculo fue creado " );
}
public int g e t V e l o c i d a d() {
return v e l o c i d a d;
}
public int g e t P a s a j e r o s() {
return p a s a j e r o s;
}
public boolean i s R u e d a P i n c h a d a() {
return r u e d a P i n c h a d a;
}
public String g e t N o m b r e() {
return nombre ;
}
}
// CLASE P R I N C I P A L
import i i c 1 1 0 3 P a c k a g e .*;
public class E n O b j e t o s {
public static void main ( String [] args ) {
// creo un objeto de tipo ( clase ) Vehiculo con el c o n s t r u c t o r definido
// en vehiculo . java
Vehiculo auto = new Vehiculo ( " auto " , 5 , 4 , true );
// creo un objeto de tipo b i c i c l e t a
Vehiculo b i c i c l e t a = new Vehiculo ( " b i c i c l e t a" , 2 , 1 , false );
// Llamo a las d i s t i n t a s v a r i a b l e s
Usuario . mensaje ( " La v e l o c i d a d del vehiculo " + auto . g e t N o m b r e()
+ " es " + auto . g e t V e l o c i d a d() + " .\ nAdemas lleva "
+ auto . g e t P a s a j e r o s() + " p a s a j e r o s" );
if ( auto . i s R u e d a P i n c h a d a ()) {
Usuario . mensaje ( " El vehiculo " + auto . g e t N o m b r e()+ " tiene una rueda pinchada " );
}
Usuario . mensaje ( " La v e l o c i d a d del vehiculo " + b i c i c l e t a. g e t N o m b r e()
+ " es " + b i c i c l e t a. g e t V e l o c i d a d() + " .\ nAdemas lleva "
+ b i c i c l e t a. g e t P a s a j e r o s() + " p a s a j e r o s" );
if ( b i c i c l e t a. i s R u e d a P i n c h a d a()) {
Usuario . mensaje ( " El vehiculo " + b i c i c l e t a. g e t N o m b r e()+ " tiene una rueda pinchada " );
}
}
// Hay que notar lo e s t r u c t u r a d o y facil de leer que quedo el programa
// despues de pasarlo a lenguaje de objetos .
}

IIC1103 Captulo 4: Clases

Problema 2: Modelando Clases


Enunciado
Modele las clases involucradas en la siguiente especificaci
on de un problema:
No considere la clase Principal que contiene el metodo main.
Deber
a declarar en java las clases que crea necesarias, as como sus atributos, metodos y constructores,
con sus respectivos parametros.
indicando su tipo y el tipo del valor de retorno.
No es necesario escribir el codigo que va dentro del metodo o constructor pero si debe comentar claramente lo que hace cada metodo.
Adem
as deber
a describir en texto c
omo interact
uan las clases de su soluci
on (puede usar una matriz o
tabla para detallar la interacci
on si lo desea).
Con el fin de ahorrar energa una empresa ha decidido construir departamentos inteligentes. Cada departamento tiene 5 sectores, una cocina, terraza, dormitorio, ba
no y sala. Cada sector cuenta con un equipo
sensor y un equipo controlador. El sensor permite detectar movimiento dentro del sector, cantidad de luz y
temperatura actuales en el sector en que se encuentra instalado. Estos datos son obtenidos del ambiente de
cada sector segundo a segundo, los valores son registrados e informados al controlador correspondiente para
que tome las medidas del caso.
El controlador tiene la capacidad de subir y bajar la temperatura, aumentar y disminuir la intensidad de
la luz as como encender y apagar luces. El controlador registra los valores ideales que los habitantes del
departamento declaran para cada sector en cuanto a temperatura (de 12 a 40 grados) y luminosidad (en
una escala discreta de 0 a 7). Cuando el controlador recibe la informaci
on del sensor, decide subir o bajar la
temperatura, o aumentar o disminuir la luz dependiendo de si los valores actuales de temperatura y luminosidad est
an por debajo o por encima de los valores ideales. Adem
as, si el controlador es informado de que
hay movimiento en su sector, debe encender las luces y apagarlas en caso contrario.

IIC1103 Captulo 4: Clases

Criterios de soluci
on
En base al enunciado podemos hacer el siguiente esquema:

Como se puede ver en el dibujo y deducir del enunciado, tenemos cuatro clases. Uno clase Departamento,
una clase Sector, una clase Sensor y una clase Controlador. En el dibujo se ve que un Departamento contiene
cinco objetos Sector (cocina, terraza, dormitorio, ba
no y sala) y que a su vez cada Sector contiene un Sensor
y un Controlador.
Adem
as de esto hay que notar que los sensores deben ser capaces de censar el ambiente y comunicarse con
los controladores (por eso la flecha entre ambos objetos) y los controladores deben ser capaces de regular el
ambiente.
Por lo anterior entonces debemos:
Hacer cuatro clases, cada una con su constructor
Departamento debe tener 5 objetos Sector y cada objeto Sector debe tener un Sensor y un Controlador.
La clase Sensor debe tener un metodo que cense y una manera de guardar esos valores. Adem
as debe
tener una manera de comunicarse con el Controlador.
El controlador debe tener un metodo que regule el ambiente.
Posible Soluci
on
public class D e p a r t a m e n t o {
private Sector cocina , terraza , dormitorio , bano , sala ;
// C o n s t u c t o r de la clase d e p a r t a m e n t o. Crea el d e p a r t a m e n t o con sus
// 5 sectores c o r r e s p o n d i e n t e s.
// A l t e r n a t i v a 1: Recibe los sectores como p a r a m e t r o s ( objetos ).
// A l t e r n a t i v a 2: Crea los sectores dentro del c o n s t r u c t o r sin p a r a m e t r o s.
public D e p a r t a m e n t o( Sector cocina , Sector terraza , Sector dormitorio ,
Sector bano , Sector sala ) {
}
}
public class Sector {
private Sensor sensor ;
private C o n t r o l a d o r c o n t r o l a d o r;
// C o n s t r u c t o r de la clase Sector . Crea un sensor y un c o n t r o l a d o r para el sector .
// Recibe sensor y c o n t r o l a d o r como p a r a m e t r o s ( objetos )
// Ademas el sensor le envia la i n f o r m a c i o n al c o n t r o l a d o r
// d i r e c t a m e n t e. En tal caso , el sensor conoce ( set ) al c o n t r o l a d o r.
public Sector ( Sensor sensor , C o n t r o l a d o r c o n t r o l a d o r) {
}
}

IIC1103 Captulo 4: Clases

public class Sensor {


private C o n t r o l a d o r c o n t r o l a d o r; // para c o m u n i c a r el sensor con el
// c o n t r o l a d o r
private boolean m o v i m i e n t o;
private int luz ;
private float t e m p e r a t u r a;
// Define las f u n c i o n e s de sensar en metodos s e p a r a d o s
// Detecta m o v i m i e n t o en el sector al cual p e r t e n e c e el sensor .
public void d e t e c t a r M o v i m i e n t o() {
}
// Detecta luz en el sector al cual p e r t e n e c e el sensor .
public void d e t e c t a r L u m i n o s i d a d() {
}
// Detecta la t e m p e r a t u r a en el sector al cual p e r t e n e c e el sensor .
public void d e t e c t a r T e m p e r a t u r a() {
}
// Fija el valor del c o n t r o l a d o r para poder c o m u n i c a r s e
public void s e t C o n t r o l a d o r( C o n t r o l a d o r c o n t r o l a d o r) {
}
}
public class C o n t r o l a d o r {
private float t e m p e r a t u r a I d e a l;
private int luzIdeal ;
private boolean m o v i m i e n t o;
private int l u z A c t u a l;
private float t e m p e r a t u r a A c t u a l;
// Sube la t e m p e r a t u r a del sector .
public void s u b i r T e m p e r a t u r a( float grados ) {
}
// Baja la t e m p e r a t u r a del sector .
public void b a j a r T e m p e r a t u r a( float grados ) {
}
// Enciende la luz del sector .
public void e n c e n d e r L u z() {
}
// Apaga la luz del sector .
public void a p a g a r L u z() {
}
// D i s m i n u y e la i n t e n s i d a d de la luz del sector .
private void d i s m i n u i r L u z( int l ) {
}
// Aumenta la i n t e n s i d a d de la luz del sector .
private void subirLuz ( int l ) {
}
// Recibe los valores actuales de temperatura , luz y movimiento , estima
// d i f e r e n c i a con los valores ideales y si es n e c e s a r i o hace los cambios
// en el sector , sube / baja t e m p e r a t u r a o luz o enciende / apaga luz .
public void a c t u a l i z a r( float temperatura , int luz , boolean m o v i m i e n t o) {
}
}

IIC1103 Captulo 4: Clases

Problema 3: Insumos
Enunciado
Una empresa recibe insumos de varios proveedores distintos. Para manejar los insumos la empresa tiene un
departamento de bodega que es administrado por un gerente. Los proveedores tienen nombre y rut de la
empresa.
Cada mes, el gerente de bodega debe pedir a sus proveedores una lista de insumos que se requieren, indicando
el tipo de insumo y la cantidad requerida. Los proveedores responden especificando el tipo y la cantidad de
insumos que pueden enviar y el costo unitario de estos. El gerente debe aprobar la cotizacion si le parece
razonable y en caso de hacerlo se realiza un pago al proveedor correspondiente y se reciben dichos insumos, agregandose al inventario centralizado en bodega. La empresa realiza todas estas operaciones en base
a memos y telefono, lo que ha demostrado ser muy ineficaz. Por ende, la empresa ha decidido automatizar
sus sistemas y le pide a usted que dise
ne el esquema de clases necesario para organizar esta informaci
on y
permitir las operaciones antes mencionadas.
Asuma que dispone de una clase reutilizable Lista (que hizo en otro proyecto anterior) que le permite
encapsular una lista de instancias de cualquier clase que usted quiera como una instancia. Por ejemplo, la
notaci
on para una lista de instancias de la clase persona sera <Lista Persona> .
El esquema que debe desarrollar corresponde a la definici
on de las clases que estime pertinentes para resolver
el problema. Dicha definici
on debe incluir los atributos necesarios para almacenar toda la informaci
on relevante y la definici
on de las funciones que permiten manipular dicha informaci
on (solo la firma, no el c
odigo
interno de las funciones).
Criterios de soluci
on
Del enunciado desprendemos que se deben crear tres clases: una clase insumo, una clase proveedor y por
u
ltimo una clase gerente. Los atributos de un objeto insumo est
an detallados en el mismo enunciado: tipo,
valor y cantidad.
Para el objeto proveedor tambien es claro que debe tener un nombre, una cuenta y un rut. Sin embargo,
es importante reconocer que debe tener dos metodos, uno que cotice y otro que efectivamente venda. Notar
que ambos metodos retornan void ya que al recibir un objeto como par
ametro permite que estos puedan ser
cambiados dentro del metodo.

Posible Soluci
on
public class Insumo {
/* * Tipo de insumo , por ejemplo : " lapiz mina ". */
public String tipo ;
/* * Valor del insumo , en pesos , por ejemplo : 123 ,45.
* Si no se conoce el valor del insumo la variable es < 0. */
public float valor ;
/* * Cantidad de insumos de este tipo , por defecto en 0. */
public int cantidad ;
/* * C o n s t r u c t o r por valores */
public Insumo ( String tipo , float valor , int cantidad );
/* * C o n s t r u c t o r que usa los valores por defecto d e f i n i d o s */
public Insumo ( String tipo );
}

IIC1103 Captulo 4: Clases

public class P r o v e e d o r {
/* * Stock de insumos que posee el p r o v e e d o r */
private Lista < Insumo > stock ;
/* * Dinero en posecion del p r o v e e d o r */
private float cuenta ;
/* * Nombre del p r o v e e d o r. */
public String nombre ;
/* * Rut del p r o v e e d o r */
public String rut ;
/* *
* Recibe una lista de insumos que c o r r e s p o n d e a una peticion . Modifica el
* valor de cada insumo de acuerdo al p r o v e e d o r Cambia la cantidad a la
* cantidad maxima de la que se dispone . Al ser un puntero los cambios
* pueden ser leidos por quien pidio la c o t i z a c i o n.
*/
public void Cotizar ( Lista < Insumo > insumos );
/* *
* Recibe una t r a n s a c c i o n de insumos . Elimina los insumos del stock del
* p r o v e e d o r e i n c r e m e n t a la cuenta acorde con la cantidad y valor de estos .
*/
public void Entregar ( Lista < Insumo > insumos );
}
public class Gerente {
/* * Dinero en posecion del gerente */
private float cuenta ;
/* * Insumos en la bodega */
private Lista < Insumo > bodega ;
/* * P r o v e e d o r e s c o n o c i d o s */
private Lista < Proveedor > bodega ;
/* *
* Realiza las o p e r a c i o n e s del gerente . D e t e r m i n a los insumos requeridos ,
* pide c o t i z a c i o n e s a los d i s t i n t o s proveedores , analiza las respuestas ,
* aprueba los p r e s u p u e s t o s y realiza la t r a n s a c c i o n final .
*/
public void Trabajar ();
}

IIC1103 Captulo 4: Clases

10

Problema 4: Transantiago
Enunciado
Para salvar el Transantiago, la empresa de software QONDA ha dise
nado un sistema de informaci
on (programa) que controle las frecuencias de los buses con ayuda de los datos de posici
on y ocupaci
on entregados
en tiempo real por cada vehculo. El siguiente es un extracto del esquema de las clases que los ingenieros de
QONDA dise
naron para el sistema. Sugiera cambios para mejorar el encapsulamiento de la soluci
on sin que
el sistema pierda funcionalidad.
Los objetos de la clase bus usan informaci
on sobre el recorrido al que pertenecen, a fin de saber a que paradero deben ir. Con la informaci
on sobre el paradero, averiguan la hora de arribo al pr
oximo paradero a fin
de saber si deben acelerar o disminuir el paso.
Cada objeto de la clase recorrido, por su parte, conoce los paraderos por los que, en forma secuencial, deben
pasar los buses que le pertenecen, y los horarios esperados de detencion en cada paradero. Adem
as, conoce
a todos sus buses, a fin de decidir si deben distanciarse o acercarse para cumplir con las frecuencias establecidas, y datos sobre el operador (la empresa que controla el recorrido) para poder generar informes o dar
avisos por e-mail en caso de ser necesario.
Cada paradero sabe que recorridos se detienen en el y en que horarios deben pasar buses. Adem
as puede
estimar la cantidad de pasajeros que esperan en cada paradero en funci
on de la hora.
Un objeto hora guarda informaci
on sobre tiempos y permite realizar f
acilmente calculos de demoras y velocidades.

Criterios de soluci
on
La encapsulacion corresponde a esconder informaci
on relevante al exterior de un objeto, al mismo tiempo
que se minimiza el conocimiento de las clases, manteniendo s
olo las relaciones estrictamente necesarias para
que el programa cumpla su funci
on. Con esto se facilitan posibles modificaciones posteriores que se haga
al programa, puesto que en lugar de modificar todas las clases (todas se conocen, por lo que un cambio
repercute en todas), s
olo se modifica la clase implicada y, a lo m
as, sus relaciones directas, puesto que el
resto es indiferente de la implementaci
on particular, con tal de que el resultado sea coherente.
Del enunciado podemos derivar el siguiente modelo actual:

Esto se puede concluir del enunciado, por ejemplo, se dice que Los objetos de la clase bus usan informaci
on
sobre el recorrido al que pertenecen y por esto hay una conexion entre bus y recorrido.

IIC1103 Captulo 4: Clases

11

Adem
as el sistema tiene las siguientes funcionalidades:
El bus sabe a d
onde dirigirse.
El bus sabe si debe acelerar o disminuir el paso.
Se puede saber a que recorrido pertenece cada bus.
El sistema puede comunicarse con el operador de cada recorrido.
Dado un paradero, se puede saber el horario de recorridos.
Se puede hacer c
alculos con horas de manera f
acil.
Es claro que no son necesarias tantas conexiones entre clases para poder tener esas funcionalidades, por lo
tanto es posible eliminar algunas y mantener un programa que hace lo mismo y es m
as eficiente.
Posible Soluci
on
A manera de ejemplo se puede hacer esto:

Se asigna la responsabilidad de dirigir los buses (destino y velocidad) a la clase recorrido, cubriendo
las dos primeras funcionalidades mencionadas. De esta manera se hacen innecesarias las conexiones
bus-paradero y bus-hora
Se puede saber a que recorrido pertenece cada bus (enlace bus-recorrido)
Se crea la clase operador para manejar el detalle de la informaci
on y las comunicaciones con los consignatarios de los recorridos. Un objeto de recorrido es responsable de generar sus reportes y comunicaciones,
que encarga al respectivo objeto operador.
Dado un paradero, se puede saber el horario de recorridos (enlace paradero-recorrido)
Que se pueda hacer c
alculos con horas de manera f
acil (clase hora, enlaces recorrido-hora y paraderohora, que trabajan con tiempos)
Es importante notar que esta no es la u
nica manera, este problema tiene m
ultiples soluciones y esta es tan
solo una de ellas.

IIC1103 Captulo 4: Clases

12

Problema 5: Cuadrados y Crculos


Enunciado
Una empresa le ha pedido desarrollar un programa que modele figuras geometricas. Se necesita modelar
cuadrados y crculos. Para cada uno se desea poder calcular permetro y area. Adem
as se desea poder saber
si las figuras se intersectan o no (s
olo figuras del mismo tipo). Escriba la clase cuadrado y crculo de manera
tal que se puedan realizar todas las operaciones pedidas.
Criterios de soluci
on
Primero debemos identificar las partes de cada clase:
El cuadrado est
a definido por el largo de sus lados, y su posici
on. Por facilidad podemos guardar la posici
on
del lado superior izquierdo. En cuanto a los metodos, necesitamos calcular permetro, area, y revisar si la
figura se intersecta con otra del mismo tipo.
Por otra parte, el crculo est
a definido por su centro y su radio. Necesita los mismos metodos que el cuadrado.
Posible Soluci
on
public class Circulo {
private double radio ;
private double x , y ;
public Circulo ( double radio , double x , double y ) {
this . radio = Math . abs ( radio ); // radio siempre positivo
this . x = x ;
this . y = y ;
}
public double g e t P e r i m e t r o () {
return 2 * Math . PI * radio ;
}
public double getArea () {
return Math . PI * radio * radio ;
}
public boolean s e I n t e r s e c a( Circulo circulo ) {
// C a l c u l a m o s d i s t a n c i a entre ambos centros
double d i s t a n c i a = g e t D i s t a n c i a( circulo . getX () , circulo . getY ());
// Si la d i s t a n c i a es menor o igual a la suma de los radios , se i n t e r s e c t a.
return ( d i s t a n c i a <= radio + circulo . getRadio ());
}
public boolean e s I n t e r i o r( double x , double y ) {
return ( g e t D i s t a n c i a(x , y ) < radio );
}
private double g e t D i s t a n c i a( double x , double y ) {
return Math . sqrt (( this . x - x ) * ( this . x - x ) + ( this . y - y ) * ( this . y - y ));
}
public double getRadio () {
return radio ;
}
public void setRadio ( double radio ) {
this . radio = Math . abs ( radio );
}
public double getX () {
return x ;
}
public void setX ( double x ) {
this . x = x ;
}
public double getY () {
return y ;
}
public void setY ( double y ) {
this . y = y ;
}
}

IIC1103 Captulo 4: Clases

13

public class Cuadrado {


private double lado ;
private double x , y ;
public Cuadrado ( double lado , double x , double y ) {
this . lado = Math . abs ( lado ); // lado siempre positivo
this . x = x ;
this . y = y ;
}
public double g e t P e r i m e t r o () {
return 4 * lado ;
}
public double getArea () {
return lado * lado ;
}
public boolean s e I n t e r s e c a( Cuadrado cuadrado ) {
// R e v i s a r e m o s si alguno de los vertices de uno esta dentro del otro , y v i c e v e r s a.
boolean interior = false ;
// Cuadrado p a r a m e t r o dentro de este
if ( e s I n t e r i o r( cuadrado . getX () , cuadrado . getY ())) {
interior = true ;
} else if ( e s I n t e r i o r( cuadrado . getX () + cuadrado . getLado () , cuadrado . getY ())) {
interior = true ;
} else if ( e s I n t e r i o r( cuadrado . getX () + cuadrado . getLado () , cuadrado . getY () + cuadrado . getLado ())) {
interior = true ;
} else if ( e s I n t e r i o r( cuadrado . getX () , cuadrado . getY () + cuadrado . getLado ())) {
interior = true ;
} else if ( cuadrado . e s I n t e r i o r(x , y )) {
// este dentro del cuadrado p a r a m e t r o
interior = true ;
} else if ( cuadrado . e s I n t e r i o r( x + lado , y )) {
interior = true ;
} else if ( cuadrado . e s I n t e r i o r( x + lado , y + lado )) {
interior = true ;
} else if ( cuadrado . e s I n t e r i o r(x , y + lado )) {
interior = true ;
}
return interior ;
}
// Revisa si el punto es interior al cuadrado o no
public boolean e s I n t e r i o r( double x , double y ) {
return ( x >= this . x && x <= this . x + lado && y >= this . y && y <= this . y + lado );
}
public double getLado () {
return lado ;
}
public void setLado ( double lado ) {
this . lado = Math . abs ( lado );
}
public double getX () {
return x ;
}
public void setX ( double x ) {
this . x = x ;
}
public double getY () {
return y ;
}
public void setY ( double y ) {
this . y = y ;
}
}

IIC1103 Captulo 4: Clases

14

Problema 6: Circunferencia Light


Enunciado
Realice un programa que determine si dos circunferencias son concentricas. Una de ellas, debe estar centrada
en el origen, y tener radio 5, mientras que los elementos de la segunda deber
an ser proporcionados por el
usuario.
Criterios de soluci
on
Debemos crear dos clases:
1. clase Circunf erencia: que tenga como atributos
las coordenadas de su centro (dado el enunciado, dos variables de tipo int)
su radio (otro entero)
un metodo para determinar si dos circunferencias son concentricas
2. clase P rincipal: donde se pida que el usuario ingrese los datos, y determine si la circunferencia ingresada
por este es concentrica con la de prueba.
Posible Soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l C i r c u n f e r e n c i a {
public static void main ( String [] args ) {
// creo las v a r i a b l e s
// la primera circunferencia , con los e l e m e n t o s a r b i t r a r i o s que dicta el problema
C i r c u n f e r e n c i a nombre = new C i r c u n f e r e n c i a(0 , 0 , 4);
// pedimos al usuario que ingrese los e l e m e n t o s de la segunda c i r c u n f e r e n c i a
int x1 = Usuario . entero ( " Ingrese la c o o r d e n a d a x del centro : " );
int y1 = Usuario . entero ( " Ingrese la c o o r d e n a d a y del centro : " );
int r1 = Usuario . entero ( " Ingrese el radio : " );
// creamos la segunda c i r c u n f e r e n c i a
C i r c u n f e r e n c i a l a Q u e I n g r e s e E l U s u a r i o = new C i r c u n f e r e n c i a( x1 , y1 , r1 );
// c o m p a r a m o s si son concentricas , u t i l i z a n d o el metodo c o r r e s p o n d i e n t e
if ( nombre . s o n C o n c e n t r i c a s( l a Q u e I n g r e s e E l U s u a r i o )) {
Usuario . mensaje ( " Son c o n c e n t r i c a s" );
} else {
Usuario . mensaje ( " No son c o n c e n t r i c a s" );
}
}
}
// clase que captura los e l e m e n t o s propios y r e l e v a n t e s de las C i r c u n f e r e n c i a s
public class C i r c u n f e r e n c i a {
// [ A T R I B U T O S] ( lo que todas tienen en comun )
int x , y ; // c o o r d e n a d a s x e y del centro
int radio ; // radio
// [ METODOS ] ( las cosas que pueden hacer )
// C o n s t r u c t o r: crea una nueva c i r c u n f e r e n c i a.
// Recibe y fija los valores del centro ( x e y ) y el radio
public C i r c u n f e r e n c i a( int x , int y , int radio ) {
this . x = x ;
this . y = y ;
this . radio = radio ;
}

IIC1103 Captulo 4: Clases

15

// metodo que d e t e r m i n a si la c i r c u n f e r e n c i a actual es c o n c e n t r i c a con otra .


// Recibe como p a r a m e t r o otra circunferencia , con la que se compara .
public boolean s o n C o n c e n t r i c a s( C i r c u n f e r e n c i a otra ) {
if ( otra != null ) { // si la otra no es null
if ( this . x == otra . x && this . y == otra . y ) { // si son c e n t r i c a s
return true ; // r e t o r n a m o s true
} else {
return false ;
}
} else {
// la otra es null
return false ; // asi que r e t o r n a m o s false
}
}
}

IIC1103 Captulo 4: Clases

16

Problema 7: Concurso de Bebidas


Enunciado
Hace mucho, mucho tiempo... se realiza un concurso de bebidas. Estamos en la final de este, y para que no
queden dudas del ganador, se le ha pedido que dise
ne un programa que determine a este heroico individuo.
Para esto, se le explica, a grosso modo, en que consiste la competencia:
A estas alturas s
olo quedan 3 concursantes.
Cada uno de ellos elige una bebida, del sabor que quiera, en una lata, botella de 1 litro, de 2 litros, o
de 3 litros, por la que pag
o en su inscripci
on 350, 500, 800, o 1000 pesos, respectivamente.
Por la presi
on del evento, la altura, y otros factores ex
ogenos que escapan a los motivos pedag
ogicos
de este enunciado, s
olo pueden beber entre 10 y 100 cc en cada trago.
Ganar
a 1000000 de veces el precio que cancelo, quien primero se acabe todo su refresco.
Adem
as, para que no queden dudas de la utilidad de su software, se le piden ciertos requisitos adicionales:
Luego de cada sorbo, se debe mostrar un mensaje en consola personalizado con la siguiente estructura:
<concursante> tomo un sorbo de <cantidad> cc y le queda <contenido>
d
onde concursante es el nombre del concursante, cantidad es la cantidad de centmetros c
ubicos que
tom
o, y contenido es el contenido que queda en el envase.
Al ganador de este magno evento le debe mostrar una ventana con el siguiente mensaje:
Felicidades <nombre> ha ganado luego de <cantidadDeTragos> tragos.
Su premio es de: <premio>
donde nombre es el nombre del concursante, cantidadDeT ragos es la cantidad de tragos que necesit
o para ganar, y premio es el monto que se adjudic
o.
Dado el gran estres de la competencia 1 , se le pide que verifique que los usuarios ingresen correctamente los datos. En concreto, ya haba una versi
on anterior a la suya, con el siguiente metodo, que le
gust
o mucho a los jueces, por lo que le piden que tambien lo implemente y utilice 2 3 :
public static int v e r i f i c a r E n t e r o( String elMensaje , int minimo , int maximo ){...}

.
que muestra el mensaje elM ensaje, y verifica que el entero ingresado por el usuario esta entre minimo
y maximo.
Criterios de soluci
on
Del enunciado concluimos que se deben crear dos clases:
1. clase Bebida:
a) Que tenga como atributos
1
2
3

y porque herrar es humano


los clientes siempre creen que saben lo que necesitan
ayuda: este m
etodo va en la clase Principal

IIC1103 Captulo 4: Clases

17

el due
no (un String)
el tipo de envase y/o contenido (esta soluci
on lleva ambas)
b) Que tenga como metodos
el constructor (se sugiere que reciba los atributos correspondientes)
los getters y setters que se estimen correspondientes (en la solucion no se usan setters)
uno que calcule el premio del ganador
uno que determine si alguien ya termin
o su bebida
2. clase P rincipal: donde se pida que el usuario ingrese los datos, se creen los objetos (por lo menos
los 3, uno para cada participante), y se utilicen los metodos correspondientes, adem
as del metodo
verif icarEntero(String, int, int) como pide el enunciado
Posible Soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class Bebida {
// [ A T R I B U T O S]
private String duenio ; // nombre del duenio de la lata
private int t i p o E n v a s e; // 0 lata , 1 botella de 1 lt , 2 de 2 lt , y 3 de 3 lt
private int c o n t e n i d o; // c o n t e n i d o actual ( en cc )
// [ METODOS ]
// C o n s t r u c t o r
public Bebida ( String duenio , int t i p o E n v a s e) {
this . duenio = duenio ;
this . t i p o E n v a s e = t i p o E n v a s e;
switch ( t i p o E n v a s e) {
case 0:
this . c o n t e n i d o = 350;
break ;
case 1:
this . c o n t e n i d o = 1000;
break ;
case 2:
this . c o n t e n i d o = 2000;
break ;
case 3:
this . c o n t e n i d o = 3000;
break ;
}
}
// getters ( retorna el valor de la variable c o r r e s p o n d i e n t e)
public String g e t D u e n i o() {
return duenio ;
}
public int g e t C o n t e n i d o() {
return c o n t e n i d o;
}
// otros
public int c a l c u l a r G a n a n c i a () {
int precio = 0;
switch ( t i p o E n v a s e) {
case 0:
precio = 350;
break ;
case 1:
precio = 500;
break ;
case 2:
precio = 800;
break ;
case 3:
precio = 1000;
break ;
}
precio *= 1000000;
return precio ;
}

IIC1103 Captulo 4: Clases

18

public boolean s e g u i r B e b i e n d o() {


// d e t e r m i n a si , luego de beber , queda bebida
// en un sorbo , tomamos ( a l e a t o r e a m e n t e) entre
int sorbo = A l e a t o r i o. entero (10 , 100);
this . c o n t e n i d o -= sorbo ;
if ( c o n t e n i d o > 0) {
return true ;
} else {
// en este caso el c o n t e n i d o es no positivo .
// m o s t r a m o s en consola el nombre , el sorbo ,
Usuario . m e n s a j e C o n s o l a( this . duenio + " , tomo
+ " cc y le queda " + this . c o n t e n i d o);
return false ;
}
}

10 y 100 cc ,

Si es negativo no es problema
y cuanto queda
un sorbo de " + sorbo

}
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l B e b i d a {
/* *
* Programa que simula un concurso de bebidas
*/
// Se le pide a cada uno de los 3 usuarios que ingrese su nombre y bebida
// para competir .
// La lata cuesta 350 , la botella de 1 lt 500 , de 2 lt 800 , y de 3 lt 1000.
// El primero que se termina su bebida gana 1000000 veces el precio que
// pago .
public static void main ( String [] args ) {
String m e n s a j e N o m b r e = " B i e n v e n i d o al concurso . Ingrese su nombre : " ;
String m e n s a j e B e b i d a = " Ingrese la bebida que quiere para competir : "
+ " \ n [0] lata
( 350 cc ) " + " \ n [1] botella (1000 cc ) "
+ " \ n [2] botella (2000 cc ) " + " \ n [3] botella (3000 cc ) " ;
Bebida b1 , b2 , b3 ;
String n o m b r e C o n c u r s a n t e 1 = Usuario . texto ( m e n s a j e N o m b r e);
int t i p o B e b i d a 1 = v e r i f i c a r E n t e r o( mensajeBebida , 0 , 3);
b1 = new Bebida ( n o m b r e C o n c ur sa nte 1 , t i p o B e b i d a 1);
String n o m b r e C o n c u r s a n t e 2 = Usuario . texto ( m e n s a j e N o m b r e);
int t i p o B e b i d a 2 = v e r i f i c a r E n t e r o( mensajeBebida , 0 , 3);
b2 = new Bebida ( n o m b r e C o n c ur sa nte 2 , t i p o B e b i d a 2);
String n o m b r e C o n c u r s a n t e 3 = Usuario . texto ( m e n s a j e N o m b r e);
int t i p o B e b i d a 3 = v e r i f i c a r E n t e r o( mensajeBebida , 0 , 3);
b3 = new Bebida ( n o m b r e C o n c ur sa nte 3 , t i p o B e b i d a 3);
int c a n t i d a d T r a g o s = 1;
while (( b1 . s e g u i r B e b i e n d o() && b2 . s e g u i r B e b i e n d o() && b3 . s e g u i r B e b i e n d o ())) {
Usuario . mensaje ( " Llevamos " + c a n t i d a d T r a g o s + " sorbos , y aun no hay ganador ! " );
c a n t i d a d T r a g o s ++;
}
// m o s t r a m o s el mensaje de f e l i c i t a c i o n p e r s o n a l i z a d o que nos piden
String f e l i c i d a d e s = " F e l i c i d a d e s " ;
int premio = 0;
if ( b1 . g e t C o n t e n i d o() <= 0) {
f e l i c i d a d e s += b1 . g e t D u e n i o();
premio = b1 . c a l c u l a r G a n a n c i a();
} else if ( b2 . g e t C o n t e n i d o() <= 0) {
f e l i c i d a d e s += b2 . g e t D u e n i o();
premio = b2 . c a l c u l a r G a n a n c i a();
} else {
f e l i c i d a d e s += b3 . g e t D u e n i o();
premio = b3 . c a l c u l a r G a n a n c i a();
}
f e l i c i d a d e s += " ha ganado luego de " + c a n t i d a d T r a g o s + " tragos . " ;
f e l i c i d a d e s += " \ nSu premio es de : " + premio ;
Usuario . mensaje ( f e l i c i d a d e s);
}
// metodo que muestra el mensaje < elMensaje > , y verifica que el entero
// i n g r e s a d o
// por el usuario este entre < minimo > y < maximo >.
public static int v e r i f i c a r E n t e r o( String elMensaje , int minimo , int maximo ) {
int valor = -1;
while ( valor < minimo || valor > maximo ) {
valor = Usuario . entero ( e l M e n s a j e);
}
return valor ;
}
}

IIC1103 Captulo 4: Clases

19

Problema 8: Puerto de Valparaso


Enunciado
Los operadores del ajetreado puerto de Valparaso han solicitado su ayuda para escribir un programa que
simule la carga de un barco con containeres.
Un barco est
a compuesto de tres secciones. En cada una de ellas se puede almacenar una cierta cantidad de
containeres de un solo tipo. El tipo depende del tama
no del container (hay de 20 y 40 pies) y si este requiere
refrigeraci
on (refrigerado o no). Se requiere de sus conocimientos para implementar las clases Seccion y
Barco.
Se ha definido la clase Container de la siguiente manera:
public class C o n t a i n e r {
private int tamano ; // tamano del c o n t a i n e r: 20 o 40 pies
private boolean r e f r i g e r a d o; // true si es r e f r i g e r a d o
// C o n s t r u c t o r del c o n t a i n e r
public C o n t a i n e r( int t , boolean r ) { ... }
// Retorna el tamano del c o n t a i n e r
public int g e t T a m a n o() { return tamano ; }
// true si el c o n t a i n e r es r e f r i g e r a d o
public boolean i s R e f r i g e r a d o() { return r e f r i g e r a d o; }
}

.
Se ha definido la clase Seccion (del barco) de la siguiente manera:
public class Seccion {
// c a p a c i d a d maxima de la seccion
private int c a p a c i d a d T o t a l;
// c a p a c i d a d d i s p o n i b l e en la seccion
private int c a p a c i d a d;
// tamano de c o n t a i n e r que puede a l m a c e n a r: 20 o 40 pies
private int tamano ;
// true si se utiliza solo para a l m a c e n a r c o n t a i n e r s r e f r i g e r a d o s
private boolean r e f r i g e r a d o;
// Crea un objeto de la clase Seccion ; genera en forma a l e a t o r i a
// el tipo de C o n t a i n e r s que puede a l m a c e n a r y su c a p a c i d a d
public Seccion (){ ... }
// Intenta agregar un c o n t a i n e r a la seccion ;
// retorna true si es factible hacerlo
public boolean Agregar ( C o n t a i n e r c ) { ... }
// Retorna true si la seccion esta llena
public boolean Lleno () { ... }
// Muestra en la consola los datos de la seccion
public void Mostrar () { ... }
}

1. Implemente el metodo agregar de la clase Seccion.


2. Implemente la clase Barco; tome en cuenta que debe:
Definir los atributos de la clase.
Implementar un constructor
Implementar el metodo Agregar
// retorna true si es factible hacerlo
public boolean Agregar ( C o n t a i n e r c , int n u m S e c c i o n ){...}

Implementar el metodo Lleno


// Retorna true si el barco esta lleno
public boolean Lleno () {...}

IIC1103 Captulo 4: Clases

20

Criterios de soluci
on
El enunciado es bastante estructurado, por lo que seguimos los pasos pedidos
1. clase Seccion:
a) Implementamos el metodo Agregar, el cu
al recibe un Container como par
ametro y retorna true si
fue posible agregarlo.
Para agregar un container hay que revisar que la secci
on tenga capacidad, que el tama
no del
container sea posible de almacenar en la seccion y si requiere refigeracion que la secci
on lo
pueda almacenar. Si no se cumple alguna de estas condiciones se debe retornar false. Si se
puede almacenar, debemos disminuir la capacidad de la seccion.
2. clase Barco:
a) Declaramos los atributos: Como dice el enunciado debe tener 3 secciones, o sea, 3 objetos de la
clase Seccion.
b) Implementar un constructor: En el creamos los tres objetos de la clase Seccion declarados como
atributos.
c) Implementar el metodo Agregar: Seg
un la seccion recibida como par
ametro llamamos al metodo
agregar de la seccion que corresponda y retornamos true o false seg
un si se pudo o no agregar el
container a la seccion requerida.
d ) Implementar el metodo Lleno: Llamamos al metodo Lleno de las 3 secciones del barco y retornamos
true s
olo si las tres secciones estan llenas. De lo contrario, retornamos false.

IIC1103 Captulo 4: Clases

21

Posible Soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class Seccion {
// c a p a c i d a d maxima de la seccion
private int c a p a c i d a d T o t a l;
// c a p a c i d a d d i s p o n i b l e en la seccion
private int c a p a c i d a d;
// tamano de c o n t a i n e r que puede a l m a c e n a r: 20 o 40 pies
private int tamano ;
// true si se utiliza solo para a l m a c e n a r c o n t a i n e r s r e f r i g e r a d o s
private boolean r e f r i g e r a d o;
// Crea un objeto de la clase Seccion ; genera en forma a l e a t o r i a
// el tipo de C o n t a i n e r s que puede a l m a c e n a r y su c a p a c i d a d
public Seccion () {
this . tamano = A l e a t o r i o. entero (20 , 40);
this . c a p a c i d a d T o t a l = 100;
this . r e f r i g e r a d o = false ;
}
// Intenta agregar un c o n t a i n e r a la seccion ;
// retorna true si es factible hacerlo
public boolean Agregar ( C o n t a i n e r c ) {
boolean exito ;
if ( c . g e t T a m a n o() == tamano && c . i s R e f r i g e r a d o() == r e f r i g e r a d o
&& c a p a c i d a d > 0) {
c a p a c i d a d = c a p a c i d a d - 1;
exito = true ;
} else {
exito = false ;
}
return exito ;
}
// Retorna true si la seccion esta llena
public boolean Lleno () {
if ( c a p a c i d a d >= c a p a c i d a d T o t a l) {
return true ;
} else {
return false ;
}
}
// Muestra en la consola los datos de la seccion
public void Mostrar () {
}
}
public class Barco {
private Seccion s1 , s2 , s3 ;
public Barco () {
s1 = new Seccion ();
s2 = new Seccion ();
s3 = new Seccion ();
}
// Intenta agregar un c o n t a i n e r a la seccin n u m S e c c i o n;
// retorna true si es factible hacerlo
public boolean Agregar ( C o n t a i n e r c , int n u m S e c c i o n) {
boolean exito = false ;
if ( n u m S e c c i o n == 1)
exito = s1 . Agregar ( c );
else if ( n u m S e c c i o n == 2)
exito = s2 . Agregar ( c );
else if ( n u m S e c c i o n == 3)
exito = s3 . Agregar ( c );
return exito ;
}
// Retorna true si el barco esta lleno
public boolean Lleno () {
boolean lleno = true ;
lleno = ( s1 . Lleno () && s2 . Lleno () && s3 . Lleno ());
return lleno ;
}
}

IIC1103 Captulo 4: Clases

22

Problema 9: C
odigo a descifrar
Enunciado
Para el siguiente c
odigo, indique el output que aparecera en la Consola.
public class ClassA {
private String id ;
private ClassA hijo ;
private int total ;
public ClassA ( String n ) {
id = n ;
total = 0;
}
public
public
public
public
public

void setHijo ( ClassA h ) { hijo = h ; }


ClassA getHijo () { return hijo ; }
String getId () { return id ; }
void aumentar ( int delta ) { total += delta ; }
int getTotal () { return total ; }

}
public static void main ( String [] args ) {
ClassA a = new ClassA ( " Juanito " );
ClassA b = new ClassA ( " Pacita " );
ClassA c = new ClassA ( " Pedrito " );
a . setHijo ( b );
b . aumentar (4);
int delta = 3;
c . aumentar ( delta ++);
b . setHijo ( c );
if ( a . getHijo (). getTotal () > 3) {
ClassA d = a . getHijo ();
Interfaz . M o s t r a r M e n s a j e C o n s o l a( " L1 : " + d . getId () + " " + d . getTotal ());
}
Interfaz . M o s t r a r M e n s a j e C o n s o l a( " L2 : " + c . getId () + " " + c . getTotal ());
c . aumentar ( delta );
c . setHijo ( a . getHijo ());
if ( a . getHijo (). getHijo (). getHijo (). getTotal () == b . getTotal ())
Interfaz . M o s t r a r M e n s a j e C o n s o l a( " L3 : " + b . getId () + " " + b . getHijo (). getTotal ());
b . aumentar ( c . getTotal () - b . getTotal ());
if ( a . getHijo (). getTotal () != b . getHijo (). getTotal ())
Interfaz . M o s t r a r M e n s a j e C o n s o l a( " L4 : " + a . getId () + " " + a . getHijo (). getTotal ());
int total = a . getTotal () + b . getTotal () + c . getTotal ();
Interfaz . M o s t r a r M e n s a j e C o n s o l a( " L5 : " + total );
}

Criterios de soluci
on
En este tipo de problemas es buena opci
on escribir a un lado una tabla con las variables y objetos, e ir
anotando los cambios lnea a lnea, realizando una especie de debug manual. Se debe ser bastante sistem
atico
para no equivocarse, y cuidar interpretar correctamente los cambios en las variables y en los objetos.
Posible Soluci
on
L1:
L2:
L3:
L5:

Pacita 4
Pedrito 3
Pacita 7
14

IIC1103 Captulo 4: Clases

23

Problema 10: Analizar C


odigo
Enunciado
A continuaci
on se presenta un codigo el cual representa un juego sencillo entre dos jugadores.
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
int sum = 0 , fila , cantidad , turno = 0;
Linea
Linea
Linea
Linea

a
b
c
d

=
=
=
=

new
new
new
new

Linea (7);
Linea (5);
Linea (3);
Linea (1);

sum = a . getPhs () + b . getPhs () + c . getPhs () + d . getPhs ();


while ( sum > 1) {
Usuario . mensaje ( " F 1 : " + a . getPhs () + " \ n " + " F 2 : "
+ b . getPhs () + " \ n " + " F 3 : " + c . getPhs () + " \ n "
+ " F 4 : " + d . getPhs () + " \ n " );
fila = Usuario . entero ( " Jugador " + ( turno + 1) + " , fila ? " );
cantidad = Usuario . entero ( " Jugador " + ( turno + 1) + " , numero " );
if ( fila == 1 && a . d e s c o n t a r( cantidad )) {
turno = ( turno + 1) % 2;
} else if ( fila == 2 && b . d e s c o n t a r( cantidad )) {
turno = ( turno + 1) % 2;
} else if ( fila == 3 && c . d e s c o n t a r( cantidad )) {
turno = ( turno + 1) % 2;
} else if ( fila == 4 && d . d e s c o n t a r( cantidad )) {
turno = ( turno + 1) % 2;
} else {
Usuario . mensaje ( " Datos i n g r e s a d o s i n c o r r e c t o s" );
}
sum = a . getPhs () + b . getPhs () + c . getPhs () + d . getPhs ();
}
Usuario . mensaje ( " Pierde " + ( turno + 1));
}
}
public class Linea {
private int phs ;
public Linea ( int a ) {
phs = a ;
}
public int getPhs () {
return phs ;
}
public void setPhs ( int b ) {
phs = b ;
}
public boolean d e s c o n t a r( int a ) {
if ( a <= 0 || phs <= 0 || phs < a ) {
return false ;
} else {
phs = phs - a ;
return true ;
}
}
}

IIC1103 Captulo 4: Clases

24

Respecto al c
odigo anterior responda las siguientes preguntas:
1. Cu
al es el u
ltimo despliegue que el programa realiza para los siguientes datos de entrada?
Fila
N
umero

3
3

1
7

2
4

4
1

2. Muestre el estado (valor de los atributos) de los objetos instanciados al final del while para los
siguiente datos de entrada.
Fila
N
umero

1
4

3
2

3
1

2
4

1
1

2
1

1
1

4
1

Criterios de soluci
on
En este tipo de problemas es buena opci
on escribir a un lado una tabla con las variables y objetos, e ir
anotando los cambios lnea a lnea, realizando una especie de debug manual. Se debe ser bastante sistem
atico
para no equivocarse, y cuidar interpretar correctamente los cambios en las variables y en los objetos.
Posible Soluci
on
1. Pierde 1

2.

Input
Fila N
umero
1
4
3
2
3
1
2
4
1
1
2
1
1
1
4
1

Instancias
a b c d
3 5 3 1
3 5 1 1
3 5 0 1
3 1 0 1
2 1 0 1
2 0 0 1
1 0 0 1
1 0 0 0

IIC1103 Captulo 4: Clases

25

Problema 11: Space Invaders


Enunciado
El juego Space Invaders consiste en defender la tierra de malvados monstruos aliengenas invasores (en
adelante, bichos), para lo cual es necesario eliminarlos antes de que logren aterrizar.
Como el juego consta de varias partes, a usted s
olo le toca dise
nar e implementar la clase Bicho, que define
a estos bichos. Suponga que su clase va a ser utilizada por otros programadores, encargados de otras partes
del juego.
El comportamiento de estos bichos es muy sencillo. Cada bicho comienza en una cierta posici
on (X,Y), siendo
X un entero entre 0 y 50 e Y un entero entre 0 y 35. Las coordenadas se definen desde la esquina superior
izquierda de la pantalla. Es decir, al aumentar X me dirijo a la derecha y al aumentar Y me dirijo hacia
abajo.
Un bicho siempre comienza moviendose hacia la derecha y contin
ua haciendolo hasta que choca con el borde
(lmite de coordenadas), momento en que se mueve una vez hacia abajo y comienza a moverse hacia la
izquierda. Se considera que un bicho ha aterrizado si llega a nivel del suelo (Y = 35).
Asimismo, los bichos deben resistir disparos de las fuerzas de defensa en su aproximaci
on al planeta. Para
ello, cada bicho parte con una cierta resistencia (entero entre 1 y 15) que decrece cada vez que es impactado,
recibiendo un cierto da
no (entero entre 1 y 3). Si la resistencia del bicho llega a 0 o menos, se considera que
este ha sido destruido.
Su clase debe:
Incluir los atributos que caractericen a un bicho.
Contener una funci
on a ser llamada cada vez que el bicho tiene que moverse.
Darse cuenta de alguna forma si el bicho ha logrado aterrizar (al menos despues de que el bicho se
mueva).
Contener una funci
on que indique al bicho que ha recibido da
no.
Darse cuenta de alguna forma si el bicho ha sido destruido (al menos despues de recibir da
no).
Criterios de soluci
on
Con lo indicado en el enunciado podemos dise
nar e implementar la clase Bicho. Vemos que como atributos
la clase debe tener la posici
on en x e y del bicho, su resistencia y puede ser una variable que nos indique en
que sentido se esta moviendo (derecha o izquierda). Ademas creamos un constructor que reciba valores para
los atributos y los setee, indicando que el bicho parte moviendose hacia la derecha.
Luego debemos implementar los dos metodos que nos piden:

Mover: Este
es el metodo responsable de mover al bicho una unidad. Como tambien se nos pide una
forma de darse cuenta cuando el bicho aterriza, hacemos que el metodo retorne true cuando esto
ocurra o false en caso contrario. Para esto, primero revisamos en que sentido se esta moviendo (derecha
o izquierda), luego revisamos que no este en alguno de los dos bordes. Si est
a en un borde aumentamos
una unidad su posici
on en y y cambiamos el sentido. Si no est
a en un borde, aumentamos o disminuimos
su posici
on en x (seg
un el sentido). Finalmente, revisamos si la posici
on en y ha llegado al suelo. Si
lleg
o al suelo retornamos true y si no retornamos false.

Recibir Da
no: Este
es el metodo responsable de indicar al bicho que ha recibido da
no. Nuevamente,
como nos piden en el enunciado una forma de darse cuenta cuando el bicho ha sido destruido, hacemos
que el metodo retorne true cuando esto ocurra o false en caso contrario. Para esto, recibimos el da
no
como parametro y disminuimos la resistencia del bicho en esta cantidad. Finalmente, revisamos si la
resistencia ha llegado a cero, si es as retornamos true, de lo contrario, retornamos false.

IIC1103 Captulo 4: Clases

26

Posible Soluci
on
class Invader {
int x ; // Posicion en el eje X
int y ; // Posicion en el eje Y
int h i t P o i n t s; // R e s i s t e n c i a del bicho
boolean g o i n g R i g h t; // true si voy hacia la derecha , false i z q u i e r d a
public Invader ( int X , int Y , int HP ) {
x = X;
y = Y;
h i t P o i n t s = HP ;
g o i n g R i g h t = true ;
}
public boolean Mover () {
if ( g o i n g R i g h t) {
if ( x == 50) {
y ++;
g o i n g R i g h t = false ;
} else
x ++;
} else {
if ( x == 0) {
y ++;
g o i n g R i g h t = true ;
} else
x - -;
}
if ( y == 35)
return true ;
else
return false ;
}
public boolean T a k e D a m a g e( int damage ) {
h i t P o i n t s -= damage ;
return ( h i t P o i n t s < 0);
}
}

IIC1103 Captulo 4: Clases

27

Problema 12: Alumnos


Enunciado
Implemente el metodo main de un programa que permita manejar los alumnos de un curso. Las siguientes
clases ya se encuentran implementadas, por lo que usted debe usarlas en su programa:
public class Alumno {
public Alumno ( String nombre , double promedio ); // C o n s t r u c t o r
public String V e r N o m b r e (); // Retorna el nombre del alumno
public double V e r P r o m e d i o (); // Retorna el promedio del alumno
}
public class Curso {
public Curso (); // C o n s t r u c t o r
public void A g r e g a r A l u m n o( Alumno nuevo ); // Agrega un nuevo alumno al curso
// Elimina un alumno segun el nombre . Retorna true si existia .
public boolean E l i m i n a r A l u m n o( String nombre )
public double Promedio (); // Retorna el promedio del curso .
public Alumno M e j o r P r o m e d i o(); // Retorna el alumno con mejor promedio .
}

.
Su metodo main debe realizar lo siguiente:
Crear un Curso.
Mostrar al usuario un men
u que le permita realizar las siguientes opciones:
Agregar un nuevo Alumno. En este caso se debe pedir el nombre y el promedio al usuario, crear
un Alumno y agregarlo al curso.
Eliminar un Alumno. Se le debe pedir al usuario que ingrese un nombre seg
un el cual se debe
intentar eliminar al alumno. Se debe mostrar al usuario si se elimin
o (el alumno exista) o no el
alumno.
Ver el promedio general del Curso. Se debe mostrar al usuario el promedio general del curso.

Ver el mejor Alumno. Se debe mostrar al usuario el nombre y el promedio del alumno con mejor
promedio.
Salir. Se debe terminar el programa.
El men
u debe aparecer una y otra vez hasta que el usuario seleccione salir.
Puede suponer que los datos ingresados por el usuario son validos.
Criterios de soluci
on
En problemas como este lo m
as importante es conocer cuales son los metodos y clases disponibles para hacer
correcto uso de ellos y no escribir mas codigo del que corresponde.
Siguiendo lo pedido en el enunciado debemos:
Crear un objeto de la clase Curso.
Implementar un ciclo que contin
ue pidiendo la opci
on que desea al usuario mientras este no elija salir
del programa.
Revisar la opci
on ingresada por el usuario.
Opci
on Agregar Alumno: Debemos pedir al usuario que ingrese el nombre y el promedio del nuevo
alumno. Crear un nuevo objeto de la clase Alumno con los datos ingresados por el usuario. Llamar al
metodo AgregarAlumno de la clase Curso, pasando el nuevo alumno como par
ametro.
IIC1103 Captulo 4: Clases

28

Opci
on Eliminar Alumno: Debemos pedir al usuario el nombre del alumno que se desea eliminar.
Llamar al metodo EliminarAlumno de la clase Curso pasando el nombre ingresado por el usuario
como parametro. Revisar lo retornado por el metodo y mostrar un mensaje al usuario indicando si se
pudo o no eliminar el alumno pedido.
Opci
on Ver Promedio General: Debemos llamar al metodo P romedio de la case Curso y mostrar en
un mensaje lo retornado por este metodo.
Opci
on Ver Mejor Alumno: Debemos llamar al metodo M ejorP romedio que nos retorna el alumno con
mejor promedio. Luego, del alumno obtenido, debemos mostrar en un mensaje el nombre del alumno
y su promedio, llamando a los metodos V erN ombre y V erP romedio de la clase Alumno
Opci
on Salir: Terminar el ciclo
Posible Soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
Curso clase = new Curso ();
int opcion = -1;
while ( opcion != 0) {
opcion = Usuario . entero (" Elija una opcion : "
+ " \ n (1) Agregar Alumno " + " \ n (2) Eliminar Alumno "
+ " \ n (3) Ver promedio general " + " \ n (4) Ver mejor alumno "
+ " \ n (0) Salir " );
if ( opcion == 1) {
String nombre = Usuario . texto ( " Ingrese Nombre " );
double prom = Usuario . real ( " Ingrese promedio " );
Alumno nuevo = new Alumno ( nombre , prom );
clase . A g r e g a r A l u m n o( nuevo );
} else if ( opcion == 2) {
String nombre2 = Usuario . texto ( " Ingrese nombre " );
if ( clase . E l i m i n a r A l u m n o( nombre2 )) {
Usuario . mensaje ( " El alumno fue e l i m i n a d o. " );
} else {
Usuario . mensaje ( " El alumno no estaba en el curso . " );
}
} else if ( opcion == 3) {
Usuario . mensaje ( " Promedio general : " + clase . Promedio ());
} else if ( opcion == 4) {
Alumno mejor = clase . M e j o r P r o m e d i o ();
Usuario . mensaje ( " Mejor alumno es " + mejor . V e r N o m b r e()
+ " con un " + mejor . V e r P r o m e d i o ());
}
}
}
}

IIC1103 Captulo 4: Clases

29

Problema 13: Trenes


Enunciado
Implemente la clase Tren la cual debe representar a un tren de pasajeros. Cada tren se caracteriza por
la capacidad de pasajeros que posee, as como tambien por el n
umero de estaciones por las cuales pasa.
Su clase adem
as debe tener un metodo subirPasajeros el cual recibe una cierta cantidad de pasajeros e
intenta subirlos al tren. En caso de poder subirlos retorna true, pero si no puede subirlos porque no hay
capacidad en el tren, retorna false (se suben todos o no se sube ninguno). Adem
as, su clase Tren debe
tener un metodo arribarEstacion el cual permite al tren avanzar una estaci
on, haciendo que la mitad de
los pasajeros descienda en esta estacion (aproximando hacia abajo). Este metodo retorna true si se lleg
oa
la u
ltima estaci
on, en tal caso deben descender todos los pasajeros del tren.
Por u
ltimo, su clase debe tener un metodo pasajerosPorEstacion que retorne el promedio de pasajeros
que se subieron al tren por la cantidad de estaciones recorridas. Este promedio debe ser con decimales.
Su clase debe ser tal, que sea capaz de funcionar con el siguiente main:
public static void main ( String [] args ) {
// Creamos un tren para 80 p a s a j e r o s y que pasa por 10 e s t a c i o n e s
Tren tren = new Tren (80 , 10);
while (! tren . a r r i b a r E s t a c i o n()) {
// C a l c u l a m o s la cantidad de familias
int n u m F a m i l i a s = A l e a t o r i o. entero (1 , 8);
for ( int i = 0; i < n u m F a m i l i a s; i ++) {
int n u m P e r s o n a s = A l e a t o r i o. entero (1 , 4);
if ( tren . s u b i r P a s a j e r o s( n u m P e r s o n a s))
Usuario . mensaje ( " Se subieron " + n u m P e r s o n a s
+ " personas al tren . " );
else
Usuario . mensaje ( n u m P e r s o n a s
+ " personas no pudieron subirse al tren . " );
}
}
// M o s t r a m o s el promedio de p a s a j e r o s por estacion
Usuario . mensaje ( " El promedio de p a s a j e r o s por estacion fue : "
+ tren . p a s a j e r o s P o r E s t a c i o n ());
}

Criterios de soluci
on
Por lo explicado en el enunciado y lo mostrado en el metodo main entregado podemos ver c
omo debe ser
nuestra clase T ren:
Atributos: capacidad de pasajeros, estaciones por las que pasa, pasajeros transportados, pasajeros
actualmente arriba del tren, estaci
on actual en la que se encuentra el tren.
Constructor: Del metodo main podemos ver que debe recibir como par
ametros la capacidad y la
cantidad de estaciones por las que pasa. Estos valores los asignamos a los atributos correspondientes.
Metodo subirP asajeros: Del metodo main podemos ver que debe recibir como parametro el n
umero de
pasajeros a subir. Luego debemos revisar que al subir los nuevos pasajeros no se sobrepase la capacidad
del tren. Si se sobrepasa la capacidad retornamos false, en caso contrario, actualizamos la cantidad de
pasajeros actualmente en el tren y la cantidad de pasajeros transportados y retornamos true.
Metodo arribaEstacion : Como dice el enunciado lo primero que debemos hacer es disminuir la cantidad
de pasajeros que actualmente est
an en el tren a la mitad. Luego actualizamos la estaci
on en la que se
encuentra el tren y revisamos si corresponde a su u
ltima estaci
on. Si se encuentra en la u
ltima estaci
on
bajamos a todos los pasajeros y retornamos true. Si no se encuentra en la u
ltima estaci
on retornamos
false.

IIC1103 Captulo 4: Clases

30

Metodo pasajerosP orEstacion: Simplemente retornamos la divisi


on de los pasajeros transportados
por el n
umero de estaciones visitadas.
Posible Soluci
on
public class Tren {
// Los a t r i b u t o s tambien podrian ser double
private int c a p a c i d a d;
private int p a s a j e r o s;
private int p a s a j e r o s T r a n s p o r t a d o s;
private int e s t a c i o n e s T o t a l e s;
private int e s t a c i o n A c t u a l;
public Tren ( int capacidad , int e s t a c i o n e s T o t a l e s) {
this . c a p a c i d a d = c a p a c i d a d;
this . e s t a c i o n e s T o t a l e s = e s t a c i o n e s T o t a l e s;
this . p a s a j e r o s = 0;
this . e s t a c i o n A c t u a l = 0;
}
public boolean s u b i r P a s a j e r o s( int num ) {
// R e v i s a m o s si hay cupo para subir a los p a s a j e r o s
if ( p a s a j e r o s + num > c a p a c i d a d)
return false ;
// Si es posible , a c t u a l i z a m o s la cantidad de p a s a j e r o s en el tren
p a s a j e r o s += num ;
p a s a j e r o s T r a n s p o r t a d o s += num ;
return true ;
}
public boolean a r r i b a r E s t a c i o n() {
// Cuando a r r i b a m o s a una estacion se bajan la mitad de los p a s a j e r o s
p a s a j e r o s = p a s a j e r o s / 2;
// Si es la ultima estacion r e t o r n a m o s true
e s t a c i o n A c t u a l ++;
if ( e s t a c i o n A c t u a l == e s t a c i o n e s T o t a l e s) {
// Bajamos a todos
p a s a j e r o s = 0;
return true ;
}
return false ;
}
public double p a s a j e r o s P o r E s t a c i o n() {
// D i v i d i m o s el total de p a s a j e r o s en la cantidad de e s t a c i o n e s
return ( double ) p a s a j e r o s T r a n s p o r t a d o s / e s t a c i o n A c t u a l;
}
}

IIC1103 Captulo 4: Clases

31

Problema 14: A
no bisiesto
Enunciado
Existen personas que han nacido en 29 de Febrero, y necesitan saber si en un a
no determinado deber
an
festejar su cumplea
nos el da 1 de Marzo o efectivamente podr
an celebrarlo el da correcto.
Para solucionar este problema, se le pide a usted que cree una clase que permita representar diferentes fechas
bas
andose en el da, mes y a
no.
Se debe validar que al crear una fecha la misma quede en un estado consistente, para ello usted puede asumir
que el a
no es correcto pero no sucede as con el mes y los das, ya que los mismos se encuentran en un rango
de 1 a 12 para el primer caso y 1 a 28-31 (dependiendo del mes y a
no) en el segundo caso.
En detalle, usted deber
a:
Crear una clase que represente la fecha junto a sus atributos.
Crear un metodo de esa clase que devuelva si el a
no es o no bisiesto.
Crear en esa clase todos los metodos necesarios para validar los das y meses. Recuerde que para validar
los das debe tener en cuenta el mes y si el a
no es bisiesto.
Luego de definir la clase Fecha usted debe escribir el metodo main en donde:
Se le pida al usuario el da, mes y a
no de dos fechas.

Se creen dos objetos de la clase fecha con estos datos.


Se imprima en consola si las fechas son o no v
alidas.

Se muestre una ventana indicando si alguna de las dos fechas pertenece a un a


no bisiesto.
Nota:
1. Recuerde que un a
no es bisiesto si es divisible por 4, excepto el u
ltimo de cada siglo (aquel divisible
por 100), salvo que este u
ltimo sea divisible por 400.
2. Los meses: Enero, Marzo, Mayo, Julio, Agosto, Octubre y Diciembre tienen 31 das, el resto tienen 30,
excepto Febrero que puede tener 28 o 29.
Criterios de soluci
on
Lo primero que debemos hacer es crear la clase Fecha con los atributos y metodos necesarios.
Atributos: Debemos almacenar el da, el mes y el a
no. Todos enteros.
Metodo para identificar si es un a
no bisiesto: Este metodo debe recibir como par
ametro el a
no y revisar
si dicho a
no es divisible por 400 o si es divisible por 4 pero no divisible por 100 a la vez. Si se cumple
lo anterior el metodo retorna true, de lo contrario retorna false.
Metodos para comprobar que la fecha sea v
alida: Para esto se puede crear s
olo un metodo o varios.
Debemos validar el mes, que se encuentre entre 1 y 12. Luego debemos validar el da, seg
un el mes y
seg
un si es a
no bisiesto o no. Finalmente el metodo debe retornar si la fecha es v
alida o no.
Despues de terminar la clase Fecha debemos implementar el metodo main:
Pedir al usuario los datos para dos fechas distintas (da, mes y a
no para dos fechas)
Crear las dos fechas seg
un los datos ingresados por el usuario, llamando al constructor de la clase Fecha

IIC1103 Captulo 4: Clases

32

Llamar a los metodos necesarios para comprobar ambas fechas y mostrar un mensaje al usuario indicando si son validas o no.
Llamar al metodo que indica si el a
no es bisiesto y seg
un lo retornado por el metodo mostrar un
mensaje al usuario, para cada una de las fechas.
Posible Soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class Fecha {
private int dia ;
private int mes ;
private int anio ;
public Fecha ( int elDia , int elMes , int elAnio ) {
dia = elDia ;
mes = elMes ;
anio = elAnio ;
}
public void c o m p r o b a r F e c h a () {
int testDia = 0;
int testMes = this . c o m p r o b a r M e s( mes );
if ( testMes != -1) {
if ( e s B i s i e s t o( anio )) {
testDia = this . c o m p r o b a r D i a( dia , 28);
} else {
testDia = this . c o m p r o b a r D i a( dia , 29);
}
if ( testDia != -1) {
Usuario . mensaje ( " Fecha valida " );
} else {
Usuario . mensaje ( " Fecha invalida " );
}
} else {
Usuario . mensaje ( " Fecha invalida " );
}
}
private int c o m p r o b a r D i a( int elDia , int unDia ) {
if ( mes == 2) {
if ( elDia <= unDia && elDia >= 1) {
return mes ;
} else {
return -1;
}
} else {
if ( mes == 2 || mes == 4 || mes == 6 || mes == 9 || mes == 11) {
if ( elDia <= 30 && elDia >= 1) {
return mes ;
} else {
return -1;
}
} else {
if ( elDia <= 31 && elDia >= 1) {
return mes ;
} else {
return -1;
}
}
}
}
public boolean e s B i s i e s t o( int elAnio ) {
if (( elAnio % 400 == 0) || (( elAnio % 4 == 0) && ( elAnio % 100 != 0))) {
return true ;
} else {
return false ;
}
}

IIC1103 Captulo 4: Clases

33

private int c o m p r o b a r M e s( int elMes ) {


if ( elMes >= 1 && elMes <= 12) {
return elMes ;
} else {
return -1;
}
}
public int getDia () {
return dia ;
}
public void setDia ( int dia ) {
this . dia = dia ;
}
public int getMes () {
return mes ;
}
public void setMes ( int mes ) {
this . mes = mes ;
}
public int getAnio () {
return anio ;
}
public void setAnio ( int anio ) {
this . anio = anio ;
}
}
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
int dia1 = Usuario . entero (" Dia fecha 1 " );
int mes1 = Usuario . entero (" Mes fecha 1 " );
int anio1 = Usuario . entero ( " Anio fecha 1 " );
int dia2 = Usuario . entero (" Dia fecha 2 " );
int mes2 = Usuario . entero (" Mes fecha 2 " );
int anio2 = Usuario . entero ( " Anio fecha 2 " );
Fecha f1 = new Fecha ( dia1 , mes1 , anio1 );
Fecha f2 = new Fecha ( dia2 , mes2 , anio2 );
f1 . c o m p r o b a r F e c h a ();
f2 . c o m p r o b a r F e c h a ();
if ( f2 . e s B i s i e s t o( f2 . getAnio ())) {
Usuario . mensaje ( " Es bisiesto debe festejar su c u m p l e a n i o s n o r m a l m e n t e " );
}
if ( f1 . e s B i s i e s t o( f2 . getAnio ())) {
Usuario . mensaje ( " Es bisiesto debe festejar su c u m p l e a n i o s n o r m a l m e n t e" );
}
}
}

IIC1103 Captulo 4: Clases

34

Problema 15: Relojes


Enunciado
Un fabricante de relojes quiere evitar la compleja mec
anica de engranajes necesaria para lograr que un reloj
coloque sus tres agujas (horario, minutero y segundero) en el angulo correcto. Para ello, le ha pedido hacer una
clase que mantenga la hora exacta y le permita acceder a un valor en grados que indique d
onde se encuentran
las distintas manillas. Usted deber
a implementar dicha clase de acuerdo a las siguientes consideraciones:
El relojero deber
a ser capaz de asignar un valor inicial al reloj, pero tambien deber
a ser capaz de
cambiar manualmente los segundos, minutos u horas. Si por alg
un motivo el relojero enviara un valor
inv
alido, el reloj no debe fallar, sino utilizar el mnimo valor posible que sea v
alido (por ejemplo, si se
ingresan 80 segundos, colocar 0 segundos).
Para que la clase mantenga el reloj interno al da, el relojero se compromete a llamar a alguna funci
on
que la clase le provea cada vez que pasa un segundo, permitiendo que el reloj se actualice.
El relojero deber
a recibir los grados de las agujas cuando lo requiera, estando estos entre 0 y 360
(el relojero no ser
a capaz de interpretar -30 ). Los grados est
an definidos como en un transportador
com
un (con el 0 en la horizontal), es decir, de forma tal si el horario marca las 12 se encuentra en 90 ,
mientras que a las 3 se encuentra en 0 .
Adicionalmente, y dado que el reloj ya est
a programado, el relojero quiere poder agregar una peque
na
pantalla display digital que muestre la hora como un texto en formato hh:mm:ss. Este texto deber
a ser
obtenido tambien desde su clase cuando el relojero lo estime conveniente.
Al relojero no le importa si las agujas del reloj se mueven en forma continua o discreta, por lo que ello
queda a discreci
on suya. Por ejemplo, el horario podra dar un salto entre una hora y otra o moverse
gradualmente.
Dise
ne la clase Reloj de tal forma que cumpla con todo lo pedido. Defina la representaci
on interna como
le parezca razonable e incluya todos los elementos que estime conveniente. No es necesario que agregue un
main() para probar su clase ni que tenga interacci
on alguna con el usuario, limtese a proveer lo que el
relojero necesita para poder construir su reloj.
Criterios de soluci
on
Hay muchas maneras de resolver el problema. Aqu s
olo presentaremos una posible soluci
on.
Lo primero que tenemos que hacer es identificar los atributos. Como debemos guardar la hora exacta lo m
as
l
ogico es tener tres variables (enteros) que representen la hora, los minutos y los segundos.
Luego nos dicen que el relojero deber
a ser capaz de asignar un valor inicial al reloj. Para esto podemos crear
un constructor que reciba como par
ametro la hora, minutos y segundos iniciales, y los asigne a los atributos
correspondientes. Revisando que sean valores v
alidos.
Adem
as nos dicen que el relojero debe poder cambiar manualmente los minutos, segundos y horas, para lo
cual podemos crear metodos para cambiar lo valores de estos atributos, siempre revisando que queden con
valores v
alidos.
Siguiendo con el enunciado nos piden implementar un metodo que avance un segundo cada vez que sea
llamado. Para esto el metodo debe aumentar en uno los segundos y revisar si es necesario aumentar tambien
los minutos o las horas cuando corresponda, manteniendo as la hora actual.
El relojero tambien debe poder recibir los grados de las agujas cuando lo requiera. Para esto podemos
implementar 3 metodos que retornen el grado del minutero, del segundero y el horario, haciendo la relaci
on
de d
onde se encuentra como si estuviera midiendose en un transportador.
Finalmente debemos implementar un metodo que retorne un String que contenga las horas seguido de un
:, luego los minutos seguido de otro :, terminando con los segundos.
IIC1103 Captulo 4: Clases

35

Posible Soluci
on
public class Reloj {
private int horas ;
private int minutos ;
private int segundos ;
/* *
* C o n s t r u y e un reloj .
*
* @param hora
*
De 0 a 23
* @param minuto
*
De 0 a 59
* @param segundo
*
De 0 a 59
*/
public Reloj ( int hora , int minuto , int segundo ) {
setHoras ( hora );
s e t M i n u t o s( minuto );
s e t S e g u n d o s( segundo );
}
/* * Avanza el tiempo del reloj en un segundo . */
public void a v a n z a r S e g u n d o () {
segundos ++;
if ( segundos >= 60) {
segundos = 0;
minutos ++;
}
if ( minutos >= 60) {
minutos = 0;
horas ++;
}
if ( horas >= 24) {
horas = 0;
}
}
/* *
* @return Los grados en donde debe estar p o s i c i o n a d a la aguja horaria .
*/
public int g r a d o s H o r a r i o() {
return (450 - 30 * ( horas % 12)) % 360;
}
/* *
* @return Los grados en donde debe estar p o s i c i o n a d o el minutero .
*/
public int g r a d o s M i n u t e r o() {
return (450 - 6 * minutos ) % 360;
}
/* *
* @return Los grados en donde debe estar p o s i c i o n a d o el s e g u n d e r o.
*/
public int g r a d o s S e g u n d e r o () {
return (450 - 6 * segundos ) % 360;
}
/* *
* @param horas
*
the horas to set
*/
public void setHoras ( int horas ) {
this . horas = horas ;
if ( horas < 0 || horas >= 24) {
horas = 0;
}
}
/* *
* @param minutos
*
the minutos to set
*/
public void s e t M i n u t o s( int minutos ) {
this . minutos = minutos ;

IIC1103 Captulo 4: Clases

36

if ( minutos < 0 || minutos >= 60) {


minutos = 0;
}
}
/* *
* @param segundos
*
the segundos to set
*/
public void s e t S e g u n d o s( int segundos ) {
this . segundos = segundos ;
if ( segundos < 0 || segundos >= 60) {
segundos = 0;
}
}
/* *
* @return El tiempo actual del reloj , en formato " hh : mm : ss "
*/
public String g e t T i e m p o() {
return horas + " : " + minutos + " : " + segundos ;
}
}

IIC1103 Captulo 4: Clases

37

Problema 16: Ruleta


Enunciado
Una ruleta permite que dos jugadores realicen apuestas, para luego lanzar la bolita y, seg
un el valor encontrado, pagar lo correspondiente a la apuesta. Los pagos son los siguientes:
N
umero si el n
umero apostado por el jugador es igual al n
umero entregado por la ruleta, el jugador
gana 16 veces lo que aposto.
Color si el color del n
umero apostado por el jugador es igual al color del n
umero obtenido, el jugador
gana 1.8 veces lo que aposto.
Lnea si el n
umero del jugador se encuentra en la misma lnea del n
umero obtenido, el jugador gana
3.5 veces lo apostado.
Haga un programa que permita utilizar una ruleta obteniendo los n
umeros de forma aleatoria 4 . Su programa
debe permitir al usuario ingresar la cantidad de n
umeros en la ruleta, exigiendo que este valor sea m
ultiplo
de 4 y se encuentre en el rango [16, 36]. Despues el usuario debe ingresar los nombres de ambos jugadores y
el dinero inicial que poseen (el mismo para ambos).
Finalmente su programa debe permitir realizar apuestas hasta que uno de los jugadores pierda (se quede sin
dinero) o hasta que uno de ellos logre multiplicar por 50 el dinero recibido inicialmente. En cada iteraci
on
cada jugador debe elegir un n
umero y un monto a apostar (el cual no puede ser mayor al dinero que le
queda). Al finalizar su programa debe mostrar quien es el ganador y la cantidad de dinero que queda en la
ruleta (para ello asuma que la ruleta parte con 10 veces el dinero que parten los jugadores).
Para la ruleta considere que comienza desde el 0 (el cual no tiene color), y que todos los impares son negros
y los pares mayores que 0 son blancos. Adem
as considere que las lneas son formadas verticalmente por 4
n
umeros consecutivos a partir del 1 (el 0 forma una u
nica lnea). Por ejemplo los n
umeros 1, 2, 3 y 4 forman
una lnea, de la misma forma que lo hacen los n
umeros 9, 10, 11 y 12.
Para la resoluci
on del problema utilice m
as de una clase.
Criterios de soluci
on
Hay muchas soluciones distintas para el problema, s
olo mostraremos una de ellas.
Del enunciado podemos deducir que hay 2 clases : la Ruleta y un Jugador. Adem
as de una clase Principal
que maneje estas dos clases para llevar a cabo el juego.
1. Clase Jugador:
Un Jugador se caracteriza por un nombre y el dinero que tiene, por lo que estos seran los atributos
de la clase. Incluimos un constructor que reciba como parametro estos valores y adem
as para poder
manejar los atributos podemos incluir getters y setters.
Adem
as de esto podemos incluir en la clase Jugador los metodos que pidan el monto de la apuesta
y el n
umero a apostar. Estos metodos piden al usuario que ingrese un valor para la apuesta y otro
para el n
umero elegido, revisan que los valores ingresados sean v
alidos y asignan dicho valor al
atributo correspondiente.
Para terminar con la clase debemos implementar un metodo que permita actualizar el dinero,
aument
andolo en una cierta cantidad.
2. Clase Ruleta:
Esta clase representa el juego de la Ruleta, el cual se caracteriza por el n
umero obtenido, los dos

jugadores y el dinero que tiene la mesa. Estos


son los atributos de la clase.
4 Utilice

el m
etodo Aleatorio.entero(int a, int b) que retorna un n
umero aleatorio en el rango [a, b].

IIC1103 Captulo 4: Clases

38

Para iniciar el juego necesitamos implementar un constructor que reciba valores para los atributos
y los asigne.
Adem
as podemos implementar un metodo que revise las ganancias del jugador comparando con el
n
umero de la ruleta y el n
umero al que el jugador apost
o, retornando el monto ganado o perdido.
Finalmente debemos implementar un metodo que implemente la l
ogica del juego: Pida a los
jugadores su apuesta y el monto a apostar (utilizando los metodos de la clase Jugador). Genere el
n
umero de la ruleta aleatoriamente. Revise los resultados y actualice las ganancias de los jugadores.
Repita todo lo anterior mientras el dinero de cada jugador se mantenga en el rango establecido y
cuando termine muestre el nombre del jugador que gana.
3. Clase Principal:
Esta clase debe tener el metodo main el cual pida los datos necesarios al usuario para crear los
dos jugadores y el n
umero de casillas de la ruleta. Cree los dos jugadores y la ruleta y finalmente
llame al metodo de la clase Ruleta que implementa la l
ogica del juego. Mostrando al final del
juego el nombre del jugador ganador.
Posible Soluci
on
public class Jugador {
private String nombre ;
private int dinero ;
public Jugador ( String n , int d ) {
nombre = n ;
dinero = d ;
}
public int e l e g i r M o n t o A p u e s t a () {
int apuesta = Usuario . entero ( nombre + " , cuanto desea apostar ? " );
while ( apuesta <= 0 || apuesta > dinero ) {
apuesta = Usuario . entero ( nombre + " , cuanto desea apostar ? " );
}
return apuesta ;
}
public int e l e g i r N u m e r o A p u e s t a( int max ) {
int numero = Usuario . entero ( nombre + " , a que numero desea apostar ? " );
while ( numero <= 0 || numero > max ) {
numero = Usuario . entero ( nombre + " , a que numero desea apostar ? " );
}
return numero ;
}
public String g e t N o m b r e() {
return nombre ;
}
public int g e t D i n e r o() {
return dinero ;
}
public void a c t u a l i z a r D i n e r o( int delta ) {
dinero += delta ;
}
}

IIC1103 Captulo 4: Clases

39

public class Ruleta {


private int n u m e r o M a x;
private Jugador jug1 ;
private Jugador jug2 ;
private int dinero ;
public Ruleta ( Jugador j1 , Jugador j2 , int d , int max ) {
n u m e r o M a x = max ;
jug1 = j1 ;
jug2 = j2 ;
dinero = d ;
}
public String c o m e n z a r A p u e s t a s( int limite ) {
while ( jug1 . g e t D i n e r o() > 0 && jug1 . g e t D i n e r o() < limite
&& jug2 . g e t D i n e r o() > 0 && jug2 . g e t D i n e r o() < limite ) {
int montoJ1 = jug1 . e l e g i r M o n t o A p u e s t a ();
int numeroJ1 = jug1 . e l e g i r N u m e r o A p u e s t a( n u m e r o M a x);
int montoJ2 = jug2 . e l e g i r M o n t o A p u e s t a ();
int numeroJ2 = jug2 . e l e g i r N u m e r o A p u e s t a( n u m e r o M a x);
int num = A l e a t o r i o. entero (0 , n u m e r o M a x);
int g a n a n c i a J 1 = r e v i s a r A p u e s t a( num , numeroJ1 , montoJ1 );
int g a n a n c i a J 2 = r e v i s a r A p u e s t a( num , numeroJ2 , montoJ2 );
dinero -= ( g a n a n c i a J 1 + g a n a n c i a J 2);
jug1 . a c t u a l i z a r D i n e r o( g a n a n c i a J 1);
jug2 . a c t u a l i z a r D i n e r o( g a n a n c i a J 2);
}
if ( jug1 . g e t D i n e r o() >= limite || jug2 . g e t D i n e r o() == 0) {
return jug1 . g e t N o m b r e ();
} else {
return jug2 . g e t N o m b r e ();
}
}
public int r e v i s a r A p u e s t a( int numero , int seleccion , int monto ) {
if ( s e l e c c i o n == numero ) {
return 16 * monto ;
} else if (( s e l e c c i o n - 1) / 4 == ( numero - 1) / 4) {
return ( int ) (3.5 * monto );
} else if ( s e l e c c i o n % 2 == numero % 2) {
return ( int ) (1.8 * monto );
}
return - monto ;
}
public int g e t D i n e r o() {
return dinero ;
}
}
public class P r i n c i p a l {
public static void main ( String [] args ) {
String n1 = Usuario . texto (" Nombre jugador 1? " );
String n2 = Usuario . texto (" Nombre jugador 2? " );
int dinero = Usuario . entero ( " Dinero inicial para j u g a d o r e s? " );
int max = Usuario . entero ( " Casillas de la ruleta ? " );
while ( max < 16 || max > 36 || max % 4 != 0) {
max = Usuario . entero ( " Debe ser multiplo de 4. Casillas de la ruleta ? " );
}
Jugador j1 = new Jugador ( n1 , dinero );
Jugador j2 = new Jugador ( n2 , dinero );
Ruleta ruleta = new Ruleta ( j1 , j2 , 10 * dinero , max );
String ganador = ruleta . c o m e n z a r A p u e s t a s (50 * dinero );
Usuario . mensaje ( " Gano : " + ganador + " . Ruleta tiene " + ruleta . g e t D i n e r o ());
}
}

IIC1103 Captulo 4: Clases

40

Problema 17: Piso de Estacionamientos


Enunciado
Debe implementar el metodo main de un programa que permite manejar un edificio de estacionamientos,
el cual tiene varios pisos para que los vehculos puedan estacionarse. Las siguientes clases ya vienen implementadas.
public class Vehiculo {
// C o n s t r u c t o r de la clase , recibe la patente y el tipo que puede ser :
// 0: auto normal , 1: lisiado , utiliza dos e s t a c i o n a m i e n t o s , 2: camion ,
// utiliza 4 e s t a c i o n a m i e n t o s
public Vehiculo ( String patente , int tipo ) {...}
public String g e t P a t e n t e() {...}
public int getTipo () {...}
// Indica la cantidad de e s t a c i o n a m i e n t o s n e c e s a r i o s para el vehiculo segun
// el tipo c o r r e s p o n d i e n t e .
public int c u p o s N e c e s a r i o s () {...}
}
public class Piso {
// C o n s t r u c t o r de la clase . Recibe la c a p a c i d a d de e s t a c i o n a m i e n t o s y si
// esta p e r m i t i d o o no e s t a c i o n a r camiones en este piso .
public Piso ( int c a p a c i d a d , boolean camiones ){...}
// Indica la cantidad de e s t a c i o n a m i e n t o s ocupados
public int c u p o s U t i l i z a d o s (){...}
// Permite agregar un nuevo vehiculo para que se e s t a c i o n e . Retorna true
// si es posible e s t a c i o n a r l o .
public boolean a g r e g a r V e h i c u l o ( Vehiculo nuevo ) {...}
// Permite buscar un vehiculo segun su patente . Si el vehiculo no se
// e n c u e n t r a en el piso , entonces retorna null .
public Vehiculo buscar ( String patente ) {...}
}
public class E s t a c i o n a m i e n t o {
// C o n s t r u c t o r de la clase , recibe el numero maximo de pisos que puede
// tener .
public E s t a c i o n a m i e n t o ( int maxPisos ){...}
// Permite agregar un nuevo piso a la torre de e s t a c i o n a m i e n t o s . Retorna
// false si no quedaran espacios para hacerlo .
public boolean a g r e g a r P i s o ( Piso piso ){...}
// Retorna la cantidad de pisos
public int g e t N u m P i s o s (){...}
// Retorna el piso indicado por el indice recibido ( p a r t i e n d o desde 0). Si
// no existe , retorna null .
public Piso o b t e n e r P i s o ( int indice ){...}
}

.
El metodo main que usted debe implementar debe realizar lo siguiente:
1. Crear una torre de estacionamientos para un m
aximo de 5 pisos.
2. Pedir al usuario una cantidad de pisos para agregar a la torre.
3. Para cada piso, pedir al usuario la informaci
on necesaria para crearlo y agregarlo al edificio de estacionamientos. En caso de no poder agregarlo mostrarle un mensaje en consola al usuario indicando esta
situacion.
4. Seleccionar un n
umero random en el rango [10, 100] que indicar
a la cantidad de vehculos que llegar
an.

IIC1103 Captulo 4: Clases

41

5. Para cada vehculo pedir al usuario la patente y obtener aleatoriamente el tipo de vehculo (auto
normal, lisiado o cami
on).
6. Intentar agregar el vehculo a alguno de los pisos de la torre de estacionamientos. Si no es posible
agregarlo en ninguno de los pisos, se debe mostrar un mensaje consola indicando al usuario la patente
del vehculo que no se pudo agregar.
7. Por u
ltimo debe buscar en que piso se encuentra el vehculo de patente BCBC22, y mostrar en consola
el ndice del piso. Si no es posible encontrarlo debe mostrar un mensaje en consola indicando esto.
Criterios de soluci
on
El enunciado es bastante estructurado. Tenemos que ir realizando paso a paso lo que se nos pide:
Llamar al constructor de la clase Estacionamiento pasando como par
ametro un 5, que corresponde a
los 5 pisos que tendr
a el estacionamiento.
Pedir al usuario la cantidad de pisos y guardar el valor ingresado en una variable.
Implementar un ciclo que permita ir creando cada uno de los pisos y agregarlo al estacionamiento.
Dentro del ciclo pedir al usuario la capacidad del piso y si acepta camiones. Crear un nuevo piso con
los valores ingresados por el usuario. Llamar al metodo agregarP iso de la clase Estacionamiento
pasando como par
ametro el piso recien creado. Revisar lo retornado por el metodo y, si no pudo
agregarse, mostrar un mensaje al usuario indic
andolo.
Generar aleatoriamente el n
umero de vehculos que llegar
an.
Implementar un ciclo para crear los vehculos que llegan.
Dentro del ciclo pedir al usuario la patente del auto y generar aletoriamente el tipo. Crear un objeto
de la clase V ehiculo con los datos.
Luego de crear el vehculo implementar un ciclo que intente agregarlo a alg
un piso.
Dentro de este ciclo obtener cada uno de los pisos y llamar al metodo agregarV ehiculo de la clase
P iso. Revisar lo retornado por el metodo para identificar si se pudo agregar.
Si no se pudo agregar a ning
un piso mostrar un mensaje informando al usuario.
Implementar ciclo para buscar en cada uno de los pisos la patente BCBC22.
Dentro del ciclo obtener cada uno de los pisos del estacionamiento. Llamar al metodo buscar de la
clase P iso con la patente buscada. Revisar lo retornado por el metodo para determinar si se encontr
o.
Mostrar un mensaje al usuario indicando si se encontr
o o no.

IIC1103 Captulo 4: Clases

42

Posible Soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
// Creamos el e s t a c i o n a m i e n t o
E s t a c i o n a m i e n t o parking = new E s t a c i o n a m i e n t o (5);
// Creamos y a g r e g a m o s los pisos , pidiendo la i n f o r m a c i o n al usuario
int numPisos = Usuario . entero ( " Ingrese la cantidad de pisos , max . 5. " );
while ( numPisos < 1 || numPisos > 5) {
numPisos = Usuario . entero ( " Ingrese la cantidad de pisos , max . 5. " );
}
for ( int i = 0; i < numPisos ; i ++) {
// Pedimos i n f o r m a c i o n al usuario
int cap = Usuario . entero ( " C a p a c i d a d del piso " );
int camiones = Usuario . entero ( " Este piso acepta camiones ?\ n (0) No \ n (1) Si " );
boolean a c e p t a C a m i o n e s = true ;
if ( camiones == 0) {
a c e p t a C a m i o n e s = false ;
}
// I n t e n t a m o s agregar el piso al edificio de e s t a c i o n a m i e n t o s .
if (! parking . a g r e g a r P i s o( new Piso ( cap , a c e p t a C a m i o n e s ))) {
Usuario . m e n s a j e C o n s o l a( " No fue posible agregar el piso . " );
}
}
// Ahora creamos los autos que llegaran al e s t a c i o n a m i e n t o
int numAutos = A l e a t o r i o. entero (10 , 100);
for ( int i = 0; i < numAutos ; i ++) {
// Pedimos la patente al usuario , y el tipo es random
String patente = Usuario . texto ( " Ingrese patente " );
int tipo = A l e a t o r i o. entero (0 , 2);
Vehiculo vehiculo = new Vehiculo ( patente , tipo );
// Buscamos un piso para a g r e g a r l o
boolean agregado = false ;
for ( int j = 0; j < parking . g e t N u m P i s o s() && ! agregado ; j ++) {
// O b t e n e m o s el piso
Piso piso = parking . o b t e n e r P i s o( j );
// I n t e n t a m o s a g r e g a r l o
if ( piso . a g r e g a r V e h i c u l o( vehiculo )) {
agregado = true ;
}
}
if (! agregado ) {
Usuario . m e n s a j e C o n s o l a( " No fue posible agregar el vehiculo : "
+ vehiculo . g e t P a t e n t e ());
}
}
// Buscamos si esta el vehiculo BCBC22 , i n d i c a m o s el piso
boolean e n c o n t r a d o = false ;
for ( int i = 0; i < parking . g e t N u m P i s o s() && ! e n c o n t r a d o; i ++) {
Piso piso = parking . o b t e n e r P i s o( i );
if ( piso . buscar ( " BCBC22 " ) != null ) {
Usuario . m e n s a j e C o n s o l a( " BCBC22 se e n c u e n t r a en el piso " + i );
e n c o n t r a d o = true ;
}
}
if (! e n c o n t r a d o) {
Usuario . m e n s a j e C o n s o l a( " BCBC22 no se e n c u e n t r a . " );
}
}
}

IIC1103 Captulo 4: Clases

43

Problema 18: Rendimiento combustible


Enunciado
Usted deber
a realizar un programa que permita probar el rendimiento de combustible de autos, de modo de
ver el rendimiento a distintas velocidades y los consumos para distintas distancias.
Deber
a crear la clase Auto la cual representara un auto dentro de su programa. Cada auto estar
a caracterizado por el tama
no de su estanque (en litros), el combustible que hay en el estanque, el rendimiento
del combustible (representado en km/lt), la velocidad para conseguir el rendimiento ideal (en km/h) y los
kilometros recorridos.
Su clase debe tener los siguientes metodos:
Auto(double tamEstanque, double rendimiento, double velIdeal) constructor de la clase,
recibe como parametros el tama
no del estanque, el rendimiento del combustible y la velocidad para el
rendimiento ideal. El combustible en el estanque y los kil
ometros recorridos comienzan en 0.
double echarBencina(double litros) permite poner combustible al vehculo. Recibe la cantidad
de combustible que se quiere poner, y pone el m
aximo posible, limitado por la cantidad recibida, por
la cantidad actual en el estanque y por el tama
no de este. Retorna la cantidad real de combustible
puesto en el estanque5 .
double calcularRendimiento(double vel) calcula y retorna el rendimiento de combustible para
una velocidad determinada. Este rendimiento se calcula utilizando la siguiente f
ormula:
R(Vi ) = R(V )

fV
V

d
onde:

R(Vi ) es el rendimiento para la velocidad Vi ,


R(V ) es el rendimiento ideal,
V es la velocidad ideal,
f V es el factor de velocidad, el cual se calcula de la siguiente forma:
fV = V

|(V Vi )|2
d

donde d es el divisor, el cual es 8 si Vi < V o 10 si Vi > V


double calcularConsumo(double vel, double kms) calcula y retorna el consumo de litros de
combustible para una velocidad determinada y una distancia definida.
boolean avanzar(double kms, double velPromedio, double desvEst) permite avanzar una
cierta distancia el auto, recibiendo la distancia, la velocidad promedio utilizada, y la desviaci
on est
andar
de las velocidades utilizadas. Antes de ello verifica que haya combustible suficiente, en caso de no haberlo retorna false y no realiza cambios en el auto. El combustible consumido se calcula asumiendo
que un octavo de la distancia se recorre en la velocidad promedio menos la desviaci
on est
andar, otro
octavo en la velocidad promedio m
as la desviacion est
andar, y el resto en la velocidad promedio. Cuando es posible realizar el avance se disminuye el combustible, se actualiza el od
ometro (medidor de
kilometraje) y se retorna true.
void mostrarRendimientos(int minVel, int maxVel, int p) muestra los rendimientos del auto para distintas velocidades en el rango [minV el, maxV el], utilizando el valor p como avance entre
una velocidad y otra. Para cada velocidad debe mostrar un mensaje como el que sigue:
Vel: 60 km/h = 8.25 km/lt
5 Por

definici
on,
esta siempre debe ser menor o igual al valor recibido.

IIC1103 Captulo 4: Clases

44

void mostrarEstado() muestra el estado del auto, el cual est


a representado por su od
ometro y la
cantidad de combustible que posee en el estanque.
Adem
as deber
a realizar un metodo main que realice lo siguiente:
Pida al usuario la informaci
on necesaria para crear dos autos.
Luego muestre un men
u al usuario con las siguientes opciones:
1. Trabajar con auto 1 permite realizar acciones sobre el auto 1, las opciones son las siguientes:
a) Poner combustible permita agregar combustible al auto. Pide al usuario los litros que se
quieren agregar e informa en un mensaje los litros reales que se agregaron.
b) Avanzar permite avanzar el auto, pidiendo al usuario los kil
ometros, la velocidad promedio
y la desviaci
on est
andar de la velocidad. Luego, muestra si pudo o no avanzar el auto.
c) Ver estado muestra el estado del auto a traves del metodo mostrarEstado.
d ) Volver vuelve al men
u principal.
2. Trabajar con auto 2 lo mismo que la opci
on anterior, pero con el auto 2.
3. Comparar rendimientos pide al usuario una velocidad mnima y m
axima y el paso y muestra
los rendimientos para esos valores de ambos autos.
4. Salir termina el programa.
Criterios de soluci
on
El enunciado es bastante estructurado, por lo que tenemos que ir realizando paso a paso lo que se nos pide.
1. Clase Auto
Lo primero que tenemos que hacer es declarar la clase con sus atributos. Del enunciado vemos que
debe tener como atributos: tama
no del estanque, combustible que hay en el estanque, rendimiento,
velocidad para conseguir rendimiento ideal y kil
ometros recorridos. Todos pueden representarse
por variables de tipo double
Constructor: Lo declaramos tal como nos indican en el enunciado. En el metodo asignamos los
valores recibidos como par
ametro a los atributos correspondientes.
Metodo echarBencina: Lo declaramos tal como nos indican en el enunciado. Tenemos que revisar
si el espacio en el estanque es suficiente para los litros que se quieren agregar. Si el espacio es
suficiente, actualizamos la cantidad de combustible y retornamos el mismo valor recibido como
par
ametro. Si el espacio no es suficiente, aumentamos el combustible hasta lo que se pueda y
retornamos lo que realmente se pudo echar.
Metodo calcularRendimiento: Lo declaramos tal como nos indican en el enunciado. Tenemos
que revisar si la velocidad recibida como parametro es mayor o no a la velocidad ideal, y seg
un
esto determinamos si el divisor es 8 o 10. Luego calculamos el factor velocidad seg
un la ecuaci
on
presentada en el enunciado. Calculamos el rendimiento seg
un el factor calculado y lo retornamos.
Metodo calcularConsumo: Lo declaramos tal como nos indican en el enunciado. Primero debemos
calcular el rendimiento, para esto utilizamos el metodo calcularRendimiento implementado anteriormente. Luego calculamos el consumo dividiendo los kil
ometros por el rendimiento obtenido.
Retornamos el consumo.
Metodo avanzar: Lo declaramos tal como nos indican en el enunciado. Calculamos los litros que
debemos consumir, llamando al metodo calcularConsumo, pas
andole los par
ametros correctos
para recorrer un octavo del recorrido en velocidad mnima, un octavo en velocidad m
axima y
el resto en velocidad promedio. Revisamos si hay combustible suficiente. Si no hay suficiente
combustible retornamos false, en caso contrario, actualizamos el od
ometro y el combustible y
retornamos true.
IIC1103 Captulo 4: Clases

45

Metodo mostrarRendimiento: Lo declaramos tal como nos indican en el enunciado. Para mostrar
las distintas velocidad podemos utilizar un ciclo (un f or por ejemplo) que vaya avanzando la
velocidad seg
un el par
ametro p. Para cada velocidad calculamos el rendimiento llamando al metodo
calcularRendimiento y lo mostramos en un mensaje.
Metodo mostrarEstado: Lo declaramos tal como nos indican en el enunciado. Mostramos en un
mensaje el valor que tienen los atributos: od
ometro y combustible.
2. Clase P rincipal: Metodo main
Pedimos al usuario el tama
no del estanque, rendimiento y velocidad ideal para cada uno de los
autos.
Creamos dos objetos de la clase Auto con los datos ingresados por el usuario.
Implementamos un ciclo para mostrar el men
u con las opciones, que no termine hasta el que
usuario ingrese la opci
on Salir.
Revisamos la opcion ingresada y determinamos con cu
al de los dos autos se trabajar
a.
Implementamos otro ciclo para mostrar el men
u con las opciones para un auto especfico.
Revisamos la opcion ingresada por el usuario y llamamos al metodo de la clase Auto que corresponda seg
un la opci
on, pidiendo al usuario los valores necesarios para pasar como parametro al
metodo.
Opci
on Comparar Rendimiento: Llamamos al metodo mostrarRendimiento de cada uno de los
autos.
Posible Soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class Auto {
private double t a m E s t a n q u e;
private double c o m b u s t i b l e;
private double r e n d i m i e n t o;
private double v e l R e n d i m i e n t o I d e a l;
private double odometro ;
public Auto ( double tamEstanque , double rendimiento ,
double v e l R e n d i m i e n t o I d e a l) {
// I n i c i a l i z a m o s todos los a t r i b u t o s de la clase
this . t a m E s t a n q u e = t a m E s t a n q u e;
this . c o m b u s t i b l e = 0;
this . r e n d i m i e n t o = r e n d i m i e n t o;
this . v e l R e n d i m i e n t o I d e a l = v e l R e n d i m i e n t o I d e a l;
this . odometro = 0;
}
public double e c h a r B e n c i n a( double litros ) {
// R e v i s a m o s si el espacio en el estanque es s u f i c i e n t e para los litros
// que se quieren echar .
if ( t a m E s t a n q u e - c o m b u s t i b l e > litros ) {
c o m b u s t i b l e += litros ;
return litros ;
} else {
// Si los litros son mas que el espacio disponible , llenamos el
// estanque y r e t o r n a m o s los litros reales u t i l i z a d o s.
double delta = t a m E s t a n q u e - c o m b u s t i b l e;
c o m b u s t i b l e = t a m E s t a n q u e;
return delta ;
}
}
public double c a l c u l a r R e n d i m i e n t o( double vel ) {
// C a l c u l a m o s el divisor segun si es mayor o menor a la v e l o c i d a d ideal
int div = 8;
if ( vel > v e l R e n d i m i e n t o I d e a l) {
div = 10;
}

IIC1103 Captulo 4: Clases

46

// C a l c u l a m o s el factor para la v e l o c i d a d actual en funcion de la v e l o c i d a d ideal


double f a c t o r V e l o c i d a d = v e l R e n d i m i e n t o I d e a l - Math . pow ( Math . abs ( v e l R e n d i m i e n t o I d e a l - vel ) / div , 2);
// Nos a s e g u r a m o s que el factor v e l o c i d a d nunca sea menor a un sexto de
// la v e l o c i d a d ideal .
if ( f a c t o r V e l o c i d a d < v e l R e n d i m i e n t o I d e a l / 6) {
f a c t o r V e l o c i d a d = v e l R e n d i m i e n t o I d e a l / 6;
}
// C a l c u l a m o s el r e n d i m i e n t o y luego lo r e t o r n a m o s
double rend = r e n d i m i e n t o * f a c t o r V e l o c i d a d / v e l R e n d i m i e n t o I d e a l;
return rend ;
}
public double c a l c u l a r C o n s u m o( double vel , double kms ) {
// C a l c u l a m o s el r e n d i m i e n t o y luego d i v i d i m o s la d i s t a n c i a en el
// r e n d i m i e n t o para obtener los litros
double rend = c a l c u l a r R e n d i m i e n t o( vel );
double consumo = kms / rend ;
return consumo ;
}
public boolean avanzar ( double kms , double velPromedio , double desvEst ) {
// C a l c u l a m o s los litros que debemos consumir
double litros = 0;
// Un octavo del r e c o r r i d o en v e l o c i d a d minima
litros += c a l c u l a r C o n s u m o( v e l P r o m e d i o - desvEst , kms / 8);
// Un octavo del r e c o r r i d o en v e l o c i d a d maxima
litros += c a l c u l a r C o n s u m o( v e l P r o m e d i o + desvEst , kms / 8);
// El resto en v e l o c i d a d promedio
litros += c a l c u l a r C o n s u m o( velPromedio , kms * 3 / 4);
// R e v i s a m o s si hay c o m b u s t i b l e s u f i c i e n t e
if ( c o m b u s t i b l e < litros ) {
return false ;
} else {
// A c t u a l i z a m o s el odometro y el c o m b u s t i b l e
odometro += kms ;
c o m b u s t i b l e -= litros ;
}
return true ;
}
public void m o s t r a r R e n d i m i e n t o s( int minVel , int maxVel , int paso ) {
Usuario . m e n s a j e C o n s o l a( " R e n d i m i e n t o Auto ( ideal : " + r e n d i m i e n t o
+ " km / lt , velIdeal : " + v e l R e n d i m i e n t o I d e a l + " km / h ) " );
// R e c o r r e m o s las d i s t i n t a s v e l o c i d a d e s m o s t r a n d o los r e n d i m i e n t o s para
// cada una de ellas
for ( int vel = minVel ; vel <= maxVel ; vel += paso )
Usuario . m e n s a j e C o n s o l a( " \ tVel : " + vel + " km / h = " + c a l c u l a r R e n d i m i e n t o( vel ) + " km / lt " );
}
public void m o s t r a r E s t a d o() {
// M o s t r a m o s los a t r i b u t o s d i n a m i c o s del vehiculo
Usuario . m e n s a j e C o n s o l a( " Estado del Vehiculo : " );
Usuario . m e n s a j e C o n s o l a( " \ t O d o m e t r o: " + odometro + " km " );
Usuario . m e n s a j e C o n s o l a( " \ t C o m b u s t i b l e: " + c o m b u s t i b l e + " lt " );
}
}

IIC1103 Captulo 4: Clases

47

import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
// Pedimos la i n f o r m a c i o n al usuario
double e s t a n q u e 1 = Usuario . real ( " Ingrese la
double r e n d i m i e n t o 1 = Usuario . real ( " Ingrese
double v e l I d e a l 1 = Usuario . real ( " Ingrese la
double e s t a n q u e 2 = Usuario . real ( " Ingrese la
double r e n d i m i e n t o 2 = Usuario . real ( " Ingrese
double v e l I d e a l 2 = Usuario . real ( " Ingrese la

c a p a c i d a d del estanque del auto 1 " );


el r e n d i m i e n t o en km / lt del auto 1 " );
v e l o c i d a d para el maximo r e n d i m i e n t o del auto 1 " );
c a p a c i d a d del estanque del auto 2 " );
el r e n d i m i e n t o en km / lt del auto 2 " );
v e l o c i d a d para el maximo r e n d i m i e n t o del auto 2 " );

// Creamos los dos autos


Auto a1 = new Auto ( estanque1 , rendimiento1 , v e l I d e a l 1);
Auto a2 = new Auto ( estanque2 , rendimiento2 , v e l I d e a l 2);
// Hacemos un ciclo para el menu
int opcion = 1;
while ( opcion > 0 && opcion < 4) {
opcion = Usuario . entero (" Elija una opcion :\ n (1) Trabajar con auto 1\ n "
+ " (2) Trabajar con auto 2\ n (3) Comparar r e n d i m i e n t o s\ n (4) Salir " );
if ( opcion == 1 || opcion == 2) { // Trabajar con auto 1 o 2
// Creamos una variable donde d e j a r e m o s el auto a utilizar
Auto auto = a1 ;
if ( opcion == 2) {
auto = a2 ;
}
int o p c i o n A u t o = 2;
while ( o p c i o n A u t o > 0 && o p c i o n A u t o < 4) {
o p c i o n A u t o = Usuario
. entero ( " Que desea hacer con el auto ?\ n (1) Poner c o m b u s t i b l e\ n "
+ " (2) Avanzar \ n (3) Ver estado \ n (4) Volver " );
if ( o p c i o n A u t o == 1) { // Poner c o m b u s t i b l e
double litros = Usuario . real ( " Cuantos litros desea poner ? " );
double ltReales = auto . e c h a r B e n c i n a( litros );
Usuario . mensaje ( " Se a g r e g a r o n " + ltReales + " litros al auto . " );
} else if ( o p c i o n A u t o == 2) { // Avanzar
double kms = Usuario . real ( " Cuantos k i l o m e t r o s desea avanzar ? " );
double v e l P r o m e d i o = Usuario . real ( " Cual fue la v e l o c i d a d promedio del avance ? " );
double desvEst = Usuario . real ( " Cual fue la d e s v i a c i o n estandar de la v e l o c i d a d u t i l i z a d a? " );
if (! auto . avanzar ( kms , velPromedio , desvEst )) {
Usuario . mensaje (" No fue posible avanzar los " + kms + " kms . " );
}
} else if ( o p c i o n A u t o == 3) { // Ver estado
auto . m o s t r a r E s t a d o();
}
}
} else if ( opcion == 3) { // Comparar r e n d i m i e n t o s
int minVel = Usuario . entero ( " Ingrese v e l o c i d a d minima : " );
int maxVel = Usuario . entero ( " Ingrese v e l o c i d a d maxima : " );
int paso = Usuario . entero ( " Ingrese paso para los i n t e r v a l o s: " );
a1 . m o s t r a r R e n d i m i e n t o s( minVel , maxVel , paso );
a2 . m o s t r a r R e n d i m i e n t o s( minVel , maxVel , paso );
}
}
}
}

IIC1103 Captulo 4: Clases

48

Problema 19: Tanques Militares


Enunciado
Usted deber
a realizar un programa que permita operar tanques militares en su nivel m
as b
asico, de modo
de ver sus desempe
nos a distintas distancias utilizando dos tipos de municiones diferentes.
Deber
a crear la clase Tanque la cual representara un tanque dentro de su programa. Un tanque se caracteriza
esencialmente por la capacidad m
axima de misiles y balas que puede cargar, y tambien por la eficiencia que
resulta de su configuraci
on. Asimismo, interesa la cantidad de misiles y balas que dispone en un determinado
instante, y tambien la cantidad de ataques que ha efectuado.
Su clase debe tener los siguientes metodos:
Tanque(int maxMisiles, int maxBalas, double eficiencia) constructor de la clase, recibe
como parametros capacidad m
axima de misiles (maxMisiles) y balas (maxBalas) que puede cargar y
la (eficiencia) que presenta. La eficiencia es un n
umero real en el intervalo abierto (0, 1), siendo m
as
eficiente (i.e. mejor puntera) en la medida que este par
ametro se acerque mas a 1.
int cargarMuniciones(boolean misil, int cantidad) agrega un determinado tipo de municiones a bordo del tanque. Si el par
ametro misil es true, entonces corresponder
a cargar misiles, y si es
false, seran balas. En ambos casos se debe respetar la restricci
on impuesta por la m
axima cantidad de
misiles y balas que el tanque puede cargar. En caso de que la cantidad que se desea agregar sea mayor
que la capacidad disponible en un determinado momento, se recarga hasta completar el respectivo
compartimento. Retorna la cantidad de municiones que se lograron recargar efectivamente.
int calcularDisparos(boolean misil, int distancia) calcula y retorna el n
umero de disparos
necesarios para derribar un blanco ubicado a una determinada distancia (en metros). Si el par
ametro
misil es true, entonces corresponder
a realizar el c
alculo suponiendo que se emplear
an misiles, y si es
false, seran balas. Las siguientes f
ormulas ayudan a determinar el n
umero buscado:
Si se emplear
an misiles, entonces se necesitar
a la siguiente cantidad de disparos:
NM =

1
)2 )
distancia (1 + ( ef iciencia

1000

Si se emplear
an balas, entonces se necesitar
a la siguiente cantidad de disparos:
NB = NM 120
boolean atacar(boolean misil, int distancia) permite atacar un blanco ubicado a una determinada distancia (en metros). Si el par
ametro misil es true, entonces corresponder
a atacar
utilizando misiles, y si es false, sera con balas. Si el blanco est
a ubicado a menos de 100 mts. o a m
as
de 5,000 mts., el tanque no realizar
a el ataque (por seguridad e incapacidad de alcance respectivamente). Asimismo, si el tanque no tiene disponible el tipo de munici
on con que se decide atacar, tampoco
lo realizar
a. En ambos casos, el metodo deber
a retornar false. Si la cantidad de disparos necesarios
para derribar el blanco es mayor que la cantidad disponible para el determinado tipo de munici
on,
ataca de todas formas aunque signifique un ataque no exitoso. Si, por el contrario, el tanque dispone
de al menos las municiones necesarias para derribar el blanco, entonces el ataque se realizara con exito.
En caso que ataque, deber
a descontar la cantidad correspondiente de municiones e informar en caso
de exito la cantidad de municiones empleadas, para finalmente retornar true.
void mostrarEstado() muestra en consola el estado del tanque en un determinado momento: su
eficiencia, la cantidad de misiles y balas disponibles para atacar, y si ha realizado uno o m
as ataques,
la cantidad de ataques, cu
antos de estos fueron exitosos, y el porcentaje de veces en que ha logrado
derribar el blanco
IIC1103 Captulo 4: Clases

49

Adem
as deber
a realizar un metodo main que realice lo siguiente:
1. Pida al usuario la informaci
on necesaria para crear dos tanques.
2. Luego muestre un men
u al usuario con las siguientes opciones:
a) Manipular Tanque 1 permite realizar cualquiera de las siguientes acciones sobre el tanque 1:

1) Recargar municiones permita recargar municiones en el tanque. Pide al usuario el tipo de


munici
on y la cantidad que desea recargar. Informa en un mensaje la cantidad de municiones
que efectivamente se pudieron agregar.
2) Atacar permite realizar un ataque con el tanque. Pide al usuario la distancia al blanco (en
metros) y el tipo de munici
on a utilizar. Informa en caso de que el ataque no se haya podido
realizar.
3) Ver estado muestra el estado del tanque a traves del metodo correspondiente.
4) Volver vuelve al men
u principal.

b) Manipular Tanque 2 an
alogo a la opci
on anterior, pero para el tanque 2.

c) Comparar Desempe
nos informa cu
al tanque se desenvolvera mejor en un determinado ataque.
Pide al usuario la distancia al blanco (en metros), e informa cu
al de los dos tanque empleara
una menor cantidad de municiones en un ataque exitoso junto con la cantidad de misiles y balas que ahorrara respecto de su contendor, o bien, que ambos mostrar
an igual desempe
no si
correspondiese.

d ) Salir termina el programa.


Criterios de soluci
on
El enunciado es bastante estructurado, por lo que tenemos que ir realizando paso a paso lo que se nos pide.
1. Clase T anque
Lo primero que tenemos que hacer es declarar la clase con sus atributos. Del enunciado vemos que
debe tener como atributos: capacidad m
axima de misiles, capacidad m
axima de balas, eficiencia,
balas y misiles con que dispone y cantidad de ataques que ha efectuado, as como los blancos que
ha derribado.
Constructor: Lo declaramos tal como nos indican en el enunciado. En el metodo asignamos los
valores recibidos como par
ametro a los atributos correspondientes.
Metodo cargarM uniciones: Lo declaramos tal como nos indican en el enunciado. Revisamos
primeros si se quiere cargar misiles o balas. Luego revisamos que lo que se quiera cargar no
sobrepase la cantidad m
axima permitida. Si no lo sobrepasa, actualizamos la cantidad de misiles
o balas, seg
un corresponda, y retornamos la cantidad recibida como par
ametro. Si lo sobrepasa,
actualizamos la cantidad de misiles o balas s
olo hasta la cantidad m
axima y retornamos la cantidad
real agregada.
Metodo calcularDisparos: Lo declaramos tal como nos indican en el enunciado. Revisamos el
tipo de munici
on (si es misil o bala). Luego calculamos el n
umero de disparos seg
un la f
ormula
entregada en el enunciado. Retornamos el n
umero de disparos calculado.
Metodo atacar: Lo declaramos tal como nos indican en el enunciado. Primero debemos revisar
si la distancia a la que se quiere realizar el ataque est
a en el rango admisible. De no ser as,
retornamos false. Si la distancia es admisible, revisamos el tipo de munici
on (misiles o balas) y si
tenemos municiones para atacar, ya que si no tenemos simplemente retornamos false. Si tenemos
municiones, calculamos cu
antas necesitamos para derribar el blanco, para esto llamamos al metodo calcularDisparos implementado anteriormente. Actualizamos las municiones que nos quedan
IIC1103 Captulo 4: Clases

50

luego del disparo y revisamos si pudimos llegar al blanco. Si llegamos, actualizamos el n


umero
de blancos derribados y mostramos un mensaje indicando que se derrib
o el blanco. Finalmente,
actualizamos el n
umero de ataques realizados por el tanque.
Metodo mostrarEstado: Lo declaramos tal como nos indican en el enunciado. Mostramos en un
mensaje la eficiencia del tanque, el n
umero de ataques, n
umero de blancos derribados, porcentaje
de exitos, cantidad de misiles disponibles y cantidad de balas disponibles.
2. Clase P rincipal: Metodo main
Pedimos al usuario la eficiencia del tanque, el n
umero m
aximo de misiles y el n
umero m
aximo de
balas para dos tanques.
Creamos dos objetos de la clase T anque con los datos ingresados por el usuario.
Implementamos un ciclo para mostrar el men
u con las opciones, que no termine hasta el que
usuario ingrese la opci
on Salir.
Revisamos la opcion ingresada y determinamos con cu
al de los dos tanques se trabajar
a.
Implementamos otro ciclo para mostrar el men
u con las opciones para un tanque especfico.
Revisamos la opcion ingresada por el usuario y llamamos al metodo de la clase T anque que
corresponda seg
un la opci
on, pidiendo al usuario los valores necesarios para pasar como parametro
al metodo.
Opci
on Comparar Desempe
no: Llamamos al metodo calcularDisparos con misiles y balas para
cada tanque y comparamos las municiones utilizadas para determinar el que tiene mejor desempe
no. Mostramos un mensaje con los resultados.
Posible Soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class Tanque {
private int m a x M i s i l e s;
private int maxBalas ;
private int misiles ;
private int balas ;
private double e f i c i e n c i a;
private int ataques ;
private int b l a n c o s D e r r i b a d o s;
public Tanque ( int maxMisiles , int maxBalas , double e f i c i e n c i a) {
// I n i c i a l i z a m o s todos los a t r i b u t o s de la clase
this . m a x M i s i l e s = m a x M i s i l e s;
this . maxBalas = maxBalas ;
this . e f i c i e n c i a = e f i c i e n c i a;
this . misiles = 0;
this . balas = 0;
this . ataques = 0;
this . b l a n c o s D e r r i b a d o s = 0;
}
public int c a r g a r M u n i c i o n e s( boolean misil , int cantidad ) {
// Cargamos la municion correspondiente , r e v i s a n d o que la c a p a c i d a d sea s u f i c i e n t e
int c a r g a R e a l = 0;
if ( misil ) {
if ( m a x M i s i l e s - misiles > cantidad ) {
// Se puede cargar la t o t a l i d a d de las m u n i c i o n e s deseadas
misiles += cantidad ;
c a r g a R e a l = cantidad ;
} else {
misiles = m a x M i s i l e s; // Cargamos hasta que copemos la c a p a c i d a d
c a r g a R e a l = m a x M i s i l e s - misiles ;
}
} else { // P r o c e d i m i e n t o analogo para las balas
if ( maxBalas - balas > cantidad ) {
balas += cantidad ;
c a r g a R e a l = cantidad ;
} else {

IIC1103 Captulo 4: Clases

51

balas = maxBalas ;
c a r g a R e a l = maxBalas - balas ;
}
}
return c a r g a R e a l;
}
public int c a l c u l a r D i s p a r o s( boolean misil , int d i s t a n c i a) {
int disparos = 0;
// C a l c u l a m o s la cantidad n e c e s a r i a de disparos segun el tipo de
// municion y la d i s t a n c i a al blanco
if ( misil ) {
disparos = d i s t a n c i a * ( int ) (1 + 1 / Math . pow ( eficiencia , 2)) / 1000;
} else {
disparos = d i s t a n c i a * ( int ) (1 + 1 / Math . pow ( eficiencia , 2)) * 12 / 100;
}
return disparos ;
}
public boolean atacar ( boolean misil , int d i s t a n c i a) {
// No se puede atacar si la d i s t a n c i a es i n a d m i s i b l e
if ( d i s t a n c i a < 100 || d i s t a n c i a > 5000) {
return false ;
}
int m u n i c i o n e s N e c e s a r i a s;
if ( misil ) {
if ( misiles == 0) { // No se puede atacar sin m u n i c i o n e s
return false ;
}
m u n i c i o n e s N e c e s a r i a s = c a l c u l a r D i s p a r o s( true , d i s t a n c i a);
if ( m u n i c i o n e s N e c e s a r i a s > misiles ) {
// Las m u n i c i o n e s d i s p o n i b l e s no son s u f i c i e n t e s para derribar el blanco
misiles = 0;
} else {
misiles -= m u n i c i o n e s N e c e s a r i a s;
b l a n c o s D e r r i b a d o s ++;
Usuario . mensaje ( " Se ha d e r r i b a d o el blanco !\ nSe u t i l i z a r o n "
+ m u n i c i o n e s N e c e s a r i a s + " misiles . " );
}
} else {
if ( balas == 0) {
return false ;
}
m u n i c i o n e s N e c e s a r i a s = c a l c u l a r D i s p a r o s( false , d i s t a n c i a);
if ( m u n i c i o n e s N e c e s a r i a s > balas ) {
balas = 0;
} else {
balas -= m u n i c i o n e s N e c e s a r i a s;
b l a n c o s D e r r i b a d o s ++;
Usuario . mensaje ( " Se ha d e r r i b a d o el blanco !\ nSe u t i l i z a r o n "
+ m u n i c i o n e s N e c e s a r i a s + " balas . " );
}
}
ataques ++;
return true ;
}
public void m o s t r a r E s t a d o() { // M o s t r a m o s los a t r i b u t o s del tanque
Usuario . m e n s a j e C o n s o l a( " Estado del Tanque : ( e f i c i e n c i a = " + e f i c i e n c i a + " ) " );
if ( ataques > 0) {
Usuario . m e n s a j e C o n s o l a( " \ t C a n t i d a d de Ataques : " + ataques );
Usuario . m e n s a j e C o n s o l a( " \ t C a n t i d a d de Ataques exitosos : " + b l a n c o s D e r r i b a d o s);
Usuario . m e n s a j e C o n s o l a( " \ t P o r c e n t a j e de exito : " + 100 * b l a n c o s D e r r i b a d o s / ataques + " %" );
}
Usuario . m e n s a j e C o n s o l a( " \ t C a n t i d a d de Misiles d i s p o n i b l e s: " + misiles );
Usuario . m e n s a j e C o n s o l a( " \ t C a n t i d a d de Balas d i s p o n i b l e s: " + balas );
}
}
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
// Pedimos la i n f o r m a c i o n al usuario
int misiles1 = Usuario . entero ( " Ingrese la maxima c a p a c i d a d del Tanque 1 para misiles : " );
int balas1 = Usuario . entero ( " Ingrese la maxima c a p a c i d a d del Tanque 1 para balas : " );
double e f i c i e n c i a 1 = Usuario . real ( " Ingrese la e f i c i e n c i a del Tanque 1: " );
int misiles2 = Usuario . entero ( " Ingrese la maxima c a p a c i d a d del Tanque 2 para misiles : " );

IIC1103 Captulo 4: Clases

52

int balas2 = Usuario . entero ( " Ingrese la maxima c a p a c i d a d del Tanque 2 para balas : " );
double e f i c i e n c i a 2 = Usuario . real ( " Ingrese la e f i c i e n c i a del Tanque 2: " );
// Creamos los tanques
Tanque t1 = new Tanque ( misiles1 , balas1 , e f i c i e n c i a 1);
Tanque t2 = new Tanque ( misiles2 , balas2 , e f i c i e n c i a 2);
// Hacemos un ciclo para el menu
int opcion = 1;
while ( opcion > 0 && opcion < 4) {
opcion = Usuario . entero (" Elija una opcion :\ n (1) M a n i p u l a r Tanque 1\ n "
+ " (2) M a n i p u l a r Tanque 2\ n (3) Comparar d e s e m p e n i o s en igual e s c e n a r i o\ n (4) Salir " );
if ( opcion == 1 || opcion == 2) {
// Creamos una variable para m a n i p u l a r el tanque que se desea utilizar
Tanque tanque = t1 ;
if ( opcion == 2) {
tanque = t2 ;
}
int o p c i o n T a n q u e = 1;
while ( o p c i o n T a n q u e > 0 && o p c i o n T a n q u e < 4) {
o p c i o n T a n q u e = Usuario . entero ( " Que desea hacer con el tanque ?\ n (1) Recargar m u n i c i o n e s\ n "
+ " (2) Atacar \ n (3) Ver estado \ n (4) Volver " );
if ( o p c i o n T a n q u e == 1) { // Recargar m u n i c i o n e s
int t i p o M u n i c i o n = 1;
while ( t i p o M u n i c i o n < 1 && t i p o M u n i c i o n > 2) {
t i p o M u n i c i o n = Usuario . entero ( " Que municion desea cargar ?\ n (1) Misiles \ n (2) Balas " );
}
int cantidad = Usuario . entero ( " Ingrese la cantidad que desea agregar : " );
if ( t i p o M u n i c i o n == 1) {
Usuario . mensaje (" Se pudieron agregar "
+ tanque . c a r g a r M u n i c i o n e s( true , cantidad )
+ " misiles al tanque . " );
} else {
Usuario . mensaje (" Se pudieron agregar "
+ tanque . c a r g a r M u n i c i o n e s( false , cantidad )
+ " balas al tanque . " );
}
} else if ( o p c i o n T a n q u e == 2) { // Atacar
int d i s t a n c i a = Usuario . entero ( " Ingrese la d i s t a n c i a a la que se e n c u e n t r a el blanco : " );
int t i p o M u n i c i o n = 1;
while ( t i p o M u n i c i o n < 1 && t i p o M u n i c i o n > 2) {
t i p o M u n i c i o n = Usuario . entero ( " Con que tipo de municion desea atacar ?\ n " +
+ " (1) Misiles \ n (2) Balas " );
}
boolean misil = true ;
if ( t i p o M u n i c i o n == 2) {
misil = false ;
}
if (! tanque . atacar ( misil , d i s t a n c i a)) {
Usuario . mensaje (" No fue posible realizar el ataque . " );
}
} else if ( o p c i o n T a n q u e == 3) { // Ver estado
tanque . m o s t r a r E s t a d o();
}
}
} else if ( opcion == 3) { // Comparar d e s e m p e n i o s
int d i s t a n c i a = Usuario . entero ( " Ingrese la d i s t a n c i a a la que se e n c u e n t r a el blanco de prueba : " );
int m i s i l e s t 1 = t1 . c a l c u l a r D i s p a r o s( true , d i s t a n c i a);
int m i s i l e s t 2 = t2 . c a l c u l a r D i s p a r o s( true , d i s t a n c i a);
int balast1 = t1 . c a l c u l a r D i s p a r o s( false , d i s t a n c i a);
int balast2 = t2 . c a l c u l a r D i s p a r o s( false , d i s t a n c i a);
if ( m i s i l e s t 1 < m i s i l e s t 2) {
// Basta comparar solo un tipo de municion para d e t e r m i n a r el mejor
// desempenio , o bien , las e f i c i e n c i a s
Usuario . mensaje ( " El Tanque 1 tendra un mejor d e s e m p e n i o: "
+ "\n\ tOcuparia "
+ ( m i s i l e s t 2 - m i s i l e s t 1)
+ " misiles menos que el Tanque 2 , o a l t e r n a t i v a m e n t e"
+ " \ n \ t O c u p a r i a " + ( balast2 - balast1 )
+ " balas menos que el Tanque 2. " );
} else if ( m i s i l e s t 1 > m i s i l e s t 2) {
Usuario . mensaje ( " El Tanque 2 tendra un mejor d e s e m p e n i o: "
+ "\n\ tOcuparia "
+ ( m i s i l e s t 1 - m i s i l e s t 2)
+ " misiles menos que el Tanque 1 , o a l t e r n a t i v a m e n t e"
+ " \ n \ t O c u p a r i a " + ( balast1 - balast2 )
+ " balas menos que el Tanque 1. " );
} else {
Usuario . mensaje ( " Ambos Tanques tendran igual d e s e m p e n i o en la prueba . " );

IIC1103 Captulo 4: Clases

53

}
}
}
}
}

IIC1103 Captulo 4: Clases

54

Problema 20: Impresoras L


aser
Enunciado
Usted deber
a realizar un programa que permita operar dos impresoras l
aser, de modo de ver sus desempe
nos
enfrentadas a distintos tipos de trabajo.
Deber
a crear la clase Impresora la cual representara una impresora dentro de su programa. Una impresora
se caracteriza esencialemente por la capacidad m
axima de hojas tama
no carta y oficio que puede tener en
sus bandejas, y tambien por la eficiencia que resulta de su configuraci
on. Asimismo, interesa la cantidad de
hojas de ambos tama
nos que dispone en un determinado instante, y tambien la cantidad de tinta que hay
en su toner.
Su clase, ademas de los getters que estime pertinentes, debe tener los siguientes metodos:
Impresora(int maxCarta, int maxOficio, double tonerIni) constructor de la clase, recibe
como parametros la capacidad m
axima de hojas tama
no carta (maxCarta) y oficio (maxOficio) que
puede cargar en sus bandejas, y la cantidad de tinta en gramos (tonerIni) que tendr
a inicialmente en
su toner, el cual tiene una capacidad maxima de 1,500 grs. en su interior. La eficiencia de la impresora
es un n
umero real en el intervalo cerrado [0,85, 1,0], que queda definido aleatoriamente durante la
a hojas de ning
un tipo.
creacion del objeto6 . Inicialmente, la impresora no tendr
int cargarPapel(int tipo, int cantidad) agrega un determinado tipo de papel a la impresora.
Si el par
ametro tipo es 1, entonces corresponder
a cargar papel tama
no carta, y si es 2, sera de oficio.
En ambos casos se debe respetar la restricci
on impuesta por la m
axima cantidad de hojas de ambos
tama
nos que la impresora puede tener. En caso de que la cantidad que se desea agregar sea mayor que
la capacidad disponible en un determinado momento, se recarga hasta completar la capacidad m
axima
del determinado tipo de papel. Retorna la cantidad de hojas que se lograron cargar efectivamente.
double CargarToner(double cantidad) agrega una determinada cantidad de gramos de tinta al
toner de la impresora, respetando la restricci
on impuesta por la capacidad m
axima del toner. En caso
de que la cantidad que se desea agregar sea mayor que la capacidad disponible en un determinado
momento, se recarga hasta completar la capacidad m
axima del toner. Retorna la cantidad de gramos
de tinta que se lograron cargar efectivamente.
double calcularGastoTinta(int pags, boolean figs) calcula y retorna los gramos de tinta que
la impresora deber
a emplear para imprimir un determinado n
umero de p
aginas (pags). Si el par
ametro
figs es true, significa que el documento contiene im
agenes de dimensiones considerables que tambien
deben imprimirse, y si es false, no las posee. Las siguientes f
ormulas ayudan a determinar los gramos
de tinta necesarios:
Si el documento no tiene im
agenes, entonces se necesitar
a la siguiente cantidad de tinta:
G = pags 0,003 (1 + (1 ef icienciaT oner))
Si el documento tiene im
agenes, entonces se necesitar
a la siguiente cantidad de tinta:
Gf igs = G 2
int imprimir(int tipoHoja, int numPags, boolean dblCara, boolean figs) permite imprimir una determinada cantidad de p
aginas (numPags) en un tama
no de hoja especfico (tipoHoja). Si
el par
ametro dblCara es true, significa que el documento debe imprimirse ocupando ambas caras de
una hoja (o sea, dos p
aginas por hoja), y si es false, una p
agina por hoja. Si el par
ametro figs es
true, significa que el documento contiene im
agenes de dimensiones considerables que tambien deben
imprimirse, y si es false, no las posee. En caso de que la tinta en el toner no sea suficiente para imprimir lo deseado, no se realizar
a la impresi
on. En caso de que la cantidad de hojas del tipo deseado no
6 double

eficienciaToner = Aleatorio.real(0.85, 1.0);

IIC1103 Captulo 4: Clases

55

sea suficiente para imprimir completamente lo deseado, se imprimir


an todas las p
aginas que se alcance.
El metodo descuenta la cantidad de hojas que se ocuparon efectivamente en la cantidad de gramos de
tinta que se gastaron del toner, y retorna finalmente la cantidad de p
aginas impresas efectivamente.
void mostrarEstado() muestra en un mensaje el estado de la impresora en un determinado momento: la cantidad de hojas que le quedan de ambos tama
nos y los gramos de tinta que quedan en su
toner.
Adem
as deber
a realizar un metodo main que realice lo siguiente:
1. Pida al usuario la informaci
on necesaria para crear dos impresoras.
2. Luego muestre un men
u al usuario con las siguientes opciones:
a) Ocupar Impresora 1 permite realizar cualquiera de las siguientes acciones sobre la impresora
1:
1) Cargar papel permite cargar un determinado tipo de papel en la impresora. Pide al usuario
el tipo de papel y la cantidad hojas que desea agregar. Informa en un mensaje las hojas que
efectivamente se pudieron agregar.
2) Imprimir permite imprimir un documento con la impresora. Pide al usuario las caractersticas del documento: cantidad de p
aginas, el tama
no de papel deseado, si ser
a a doble cara o
no, y si contiene im
agenes que imprimir o no. Informa la cantidad de p
aginas del documento
impresas efectivamente.
3) Ver estado muestra el estado de la impresora a traves del metodo correspondiente.
4) Volver vuelve al men
u principal.

b) Ocupar Impresora 2 an
alogo a la opci
on anterior, pero para la impresora 2.

c) Comparar Desempe
nos informa cu
al impresora est
a mejor preparada para imprimir un trabajo
exigente, caracterizado por la presencia de imagenes en todas sus p
aginas. La comparaci
on se
hace en terminos de la m
axima cantidad de p
aginas que cada impresora podra imprimir del
trabajo se
nalado, en relaci
on a su estado. En caso de haber una ganadora, informa las p
aginas
que imprimira, y si no la hay, da cuenta de la situaci
on de empate.

d ) Salir termina el programa.


Criterios de soluci
on
El enunciado es bastante estructurado, por lo que tenemos que ir realizando paso a paso lo que se nos pide.
1. Clase Impresora
Lo primero que tenemos que hacer es declarar la clase con sus atributos. Del enunciado vemos
que debe tener como atributos: n
umero de hojas tama
no carta y n
umero de hojas tama
no oficio
con las que cuenta; m
aximo n
umero de hojas tama
no carta que puede tener y m
aximo n
umero
de hojas tama
no oficio que puede tener; cantidad de tinta y m
axima cantidad de tinta que puede
tener; eficiencia del toner. Debemos tambien declarar los getters para los atributos.
Constructor: Lo declaramos tal como nos indican en el enunciado. En el metodo asignamos los
valores recibidos como par
ametro a los atributos correspondientes. Calculamos la eficiencia como
un n
umero aleatorio entre 0.85 y 1.
Metodo cargarP apel: Lo declaramos tal como nos indican en el enunciado. Revisamos primero
si se quiere cargar hojas tama
no carta o hojas tama
no oficio. Luego revisamos que lo que se
quiera cargar no sobrepase la cantidad m
axima permitida. Si no lo sobrepasa, actualizamos la
cantidad de hojas tama
no carta u oficio, seg
un corresponda, y retornamos la cantidad recibida
como parametro. Si lo sobrepasa, actualizamos la cantidad de hojas tama
no carta u oficio solo
hasta la cantidad m
axima y retornamos la cantidad real agregada.
IIC1103 Captulo 4: Clases

56

Metodo CargarT oner: Lo declaramos tal como nos indican en el enunciado. Revisamos que la
cantidad que se desea agregar no sobrepase la cantidad m
axima permitida. Si no la sobrepasa,
actualizamos la cantidad de tinta y retornamos el mismo valor recibido como par
ametro. Si la
sobrepasa, actualizamos la cantidad de tinta s
olo hasta el m
aximo permitido y retornamos la
cantidad real agregada.
Metodo calcularGastoT inta: Lo declaramos tal como nos indican en el enunciado. Revisamos si
la impresi
on tiene im
agenes (seg
un el par
ametro figs recibido). Seg
un esto calculamos el gasto con
la ecuacion entregada en el enunciado. Retornamos el gasto calculado.
Metodo imprimir: Lo declaramos tal como nos indican en el enunciado. Revisamos si la impresi
on
ser
a a doble cara. Seg
un esto actualizamos el n
umero de hojas que debemos imprimir. Calculamos
el uso de tinta llamando al metodo calcularGastoT inta implementado anteriormente. Si la tinta
actual del toner no alcanza para imprimir lo deseado retornamos 0. En caso contrario, actualizamos
la tinta actual y revisamos el tama
no de papel en que se desea imprimir. Seg
un el tipo de papel
revisamos si la cantidad de hojas de ese tipo alcanza para imprimir lo que se desea. Actualizamos
la cantidad de hojas imprimiendo s
olo lo que se pueda. Retornamos el n
umero real de hojas que
se alcanzaron a imprimir.
Metodo mostrarEstado: Lo declaramos tal como nos indican en el enunciado. Mostramos en un
mensaje el valor que tienen los atributos: hojas tama
no carta, hojas tama
no oficio y tinta del
toner.
2. Clase P rincipal: Metodo main
Pedimos al usuario la cantidad de hojas tama
no carta, la cantidad de hojas tama
no oficio y la
cantidad de tinta para dos Impresoras.
Creamos dos objetos de la clase Impresora con los datos ingresados por el usuario.
Implementamos un ciclo para mostrar el men
u con las opciones, que no termine hasta el que
usuario ingrese la opci
on Salir.
Revisamos la opcion ingresada y determinamos con cu
al de las dos impresoras se trabajar
a.
Implementamos otro ciclo para mostrar el men
u con las opciones para una impresora especfica.
Revisamos la opcion ingresada por el usuario y llamamos al metodo de la clase Impresora que
corresponda seg
un la opci
on, pidiendo al usuario los valores necesarios para pasar como parametro
al metodo.
Posible Soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class I m p r e s o r a {
private
private
private
private
private
private
private

int h o j a s C a r t a;
int h o j a s O f i c i o;
int m a x H o j a s C a r t a;
int m a x H o j a s O f i c i o;
double t i n t a T o n e r;
double m a x T i n t a T o n e r;
double e f i c i e n c i a T o n e r;

public I m p r e s o r a( int maxCarta , int maxOficio , double t o n e r I n i c i a l) {


h o j a s C a r t a = 0;
h o j a s O f i c i o = 0;
m a x H o j a s C a r t a = maxCarta ;
m a x H o j a s O f i c i o = m a x O f i c i o;
t i n t a T o n e r = t o n e r I n i c i a l;
m a x T i n t a T o n e r = 1500.0;
e f i c i e n c i a T o n e r = A l e a t o r i o. real (0.85 , 1.0);
}
public int c a r g a r P a p e l( int tipo , int cantidad ) {

IIC1103 Captulo 4: Clases

57

// Cargamos papel r e s p e t a n d o la c a p a c i d a d maxima de las bandejas de la i m p r e s o r a


int c a r g a R e a l = 0;
if ( tipo == 1) { // Carta
if ( m a x H o j a s C a r t a - h o j a s C a r t a >= cantidad ) {
c a r g a R e a l = cantidad ;
h o j a s C a r t a += c a r g a R e a l;
} else {
c a r g a R e a l = m a x H o j a s C a r t a - h o j a s C a r t a;
h o j a s C a r t a += c a r g a R e a l;
}
} else if ( tipo == 2) { // Oficio
if ( m a x H o j a s O f i c i o - h o j a s O f i c i o >= cantidad ) {
c a r g a R e a l = cantidad ;
h o j a s O f i c i o += c a r g a R e a l;
} else {
c a r g a R e a l = m a x H o j a s O f i c i o - h o j a s O f i c i o;
h o j a s O f i c i o += c a r g a R e a l;
}
}
return c a r g a R e a l;
}
public double C a r g a r T o n e r( double cantidad ) {
// Cargamos tinta en el toner r e s p e t a n d o su c a p a c i d a d maxima
double c a r g a R e a l = 0.0;
if ( m a x T i n t a T o n e r - t i n t a T o n e r >= cantidad ) {
c a r g a R e a l = cantidad ;
t i n t a T o n e r += c a r g a R e a l;
} else {
c a r g a R e a l = m a x T i n t a T o n e r - t i n t a T o n e r;
t i n t a T o n e r += c a r g a R e a l;
}
return c a r g a R e a l;
}
public double c a l c u l a r G a s t o T i n t a( int pags , boolean figs ) {
double uso ;
if ( figs ) {
uso = pags * 0.006 * (1 + (1 - e f i c i e n c i a T o n e r));
} else {
uso = pags * 0.003 * (1 + (1 - e f i c i e n c i a T o n e r));
}
return uso ;
}
public int imprimir ( int tipoHoja , int numPaginas , boolean dobleCara , boolean h a y F i g u r a s N e g r a s) {
// Imprime una d e t e r m i n a d a cantidad de copias
int n u m H o j a s R e a l e s = 0;
int p a g i n a s I m p r e s a s = 0;
// C a l c u l a m o s las hojas que se ocuparan
if ( d o b l e C a r a) {
n u m H o j a s R e a l e s = n u m P a g i n a s / 2 + n u m P a g i n a s % 2;
} else {
n u m H o j a s R e a l e s = n u m P a g i n a s;
}
// C a l c u l a m o s la cantidad de tinta que se ocupara del toner . Sin tinta
// suficiente , no se r e a l i z a r a la i m p r e s i o n deseada
double usoToner = c a l c u l a r G a s t o T i n t a( numPaginas , h a y F i g u r a s N e g r a s );
if ( t i n t a T o n e r < usoToner ) {
return p a g i n a s I m p r e s a s;
}
t i n t a T o n e r -= usoToner ;
if ( tipoHoja == 1) { // Carta
if ( h o j a s C a r t a >= n u m H o j a s R e a l e s) {
h o j a s C a r t a -= n u m H o j a s R e a l e s;
p a g i n a s I m p r e s a s = n u m P a g i n a s;
} else { // Si no hay hojas suficientes , se imprimen las que
// alcancen
int o l d P a p e l C a r t a = h o j a s C a r t a;
h o j a s C a r t a = 0;
if ( d o b l e C a r a) {
p a g i n a s I m p r e s a s = o l d P a p e l C a r t a * 2;
} else {
p a g i n a s I m p r e s a s = o l d P a p e l C a r t a;
}

IIC1103 Captulo 4: Clases

58

}
} else if ( tipoHoja == 2) { // Oficio
if ( h o j a s O f i c i o >= n u m H o j a s R e a l e s) {
h o j a s O f i c i o -= n u m H o j a s R e a l e s;
p a g i n a s I m p r e s a s = n u m P a g i n a s;
} else {
int o l d P a p e l O f i c i o = h o j a s O f i c i o;
h o j a s O f i c i o = 0;
if ( d o b l e C a r a) {
p a g i n a s I m p r e s a s = o l d P a p e l O f i c i o * 2;
} else {
p a g i n a s I m p r e s a s = o l d P a p e l O f i c i o;
}
}
}
return p a g i n a s I m p r e s a s;
}
public void m o s t r a r E s t a d o() {
Usuario . mensaje ( " El estado de la I m p r e s o r a es el s i g u i e n t e: "
+ " \ n \ tPapel carta : " + h o j a s C a r t a + " \ n \ tPapel oficio : "
+ h o j a s O f i c i o + " \ n \ tGramos de tinta en Toner : " + t i n t a T o n e r);
}
public int g e t H o j a s C a r t a() {
return h o j a s C a r t a;
}
public int g e t H o j a s O f i c i o() {
return h o j a s O f i c i o;
}
public double g e t T i n t a T o n e r() {
return t i n t a T o n e r;
}
}
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
// Pedimos la i n f o r m a c i o n al usuario
int carta1 = Usuario . entero ( " Ingrese la maxima c a p a c i d a d de hojas tamanio carta " +
" para la I m p r e s o r a 1: " );
int oficio1 = Usuario . entero ( " Ingrese la maxima c a p a c i d a d de hojas tamanio oficio " +
" para la I m p r e s o r a 1: " );
double tinta1 = Usuario . real ( " Ingrese la cantidad incial de tinta en el toner " +
" de la I m p r e s o r a 1: " );
int carta2 = Usuario . entero ( " Ingrese la maxima c a p a c i d a d de hojas tamanio carta " +
" para la I m p r e s o r a 2: " );
int oficio2 = Usuario . entero ( " Ingrese la maxima c a p a c i d a d de hojas tamanio oficio " +
" para la I m p r e s o r a 2: " );
double tinta2 = Usuario . real ( " Ingrese la cantidad incial de tinta en el toner " +
" de la I m p r e s o r a 2: " );
// Creamos las i m p r e s o r a s
I m p r e s o r a i1 = new I m p r e s o r a( carta1 , oficio1 , tinta1 );
I m p r e s o r a i2 = new I m p r e s o r a( carta2 , oficio2 , tinta2 );
// Hacemos un ciclo para el menu
int opcion = 1;
while ( opcion > 0 && opcion < 4) {
opcion = Usuario . entero (" Elija una opcion :\ n (1) Ocupar I m p r e s o r a 1\ n "
+ " (2) Ocupar I m p r e s o r a 2\ n (3) D e t e r m i n a r mejor i m p r e s o r a\ n (4) Salir " );
if ( opcion == 1 || opcion == 2) {
// Creamos una variable para m a n i p u l a r la i m p r e s o r a que se desea utilizar
I m p r e s o r a i m p r e s o r a = i1 ;
if ( opcion == 2) {
i m p r e s o r a = i2 ;
}
int o p c i o n I m p r e s o r a = 1;
while ( o p c i o n I m p r e s o r a > 0 && o p c i o n I m p r e s o r a < 4) {
o p c i o n I m p r e s o r a = Usuario . entero ( " Que desea hacer con esta i m p r e s o r a?\ n (1) Cargar papel \ n "
+ " (2) Imprimir \ n (3) Ver estado \ n (4) Volver " );
if ( o p c i o n I m p r e s o r a == 1) { // Cargar papel
int t i p o P a p e l = 1;

IIC1103 Captulo 4: Clases

59

while ( t i p o P a p e l < 1 && t i p o P a p e l > 2) {


t i p o P a p e l = Usuario . entero ( " Que tamanio desea cargar ?\ n (1) Carta \ n (2) Oficio " );
}
int cantidad = Usuario . entero ( " Ingrese la cantidad que desea agregar : " );
Usuario . mensaje ( " Se pudieron agregar "
+ i m p r e s o r a. c a r g a r P a p e l( tipoPapel , cantidad )
+ " hojas del tipo deseado a la i m p r e s o r a. " );
} else if ( o p c i o n I m p r e s o r a == 2) { // Imprimir
int t i p o P a p e l = 1;
while ( t i p o P a p e l < 1 && t i p o P a p e l > 2) {
t i p o P a p e l = Usuario . entero ( " En que tamanio de hoja desea imprimir ?\ n (1) Carta \ n (2) Oficio " );
}
int cantidad = Usuario . entero ( " Ingrese la cantidad de copias que desea : " );
int o p c i o n D o b l e C a r a = 1;
while ( o p c i o n D o b l e C a r a < 1 && o p c i o n D o b l e C a r a > 2) {
o p c i o n D o b l e C a r a = Usuario . entero ( " Desea imprimir en doble cara ?\ n (1) Si \ n (2) No " );
}
boolean d o b l e C a r a = true ;
if ( o p c i o n D o b l e C a r a == 2) {
d o b l e C a r a = false ;
}
int o p c i o n F i g u r a s N e g r a s = 1;
while ( o p c i o n F i g u r a s N e g r a s < 1 && o p c i o n F i g u r a s N e g r a s > 2) {
o p c i o n F i g u r a s N e g r a s = Usuario . entero ( " El original posee figuras oscuras ?\ n (1) Si \ n (2) No " );
}
boolean f i g u r a s N e g r a s = true ;
if ( o p c i o n F i g u r a s N e g r a s == 2) {
f i g u r a s N e g r a s = false ;
}
int p a g i n a s I m p r e s a s = i m p r e s o r a. imprimir ( tipoPapel , cantidad , dobleCara , f i g u r a s N e g r a s);
Usuario . mensaje ( " Se pudieron imprimir " + p a g i n a s I m p r e s a s
+ " paginas s a t i s f a c t o r i a m e n t e. " );
} else if ( o p c i o n I m p r e s o r a == 3) { // Ver estado
i m p r e s o r a. m o s t r a r E s t a d o();
}
}
} else if ( opcion == 3) { // Comparar d e s e m p e n i o s
int p a g i n a s I 1 = 0 , p a g i n a s I 2 = 0;
for ( int i = i1 . g e t H o j a s C a r t a() * 2; i >= 0; i - -) {
if ( i1 . c a l c u l a r G a s t o T i n t a(i , true ) <= i1 . g e t T i n t a T o n e r ()) {
paginasI1 = i;
break ;
}
}
for ( int i = i2 . g e t H o j a s C a r t a() * 2; i >= 0; i - -) {
if ( i2 . c a l c u l a r G a s t o T i n t a(i , true ) <= i2 . g e t T i n t a T o n e r ()) {
paginasI2 = i;
break ;
}
}
if ( p a g i n a s I 1 > p a g i n a s I 2) {
Usuario . mensaje ( " La i m p r e s o r a 1 esta mejor p r e p a r a d a para un trabajo exigente . Podria imprimir "
+ p a g i n a s I 1 + " paginas . " );
} else if ( p a g i n a s I 1 < p a g i n a s I 2) {
Usuario . mensaje ( " La i m p r e s o r a 2 esta mejor p r e p a r a d a para un trabajo exigente . Podria imprimir "
+ p a g i n a s I 2 + " paginas . " );
} else {
Usuario . mensaje ( " Ambas i m p r e s o r a s estan i g u a l m e n t e p r e p a r a d a s para un trabajo exigente . "
+ Podrian imprimir
p a g i n a s I 1 + " paginas . " );
}
}
}
}
}

IIC1103 Captulo 4: Clases

60

Problema 21: Clnicas


Enunciado
Usted deber
a implementar un programa que permita revisar estadsticas sobre dos clnicas y los cuatro
medicos que trabajan en cada una de ellas. Su programa deber
a simular la llegada de una cierta cantidad de
pacientes, para luego permitir medir la efectividad en el diagn
ostico de los medicos de las distintas clnicas.
Usted deber
a implementar la clase Cl
nica la cual representara a cada una de las clnicas presentes en el
programa. Cada clnica est
a representada por sus 4 medicos, los cuales a su vez se encuentran representados
por la clase Medico, la cual ya est
a implementada y su explicaci
on la encontrar
a m
as abajo.
A continuaci
on se detallan los metodos que debe tener su clase.
Clinica(int edad0, int edad1, int edad2, int edad3) constructor de la clase. Recibe como
par
ametros las edades en que se especializan cada uno de los medicos de la clnica.
Medico ObtenerMedico(int indice) retorna el medico indicado en el ndice. Este ndice va de 0
a 3.
boolean Atender(int edadPaciente, int medicoElegido) indica que se debe atender a un paciente. Recibe como parametro la edad del paciente, y el identificador del medico elegido (entre 0 y
3). Hace que el medico elegido atienda al paciente, en caso de que el diagn
ostico de ese medico no sea
correcto, entonces se pasa al siguiente medico. As hasta que alg
un medico de un buen diagn
ostico,
o hasta que todos los medicos hayan atendido al paciente. Retorna true si alguno de los medicos
logr
o atender al paciente.
public Medico MasEfectivo() retorna el medico m
as efectivo dentro de los medicos de la clnica.
Para ver la efectividad de un medico se utiliza el metodo getEfectividad() de la clase Medico.

public double EfectividadClinica() retorna la efectividad de los medicos de la clnica. Esta


es
el resultado de la divisi
on del total de diagn
osticos correctos por el total de atenciones de los medicos
de la clnica.
public void MostrarEstadisticas() muestra estadsticas de la clnica y sus medicos. De la clnica
muestra la efectividad, y de cada medico muestra su edad, el n
umero de atenciones, el n
umero de
diagn
osticos correctos, la efectividad y el promedio de edad de los pacientes a los que el medico ha
dado un buen diagn
ostico (este se obtiene con el metodo getEdadPromedioCorrectos() de la clase
Medico). El mensaje debe ser como el siguiente:
La efectividad promedio de los medicos de la clinica es: 0.36597938144329895
Medico 0 (20)
Atenciones: 98
Diagnosticos correctos: 44
Efectividad: 0.4489795918367347
Promedio edad pacientes diagnostico correcto: 20.454545454545453
Medico 1 (40)
Atenciones: 95
Diagnosticos correctos: 28
Efectividad: 0.29473684210526313
Promedio edad pacientes diagnostico correcto: 43.25
...
Su programa debe funcionar con el siguiente metodo main

IIC1103 Captulo 4: Clases

61

import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
// P r e g u n t a m o s al u s u a r i o l a s edades de los e s p e c i a l i s t a s de cada clinica
int edad10 = Usuario . entero ( " Ingrese la edad del medico 0 de la clinica 1. " );
int edad11 = Usuario . entero ( " Ingrese la edad del medico 1 de la clinica 1. " );
int edad12 = Usuario . entero ( " Ingrese la edad del medico 2 de la clinica 1. " );
int edad13 = Usuario . entero ( " Ingrese la edad del medico 3 de la clinica 1. " );
int edad20 = Usuario . entero ( " Ingrese la edad del medico 0 de la clinica 2. " );
int edad21 = Usuario . entero ( " Ingrese la edad del medico 1 de la clinica 2. " );
int edad22 = Usuario . entero ( " Ingrese la edad del medico 2 de la clinica 2. " );
int edad23 = Usuario . entero ( " Ingrese la edad del medico 3 de la clinica 2. " );
// Creamos las dos clinicas
Clinica clinica1 = new Clinica ( edad10 , edad11 , edad12 , edad13 );
Clinica clinica2 = new Clinica ( edad20 , edad21 , edad22 , edad23 );
// P r e g u n t a m o s al usuario la cantidad de p a c i e n t e s a atender
int n u m P a c i e n t e s = Usuario . entero ( " Ingrese la cantidad de p a c i e n t e s" );
// Creamos un ciclo con una i t e r a c i o n para cada paciente
for ( int i = 0; i < n u m P a c i e n t e s; i ++) {
// Vemos la edad del paciente , la clinica y el medico elegido .
int edad = A l e a t o r i o. entero (1 , 80);
int i d C l i n i c a = A l e a t o r i o. entero (1 , 2);
int idMedico = A l e a t o r i o. entero (0 , 3);
// D e f i n i m o s un boolean que indique si se c o n s i g u i o o no d i a g n o s t i c o
boolean d i a g n o s t i c o C o n s e g u i d o = true ;
if ( i d C l i n i c a == 1) {
// R e v i s a m o s si hay d i a g n o s t i c o correcto , de no haberlo nos
// c a m b i a m o s de clinica
if (! clinica1 . Atender ( edad , idMedico )) {
i d C l i n i c a = 2;
if (! clinica2 . Atender ( edad , idMedico )){
d i a g n o s t i c o C o n s e g u i d o = false ;
}
}
} else {
// R e v i s a m o s si hay d i a g n o s t i c o correcto , de no haberlo nos
// c a m b i a m o s de clinica
if (! clinica2 . Atender ( edad , idMedico )) {
i d C l i n i c a = 1;
if (! clinica1 . Atender ( edad , idMedico )) {
d i a g n o s t i c o C o n s e g u i d o = false ;
}
}
}
if (! d i a g n o s t i c o C o n s e g u i d o) {
Usuario . m e n s a j e C o n s o l a( " El paciente de edad " + edad
+ " no c o n s i g u i o buen d i a g n o s t i c o. " );
} else {
Usuario . m e n s a j e C o n s o l a( " El paciente de edad " + edad
+ " c o n s i g u i o buen d i a g n o s t i c o en la clinica " + i d C l i n i c a);
}
}
// M o s t r a m o s la i n f o r m a c i o n final
Usuario . m e n s a j e C o n s o l a( " \ n E s t a d i s t i c a s Clinica 1: " );
clinica1 . M o s t r a r E s t a d i s t i c a s();
Usuario . m e n s a j e C o n s o l a( " \ n E s t a d i s t i c a s Clinica 2: " );
clinica2 . M o s t r a r E s t a d i s t i c a s();
// Vemos cual fue el mejor medico
Medico m a s E f e c t i v o 1 = clinica1 . M a s E f e c t i v o ();
Medico m a s E f e c t i v o 2 = clinica2 . M a s E f e c t i v o ();
if ( m a s E f e c t i v o 1. g e t E f e c t i v i d a d() > m a s E f e c t i v o 2. g e t E f e c t i v i d a d ()) {
Usuario . m e n s a j e C o n s o l a( " \ nEl medico mas efectivo fue de la clinica 1 con una e f e c t i v i d a d de "
+ m a s E f e c t i v o 1. g e t E f e c t i v i d a d ());
} else if ( m a s E f e c t i v o 2. g e t E f e c t i v i d a d() > m a s E f e c t i v o 1. g e t E f e c t i v i d a d()) {
Usuario . m e n s a j e C o n s o l a( " \ nEl medico mas efectivo fue de la clinica 2 con una e f e c t i v i d a d de "
+ m a s E f e c t i v o 2. g e t E f e c t i v i d a d ());
} else {
Usuario . m e n s a j e C o n s o l a( " \ nAmbas clinicas tuvieron i g u a l a d o s a sus medicos mas e f e c t i v o s "
+ " con una e f e c t i v i d a d de " + m a s E f e c t i v o 1. g e t E f e c t i v i d a d ());
}
}
}

IIC1103 Captulo 4: Clases

62


Adem
as cuenta con la clase Medico. Esta
identifica un medico, cuya principal caracterstica es la edad para
la cual es especialista. A continuacion se describen los metodos de esta clase.
Medico(int edadEspecialista) constructor de la clase, recibe como par
ametro la edad para la
cual el medico es especialista.
boolean Atender(int edadPaciente) indica que debe atender a un paciente de la edad recibida
como parametro. Retorna true en caso de conseguir un diagn
ostico correcto, false en otro caso.
int getEdadEspecialista() retorna la edad en la cual es especialista el medico.
int getAtenciones() retorna la cantidad de atenciones realizadas por el medico.
int getDiagnosticosCorrectos() retorna la cantidad de diagn
osticos correctos realizadas por el
medico.
double getEdadPromedioCorrectos() retorna la edad promedio de los pacientes a los cuales el
medico ha dado un correcto diagn
ostico.
double getEfectividad() retorna la efectividad del medico.
Criterios de soluci
on
El enunciado es bastante estructurado, por lo que tenemos que ir realizando paso a paso lo que se nos pide.
Clase Clinica
Lo primero que tenemos que hacer es declarar la clase con sus atributos. Del enunciado vemos que
lo que caracteriza a una Clnica son los 4 medicos que trabajan en ella, por lo que como atributos
debemos tener 4 objetos de la clase M edico
Constructor: Lo declaramos tal como nos indican en el enunciado. En el metodo creamos cada
uno de los cuatro medicos, llamando al constructor de la clase, pasando para cada uno la edad
recibida como par
ametro.
Metodo ObtenerM edico: Lo declaramos tal como nos indican en el enunciado. Revisamos el ndice
recibido como par
ametro. Con un bloque de if y else determinamos cu
al objeto de la clase M edico
retornar. Retornamos correctamente el medico pedido.
Metodo Atender: Lo declaramos tal como nos indican en el enunciado. Obtenemos el medico elegido seg
un el ndice ingresado como par
ametro, llamando al metodo ObtenerM edico implementado
anteriormente. Implementamos un ciclo que nos permita revisar todos los medicos y que contin
ue
mientras no sea posible encontrar un diagn
ostico. Dentro del ciclo llamamos al metodo Atender
de la clase M edico y revisamos si se encontr
o diagn
ostico. Si no fue as, obtenemos al siguiente
medico y seguimos intentando.
Metodo M asEf ectivo: Lo declaramos tal como nos indican en el enunciado. Implementamos
un ciclo para revisar la efectividad de cada uno de los medicos. Dentro del ciclo obtenemos la
efectividad del medico con el metodo getEf ectividad y la comparamos con la mayor obtenida
hasta el momento. Finalmente retornamos el medico que posee la mayor efectividad.
Metodo Ef ectividadClinica: Lo declaramos tal como nos indican en el enunciado. Implementamos un ciclo para obtener las atenciones de todos los medicos y los buenos diagn
osticos. En
el ciclo llamamos a los metodos getAtenciones y getDiagnosticosCorrectos para cada medico.
Finalmente retornamos la suma de los buenos diagn
osticos dividido por la suma de las atenciones
de todos los medicos.

IIC1103 Captulo 4: Clases

63

Metodo mostrarEstadisticas: Lo declaramos tal como nos indican en el enunciado. Primero mostramos en un mensaje la efectividad, la cual obtenemos llamando al metodo Ef ectividadClinica
implementado anteriormente. Luego implementamos un ciclo para mostrar los datos de cada uno
de los medicos. En el ciclo mostramos la edad de especialidad del medico, el n
umero de atenciones
y diagn
osticos correctos, y el promedio de edad de los pacientes a los que el medico ha dado un
buen diagn
ostico. Todo lo anterior llamando a los metodos correspondientes de la clase M edico.
Posible Soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class Clinica {
// D e c l a r a m o s como atributo los 4 medicos
private Medico medico0 ;
private Medico medico1 ;
private Medico medico2 ;
private Medico medico3 ;
public Clinica ( int edad0 , int edad1 , int edad2 , int edad3 ) {
// En el c o n s t r u c t o r creamos los objetos de los 4 medicos segun los
// p a r a m e t r o s r e c i b i d o s
medico0 = new Medico ( edad0 );
medico1 = new Medico ( edad1 );
medico2 = new Medico ( edad2 );
medico3 = new Medico ( edad3 );
}
public Medico O b t e n e r M e d i c o( int indice ) {
// Segun el indice elegido r e t o r n a m o s al medico s e l e c c i o n a d o
if ( indice == 0) {
return medico0 ;
} else if ( indice == 1) {
return medico1 ;
} else if ( indice == 2) {
return medico2 ;
} else {
return medico3 ;
}
}
public boolean Atender ( int edadPaciente , int m e d i c o E l e g i d o) {
// O b t e n e m o s el medico elegido por el paciente
Medico elegido = O b t e n e r M e d i c o( m e d i c o E l e g i d o);
int i = 0;
// Creamos un ciclo que nos permita revisar todos los medicos . El ciclo
// continua mientras no sea posible e n c o n t r a r un d i a g n o s t i c o al paciente .
for ( i = 0; i < 4 && ! elegido . Atender ( e d a d P a c i e n t e); i ++) {
// C a m b i a m o s el medico elegido porque no se encontro d i a g n o s t i c o.
m e d i c o E l e g i d o = ( m e d i c o E l e g i d o + 1) % 4;
elegido = O b t e n e r M e d i c o( m e d i c o E l e g i d o);
}
// Si r e v i s a m o s todos los medicos y no e n c o n t r a m o s diagnostico , entonces
// r e t o r n a m o s false .
if ( i == 3) {
return false ;
}
return true ;
}
public Medico M a s E f e c t i v o() {
// C o m p a r a m o s todos los medicos , y en esta variable vamos g u a r d a n d o el
// que posea la mayor e f e c t i v i d a d.
Medico m a s E f e c t i v o = O b t e n e r M e d i c o (0);
for ( int i = 1; i < 4; i ++) {
Medico otro = O b t e n e r M e d i c o( i );
if ( m a s E f e c t i v o. g e t E f e c t i v i d a d() < otro . g e t E f e c t i v i d a d ()) {
m a s E f e c t i v o = otro ;
}
}
return m a s E f e c t i v o;
}
public double E f e c t i v i d a d C l i n i c a() {

IIC1103 Captulo 4: Clases

64

// Sumamos las a t e n c i o n e s de todos los medicos y los buenos d i a g n o s t i c o s


double a t e n c i o n e s = 0;
double b u e n o s D i a g n o s t i c o s = 0;
for ( int i = 0; i < 4; i ++) {
Medico medico = O b t e n e r M e d i c o( i );
a t e n c i o n e s += medico . g e t A t e n c i o n e s ();
b u e n o s D i a g n o s t i c o s += medico . g e t D i a g n o s t i c o s C o r r e c t o s ();
}
return b u e n o s D i a g n o s t i c o s / a t e n c i o n e s;
}
public void M o s t r a r E s t a d i s t i c a s() {
// M o s t r a m o s las e s t a d i s t i c a s de la e f e c t i v i d a d.
Usuario . m e n s a j e C o n s o l a( " La e f e c t i v i d a d promedio de los medicos de la clinica es : "
+ E f e c t i v i d a d C l i n i c a ());
// Hacemos un ciclo para mostrar las e s t a d i s t i c a s de cada uno de los medicos
for ( int i = 0; i < 4; i ++) {
Medico medico = O b t e n e r M e d i c o( i );
Usuario . m e n s a j e C o n s o l a( " \ tMedico " + i + " ( "
+ medico . g e t E d a d E s p e c i a l i s t a() + " ) " );
Usuario . m e n s a j e C o n s o l a( " \ t \ t A t e n c i o n e s: " + medico . g e t A t e n c i o n e s());
Usuario . m e n s a j e C o n s o l a( " \ t \ t D i a g n o s t i c o s c o r r e c t o s: "
+ medico . g e t D i a g n o s t i c o s C o r r e c t o s ());
Usuario . m e n s a j e C o n s o l a( " \ t \ t E f e c t i v i d a d: "
+ medico . g e t E f e c t i v i d a d ());
Usuario . m e n s a j e C o n s o l a( " \ t \ t P r o m e d i o edad p a c i e n t e s d i a g n o s t i c o correcto : "
+ medico . g e t E d a d P r o m e d i o C o r r e c t o s ());
}
}
}

IIC1103 Captulo 4: Clases

65

Problema 22: Cr
edito Bancario
Enunciado
Ud. deber
a desarrollar un programa que permita a un usuario realizar la pre-aprobaci
on de la solicitud de
un credito bancario. Dispondr
a de la clase Principal, cuyo metodo main debe funcionar con su programa.
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
int opcion = 1;
while ( opcion < 2) {
int rut = Usuario . entero ( " Banco IIC1103 - S o l i c i t u d de Creditos \ nIngrese su Rut " );
int edad = Usuario . entero ( " Banco IIC1103 - S o l i c i t u d de Creditos \ nIngrese su Edad " );
int r e n t a M e n s u a l = Usuario . entero ( " Banco IIC1103 - S o l i c i t u d de Creditos "
+ " \ nIngrese su renta mensual ( total familiar ) " );
int g r u p o F a m i l i a r = Usuario . entero ( " Banco IIC1103 - S o l i c i t u d de Creditos "
+ " \ nIngrese el nro . de personas de su familia ( i n c l u y e n d o s e) " );
int t i p o T r a b a j o = Usuario . entero ( " Banco IIC1103 - S o l i c i t u d de Creditos "
+ " \ nIngrese su tipo de o c u p a c i o n \ n (1) D e p e n d i e n t e\ n (2) I n d e p e n d i e n t e (3) Jubilado " );
Cliente cliente = new Cliente ( rut , edad , rentaMensual , grupoFamiliar , t i p o T r a b a j o);
int monto = Usuario . entero ( " Banco IIC1103 - S o l i c i t u d de Creditos \ nIngrese monto a s o l i c i t a r" );
int nroMeses = Usuario . entero ( " Banco IIC1103 - S o l i c i t u d de Creditos \ nIngrese numero de meses " );
Banco banco = new Banco ();
banco . s o l i c i t a r C r e d i t o( cliente , monto , nroMeses );
opcion = Usuario . entero (" Desea pedir otro credito ?\ n (1) Si \ n (2) No " );
}
}
}

.
El programa lo dividiremos en 3 subconjuntos incrementales. Le recomendamos no comenzar con el siguiente
subconjunto hasta terminar y probar el funcionamiento correcto del subconjunto actual.
Incremento 1
En este incremento, Ud. debe hacer que su sistema tenga la funcionalidad de solicitar el credito, y hacer una
validaci
on del mismo por parte del banco. Primero debe crear la clase Cliente, que debe tener los siguientes
atributos y metodos:
int rut representa su identificador de identidad. Por simplicidad, corresponde a un n
umero entero
cualquiera.
int edad corresponde a la edad en a
nos del cliente que solicita el credito.
int rentaMensual representa el total de ingresos familiares mensuales del cliente.
int grupoFamiliar corresponde al total de miembros del grupo familiar (incluyendose el cliente).
int tipoTrabajo representa el tipo de trabajo u ocupaci
on actual del cliente, donde:
1: Dependiente

2: Independiente
3: Jubilado

public Cliente(int rut, int edad, int rentaMensual, int grupoFamiliar, int tipoTrabajo)
constructor, inicializa todos los atributos de la clase, con los valores enviados como par
ametro.
getters y setters para cada uno de los atributos revise la implementaci
on de la clase Principal para
saber con certeza el nombre de los metodos necesarios.
Luego debe crear la clase AnalistaRiesgos, que debe tener siguiente metodo:

IIC1103 Captulo 4: Clases

66

public double determinarRiesgo(Cliente cliente, double montoCuota) Debe retornar el nivel de riesgo del cliente, el que corresponde a un valor de tipo double, que por defecto es cero. Para
su calculo debe considerarse lo siguiente:
Si la edad del cliente es menor que 23 a
nos o mayor a 65 a
nos , debe sumarse al ndice 1 punto.
Debe informarse en consola tal riesgo con un mensaje de la forma **Edad riesgosa (menor a
23 o mayor a 65 a~
nos).
Si el 50 % de la renta perc
apita del grupo familiar es menor que el monto mensual de la cuota, debe sumarse al ndice 1000 puntos. Debe informarse en consola tal riesgo con un mensaje de la forma **Monto mensual (X) no debe ser mayor al 50 % de la renta perc
apita
familiar (y), donde X es el monto mensual a pagar, e Y corresponde al valor del 50 % de la renta
perc
apita familiar.
Si el tipo de trabajo es Dependiente, no sumar nada al ndice de riesgo.

Si el tipo de trabajo es Independiente, sumar 2.5 puntos al ndice de riesgo.


Si el tipo de trabajo es Jubilado, sumar 1.5 puntos al ndice de riesgo.

Finalmente, Ud. debe crear la clase Banco, con los siguientes atributos y metodos:
AnalistaRiesgos analista Corresponde al objeto de la clase AnalistaRiesgos que revisara la
situacion del cliente que solicita el credito.
public Banco() constructor, inicializa los atributos de la clase.
public void solicitarCredito(Cliente cliente, int monto, int nroMeses) este metodo es
el encargado de realizar la solicitud del credito, e imprime en pantalla el resultado de la gesti
on. En
este incremento deben implementarse las siguientes reglas:
Si el ndice de riesgo, calculado por analista es menor a 2.5, debe informarse al cliente que el
credito fue pre-aprobado.
Si el ndice de riesgo, calculado por analista es mayor o igual a 2.5 y menor que 5.0, debe
informarse al cliente que el credito fue aprobado, pero debe ir al banco con un aval para su
aprobacion final.
Si el ndice de riesgo, calculado por analista es mayor a 5.0, debe informarse al cliente que el
credito fue rechazado.
Note que analista necesitara el monto mensual de la cuota. Para ello, debe calcularlo con la siguiente
f
ormula: montoCuota = monto(1 + 0,02)n /n con n=n
umero de meses.
Incremento 2
R
Si bien los bancos analizan el riesgo de sus clientes, antes piden un informe a Dicom$sobre
el comportamiento
comercial de sus clientes. Para ello, primero Ud. debe implementar la clase InformeComercial con los
siguientes atributos:

public int montoProtestos representa el monto en pesos de los protestos que tiene el cliente.
public int montoMora representa el monto en pesos de cuotas en mora con el comercio que tiene
el cliente.
public InformeComercial() constructor de la clase.
getters y setters para cada uno de los atributos
A continuaci
on Ud. debe crear la clase Dicom, con el siguiente metodo (adem
as del constructor por defecto):
IIC1103 Captulo 4: Clases

67

public InformeComercial generarInforme(Cliente cliente) genera el informe comercial del


cliente. Para efectos de este ejercicio, ello se hace de la siguiente forma:
Si el Rut del cliente es divisible por 5, tiene como monto de protestos el valor de su Rut, cero en
otro caso.
Si el Rut del cliente es divisible por 3, tiene como monto adeudado (mora) el valor de su Rut,
cero en otro caso.
Debe informar por consola el caso de que exista alg
un monto de protestos o monto en mora, con
mensajes separados para cada uno, indicando el valor correspondiente.
Finalmente, Ud. debe modificar la implementaci
on de la clase Banco, de tal forma que antes de efectuar el
R En caso de tener como monto
an
alisis de riesgo interno del banco, se pida el informe comercial a Dicom$.
de protestos y/o monto de mora un valor superior a 0 pesos, se debe rechazar autom
aticamente el credito,
informando con un mensaje en pantalla tal situaci
on. En caso de que no exista ning
un problema de protestos
o morosidades, se contin
ua con el an
alisis de riesgo del banco. Debe agregar a la clase, como atributo, un
objeto de la clase Dicom para la realizaci
on de esta tarea, el cual debe ser usado para la generaci
on del
informe comercial.
Incremento 3
R
Dicom$no
posee la informaci
on comercial de las personas, sino que la obtiene de otras fuentes, en particular
de las c
amaras de comercio. Ud. en su programa debe implementar la funcionalidad de consultar por parte
R
una c
amara de comercio la informaci
on comercial de una persona determinada. Para ello Ud.
de Dicom$a
debe implementar la clase CamaraComercio con los siguientes metodos (adem
as del constructor por defecto):

public int tieneProtestos(Cliente cliente) calcula el monto de protestos del cliente, con las
mismas reglas del incremento 2 para este aspecto. Debe informar por consola si existe alg
un monto en
protesto y su valor.
public int tieneMora(Cliente cliente) calcula el monto en mora del cliente, con las mismas
reglas del incremento 2 para este aspecto. Debe informar por consola si existe alg
un monto en mora y
su valor.
Finalmente, debe modificar la clase Dicom para que use la nueva funcionalidad. Para ello es requisito que
Ud. agregue como atributo un objeto de la clase CamaraComercio y lo use en el metodo generarInforme
para realizar la tarea del c
alculo de los protestos y mora.
Criterios de soluci
on
Posible Soluci
on
import i i c 1 1 0 3 P a c k a g e. Usuario ;
public class A n a l i s t a R i e s g o s {
public double d e t e r m i n a r R i e s g o( Cliente cliente , double m o n t o C u o t a) {
double i n d i c e R i e s g o = 0;
if ( cliente . getEdad () > 65 || cliente . getEdad () < 23) {
i n d i c e R i e s g o += 1;
Usuario . mensaje ( " ** Edad riesgosa ( menor a 23 o mayor a 65 anios ) " );
}
double p e r C a p i t a = cliente . g e t R e n t a M e n s u a l ()/ cliente . g e t G r u p o F a m i l i a r();
if ( m o n t o C u o t a > p e r C a p i t a * 0.5) {
i n d i c e R i e s g o += 1000;
Usuario . mensaje ( " ** Monto mensual ( "
+ montoCuota
+ " ) no debe ser mayor al 50 % de la renta p e r c a p i t a familiar ( "
+ p e r C a p i t a * 0.5 + " ) " );
}
if ( cliente . g e t T i p o T r a b a j o() == 1) {

IIC1103 Captulo 4: Clases

68

i n d i c e R i e s g o += 0;
} else if ( cliente . g e t T i p o T r a b a j o() == 2) {
i n d i c e R i e s g o += 2.5;
} else if ( cliente . g e t T i p o T r a b a j o() == 3) {
i n d i c e R i e s g o += 1.5;
}
return i n d i c e R i e s g o;
}
}
import i i c 1 1 0 3 P a c k a g e. Usuario ;
public class Banco {
A n a l i s t a R i e s g o s analista ;
Dicom dicom ;
public Banco () {
analista = new A n a l i s t a R i e s g o s();
dicom = new Dicom ();
}
public void s o l i c i t a r C r e d i t o( Cliente cliente , int monto , int nroMeses ) {
I n f o r m e C o m e r c i a l informe = dicom . g e n e r a r I n f o r m e( cliente );
if ( informe . g e t M o n t o M o r a () <= 0 && informe . g e t M o n t o P r o t e s t o s() <= 0) {
double m o n t o C u o t a = monto * Math . pow ((1 + 0.02) , nroMeses ) / nroMeses ;
double riesgo = analista . d e t e r m i n a r R i e s g o( cliente , m o n t o C u o t a);
if ( riesgo < 2.5) {
Usuario . mensaje ( " Enhorabuena , credito p r e a p r o b a d o. " +
" Vaya a las oficinas con su RUT para hacerlo efectivo " );
} else if ( riesgo >= 2.5 && riesgo < 5.0) {
Usuario . mensaje ( " El credito ha sido preaprobado , " +
" sin embargo debe d i r i g i r s e a las oficinas con un aval " );
} else {
Usuario . mensaje ( " El credito ha sido r e c h a z a d o debido a su alto riesgo de pago . " );
}
} else {
Usuario . mensaje ( " Credito ha sido r e c h a z a d o por tener p r o b l e m a s de p r o t e s t o s y / o mora " );
}
}
}
import i i c 1 1 0 3 P a c k a g e. Usuario ;
public class C a m a r a C o m e r c i o {
public int t i e n e P r o t e s t o s( Cliente cliente ) {
if ( cliente . getRut () % 5 == 0) {
Usuario . mensaje ( " ** El cliente tiene p r o t e s t o s por "
+ cliente . getRut ());
return cliente . getRut ();
} else {
return 0;
}
}
public int t i e n e M o r a( Cliente cliente ) {
if ( cliente . getRut () % 3 == 0) {
Usuario . mensaje ( " ** El cliente tiene mora por " + cliente . getRut ());
return cliente . getRut ();
} else {
return 0;
}
}
}
public class Cliente {
int rut ;
int edad ;
int r e n t a M e n s u a l;
int g r u p o F a m i l i a r;
int t i p o T r a b a j o;
public Cliente ( int rut , int edad , int rentaMensual , int grupoFamiliar ,
int t i p o T r a b a j o) {
this . rut = rut ;
this . edad = edad ;
this . r e n t a M e n s u a l = r e n t a M e n s u a l;
this . g r u p o F a m i l i a r = g r u p o F a m i l i a r;
this . t i p o T r a b a j o = t i p o T r a b a j o;

IIC1103 Captulo 4: Clases

69

}
public int getRut () {
return rut ;
}
public void setRut ( int rut ) {
this . rut = rut ;
}
public int getEdad () {
return edad ;
}
public void setEdad ( int edad ) {
this . edad = edad ;
}
public int g e t R e n t a M e n s u a l () {
return r e n t a M e n s u a l;
}
public void s e t R e n t a M e n s u a l( int r e n t a M e n s u a l) {
this . r e n t a M e n s u a l = r e n t a M e n s u a l;
}
public int g e t G r u p o F a m i l i a r () {
return g r u p o F a m i l i a r;
}
public void s e t G r u p o F a m i l i a r( int g r u p o F a m i l i a r) {
this . g r u p o F a m i l i a r = g r u p o F a m i l i a r;
}
public int g e t T i p o T r a b a j o() {
return t i p o T r a b a j o;
}
public void s e t T i p o T r a b a j o( int t i p o T r a b a j o) {
this . t i p o T r a b a j o = t i p o T r a b a j o;
}
}
public class Dicom {
public C a m a r a C o m e r c i o camara ;
public Dicom () {
camara = new C a m a r a C o m e r c i o();
}
public I n f o r m e C o m e r c i a l g e n e r a r I n f o r m e( Cliente cliente ) {
I n f o r m e C o m e r c i a l informe = new I n f o r m e C o m e r c i a l();
informe . s e t M o n t o P r o t e s t o s( camara . t i e n e P r o t e s t o s( cliente ));
informe . s e t M o n t o M o r a( camara . t i e n e M o r a( cliente ));
return informe ;
}
}
public class I n f o r m e C o m e r c i a l {
public int m o n t o P r o t e s t o s;
public int m o n t o M o r a;
public int g e t M o n t o P r o t e s t o s () {
return m o n t o P r o t e s t o s;
}
public void s e t M o n t o P r o t e s t o s( int m o n t o P r o t e s t o s) {
this . m o n t o P r o t e s t o s = m o n t o P r o t e s t o s;
}
public int g e t M o n t o M o r a() {
return m o n t o M o r a;
}

IIC1103 Captulo 4: Clases

70

public void s e t M o n t o M o r a( int m o n t o M o r a) {


this . m o n t o M o r a = m o n t o M o r a;
}
}

IIC1103 Captulo 4: Clases

71

You might also like