Está en la página 1de 95

lica de Chile

Pontificia Universidad Cato


Escuela de Ingeniera
Departamento de Ciencia de la Computacio n

IIC1103 Introducci
on a la Programaci
on

Captulo 8: Archivos

Resumen te
orico
Generalmente cuando dise namos un programa nos encontramos con la necesidad de guardar la informaci on
que este genera a un archivo, o que la informaci
on que este necesita para funcionar sea leda desde un archivo.
El querer almacenar informaci on es algo muy com un, puesto que con ello podemos guardar la informaci on
que el programa genera vol atilmente, y que de otra manera se perdera al cerrarlo. Ejemplos de esto son los
reproductores de video, editores de im agenes, editores de texto, etc.

Se llama input a la informaci on recibida desde un agente externo, y output la informaci on que es ex-
puesta al exterior. Los lenguajes de programaci on modernos generalmente ofrecen herramientas para poder
comunicarse con el exterior, acciones de I/O, especficamente Java ofrece una gran cantidad de clases que
encapsulan los procesos para lectura y escritura de informacion, escondiendo lo tedioso que podra ser, sim-

plificando la labor del programador. Estas clases son capaces de interactuar con m
ultiples fuentes, como son
archivos, internet, lnea de comando, la pantalla, etc.

Nosotros ya hemos realizado acciones de I/O, por ejemplo mostrar mensajes en pantalla, y pedir al usuario
que ingrese cierto dato. La lectura de archivos es un poco distinta, puesto que tiene ciertas reglas.

Sistema de Archivos
Los archivos dentro de un computador est
an almacenados en forma jer
arquica:

Unidades Fsicas y L
ogicas: Son el punto de partida del sistema de archivos. Por ejemplo el disco C:/
en Windows.
Carpetas: Se encuentran dentro de las unidades o de otras carpetas, tienen una funci
on de organizaci
on.
Archivos: Se encuentran dentro de las unidades o de carpetas. Estos son los elementos que guardan la
informaci
on.

Debido a esto, los archivos tienen rutas asociadas que indican la unidad, carpeta/s y el nombre del archivo
correspondiente. Por ejemplo, para acceder a un archivo llamado bar.txt en la carpeta foo del disco C,
la ruta sera C:/foo/bar.txt. A esto llamaremos ruta absoluta puesto que incluye la ruta completa desde
la unidad, no se asume nada. A diferencia de la ruta absoluta, existen las llamadas rutas relativas, estas
corresponden a la ruta desde la carpeta actual hasta el archivo. Por ejemplo, si nos encontramos dentro de
la carpeta foo (del ejemplo anterior), la ruta hasta el archivo bar.txt es simplemente bar.txt, puesto
que ya nos encontramos en la carpeta. Si nos encontr aramos en el disco C la ruta al mismo archivo sera
foo/bar.txt.

IIC1103 Captulo 8: Archivos 1


Adem as, los archivos y carpetas tienen permisos asociados, estos indican quienes pueden leer, escribir o ejecu-
tar determinado archivo. Se debe considerar esto antes de realizar operaciones sobre archivos. Generalmente
los due
nos, quienes crearon el archivo, tienen todos los permisos y pueden modificar los permisos de terceros.

Generalmente los archivos son guardados de forma binaria en los dispositivos de almacenamiento. Estos bits
pueden ser interpretados de varias maneras: como n umeros, como caracteres, como valores booleanos, etc.
Por esto, existen las extensiones (por ejemplo .txt), que le indican al sistema operativo (encargado de la
lectura y escritura) que tipo de archivo es el que se est
a intentado abrir, de manera que sea interpretado con
el programa correcto.

Por u
ltimo, se debe tener en cuenta que las acciones sobre archivos (como muchas de I/O) pueden fallar, por
lo que se debe indicar a Java que cada metodo que utilice algun tipo de I/O puede lanzar error.

Archivos en Java
En Java los archivos son representados por la clase File, cuyo constructor recibe la ruta (absoluta o relativa)
al archivo en cuesti
on. Es importante que el archivo no necesariamente debe existir, por ejemplo si queremos
crear un nuevo archivo ingresamos la ruta al archivo que queremos crear, aunque este todava no exista.

File archivo = new File(\C:/foo/bar.txt");

La clase File ofrece una variedad de metodos, entre ellos revisar permisos y existencia del archivo. Algunos
ejemplos son:

boolean exists() - Indica si el archivo existe o no.


boolean canRead() - Indica si el usuario tiene permisos de lectura sobre el archivo.
boolean canWrite() - Indica si el usuario tiene permisos de escritura sobre el archivo.
boolean canExecute() - Indica si el usuario tiene permisos de ejecucion sobre el archivo.
boolean isFile() - Indica si el archivo es en realidad un archivo (puede ser una carpeta).
boolean isDirectory() - Indica si el archivo es una carpeta (directorio) o no.

La clase archivo no est


a incluida por defecto en los proyectos, por lo que hay que importarla del paquete
java.io.

import java.io.File;
o
import java.io.*;

Para la lectura y escritura de informaci


on Java posee un tipo de clases llamadas Streams, estos representan
una conexion entre el programa y determinada fuente de informaci on. Existen muchos tipos de Stream, por
lo que solo veremos un par.

IIC1103 Captulo 8: Archivos 2


La clase Scanner es una de las que ofrece Java para lectura. Su constructor recibe la ruta al archivo o un
objeto tipo File.

Scanner dataIn = new Scanner(\C:/foo/bar.txt");


o
Scanner dataIn = new Scanner(archivo);

Al igual que la clase archivo, esta ofrece una gran cantidad de metodos:

int nextInt() - Intepreta el siguiente grupo de bits como un n


umero entero.

String next() - Interpreta el siguiente grupo de bits como una cadena de caracteres. Retorna la siguiente
palabra, antes de un espacio en blanco.

String nextLine() - Interpreta el siguiente grupo de bits como una cadena de caracteres. Retorna la
siguiente linea, antes de un salto de lnea.

void close() - Cierra el archivo liber


andolo para que otro programa pueda utilizarlo (importante cerrar
los archivos siempre antes de terminar el programa)

La clase Scanner viene en el paquete java.util por lo que hay que importarlo usando:
import java.util.Scanner;
Adem as, como dijimos antes, la lectura puede fallar, por lo que hay que avisar a Java que el m
etodo que
contiene al Scanner puede lanzar errores, esto se hace agregando la etiqueta throws IOException entre la
definici
on del metodo y la llave que comienza el c
odigo interno.

public void metodo(argumentos) throws IOException { ... }

En tanto, para escritura utilizamos la clase FileWriter, cuyo constructor, al igual que el Scanner, acepta un
String con la ruta al archivo o un objeto tipo File.

FileWriter dataOut = new FileWriter(\C:/foo/bar.txt");


o
FileWriter dataOut = new FileWriter(archivo);

Esta clase se utiliza para escribir caracteres, a traves del metodo:


void write(String);
Adem as, al igual que el Scanner, debemos cerrar el Stream con el metodo close() y agregar la etiqueta
throws IOException al metodo. La clase FileWriter viene en el paquete java.io.

IIC1103 Captulo 8: Archivos 3


Ejemplos
Problema 1: Redactor
Enunciado
Escriba un programa que le permita al usuario escribir texto (lnea a lnea) en un archivo, mostrando lo
que ha escrito hasta el momento. Adem as debe ser capaz de recordar lo escrito cuando se vuelva a iniciar el
programa. Se debe salir cuando se ingrese el comando ;SALIR;.

Criterios de soluci
on
Observamos que el programa debe cumplir con los siguientes requisitos:

Cargar la informaci
on pasada del programa, en caso de que se haya ejecutado antes
Mostrar al usuario lo escrito y pedir la siguiente linea a escribir. Repetir hasta encontrar el String
;SALIR;.
Guardar lo escrito al finalizar el programa.

El primer punto es f acil de lograr, solo verificar si existe el archivo a escribir, y de existir, leerlo antes de
empezar a escribir. Lo que leamos debemos guardarlo a un String que representar a la informacion final que
debe contener el archivo. Luego debemos realizar un loop, que muestre la informaci on actual, y pida al
usuario la siguiente linea a escribir. En caso de que la linea sea ;SALIR;debemos salir del loop.
Finalmente debemos escribir el String guardado al archivo.

Posible soluci
on
import i i c 1 1 0 3 P a c k a g e. Usuario ;
import java . io . File ;
import java . io . F i l e W r i t e r;
import java . io . I O E x c e p t i o n;
import java . util . Scanner ;

public class Program {

public static void main ( String [] args ) throws I O E x c e p t i o n {

// I n i c i a m o s el lector en un archivo a r b i t r a r i o ( llamado file en este caso )


File file = new File ( " file . txt " );
Scanner dataIn = new Scanner ( file );

String actual = " " ;


Usuario . mensaje ( " B i e n v e n i d o a W r i t t e r I I C 1 1 0 3" );

// Leer el archivo e x i s t e n t e
if ( file . exists ()) {
while ( dataIn . hasNext ()) {
actual += dataIn . nextLine ();

// Esto es para que no agregue un salto de linea extra al final del texto
if ( dataIn . hasNext ()) {
actual += " \ n " ;
}
}
}

F i l e W r i t e r dataOut = new F i l e W r i t e r( file );

String newLine = " " ;


while (! newLine . equals ( " ; SALIR ; " )) {
// Si la linea es no vacia , la agrega al texto
if (! newLine . equals ( " " )) {
actual += " \ n " + newLine ;
}

IIC1103 Captulo 8: Archivos 4


// Pide la s i g u i e n t e linea al usuario
newLine = Usuario . texto ( actual + " \ n >" );
}

// Una vez listo e s c r i b i m o s el texto al archivo


dataOut . write ( actual );
Usuario . mensaje ( " Gracias por usar W r i t t e r I I C 1 1 0 3" );

// Debemos recordar cerrar los lectores y e s c r i t o r e s


dataIn . close ();
dataOut . close ();
}
}

IIC1103 Captulo 8: Archivos 5


Problema 2: Leyendo al maestro
Enunciado
Leonardo di Ser Piero1, uno de los m as grandes genios de la humanidad, para proteger la propiedad intelectual
de sus escritos (o por mala costumbre, como piensan otros) en sus cuadernos y libretas sola escribir al
reves, como si estuviera viendo el reflejo de un espejo. Sabiendo esto, se le pide que dise
ne un programa que
traduzca los textos de Leo: se le debe pedir al usuario que ingrese el nombre de un archivo, leer lnea por
lnea, cada una de ellas invertirla, y guardar todo en un archivo cuyo nombre debe ingresar el usuario.

Criterios de soluci
on
Debemos:

1. recibir el nombre de un archivo.


2. intentar abrirlo (manejando los posibles errores).
3. leer cada una de las lneas.
4. cada una de ellas, se debe invertir.
5. escribir los datos en un archivo de salida, cuyo nombre ingresa el usuario (manejando los posibles
errores).

Por simplicidad, optaremos por guardar el contenido completo del archivo, luego pasar a un arreglo de
Strings, donde cada posici
on es una lnea, la que luego invertiremos.
Adem as, manejaremos todos los posibles errores al mismo tiempo (encerrando el c
odigo en un gran try/catch).

Posible soluci
on
import java . util .*;
import java . io . File ;
import i i c 1 1 0 3 P a c k a g e .*;
import java . io .*;

public class P r i n c i p a l {

public static void main ( String [] args ) {


// alguna r e f e r e n c i a a los archivos
String entrada = Usuario . texto ( " Ingrese el nombre del archivo de entrada a leer " );
String salida = Usuario . texto ( " Ingrese el nombre del archivo de salida a escribir " );
File a r c h i v o E n t r a d a = new File ( entrada );
File a r c h i v o S a l i d a 2 = new File ( salida );

// alguna manera de leer / escribir


F i l e W r i t e r escribir ;
Scanner lector ;

// v a r i a b l e s para guardar los c o n t e n i d o s


String c o n t e n i d o = " " , c o n t e n i d o I n v e r s o = " " ;
// manejar posibles errores
try {
lector = new Scanner ( a r c h i v o E n t r a d a);
escribir = new F i l e W r i t e r( a r c h i v o S a l i d a 2);
// leemos cada linea
while ( lector . hasNext ()) {
// i n c l u i m o s el salta de linea c o r r e s p o n d i e n t e
c o n t e n i d o += ( lector . nextLine () + " \ n " );
}
// usamos un arreglos de Strings auxiliar
String [] lineas = c o n t e n i d o. split ( " \ n " );
// para la cantidad de lineas
for ( int i = 0; i < lineas . length ; i ++) {

1 m
as detalles en http://es.wikipedia.org/wiki/Leonardo da Vinci

IIC1103 Captulo 8: Archivos 6


// para cada linea
// copiamos desde el final al principio , cada caracter
for ( int j = lineas [ i ]. length () - 1; j >= 0; j - -) {
c o n t e n i d o I n v e r s o += lineas [ i ]. charAt ( j );
}
// a g r e g a m o s el salto de linea c o r r e s p o n d i e n t e
c o n t e n i d o I n v e r s o += " \ n " ;
}
// e s c r i b i m o s en el archivo
escribir . write ( c o n t e n i d o I n v e r s o);

// cerramos las c o n e x i o n e s
escribir . close ();
lector . close ();

// m a n e j a m o s los errores
} // el archivo no se e n c u e n t r a
catch ( F i l e N o t F o u n d E x c e p t i o n e ) {
Usuario . mensaje ( " No se e n c u e n t r a el archivo : " + entrada );
} // algun error de entrada / salida
catch ( I O E x c e p t i o n e ) {
Usuario . mensaje ( " Error de tipo entrada / salida " );
} // C U A L Q U I E R tipo de error
catch ( E x c e p t i o n e ) {
Usuario . mensaje ( " Error ! " );
}
}
}

IIC1103 Captulo 8: Archivos 7


Problema 3: Tabla de Posiciones
Enunciado
La FIFA le ha pedido programar una aplicaci on para crear la tabla de posiciones de cada grupo para la
primera fase del Mundial de Sud africa 2010. Para esto, le han entregado el archivo equipos.txt que tiene
almacenados los nombres de los equipos de un grupo (uno en cada lnea). Adem as, en la primera lnea del
archivo aparece la cantidad de equipos que tiene el archivo (ya que la aplicaci
on no s olo se usar
a para el
mundial):

4
Chile
Honduras
Espa~
na
Suiza

Usando arreglos y archivos, escriba un programa que para cada equipo pregunte al usuario los partidos
ganados, partidos perdidos, partidos empatados, goles a favor y goles en contra. Al finalizar, debe crear el
archivo tablaDePosiciones.txt con el siguiente formato:

TABLA DE POSICIONES

EQUIPO PTS PJ PG PP PE GF GC DIF


Chile 12 4 4 0 0 9 3 6
Espa~
na 10 4 3 0 1 9 5 4
Honduras 3 4 1 3 0 3 7 -4
Suiza 1 4 0 3 1 4 11 -7

La tabla de posiciones debe ordenarse por puntos y diferencia de goles (en caso de tener igual cantidad de
puntos).

NOTA: PTS = 3*PG + PE, DIF = GF GC.

Criterios de Soluci
on
Para almacenar los datos de cada uno de los equipos (nombre, partidos ganados, partidos perdidos,
partidos empatados, partidos jugados, goles a favor, goles en contra y diferencia de goles) crearemos la
clase Equipo.
Crearemos un arreglo de Equipos.
Leeremos desde el archivo los nombres de cada uno de los equipos.
Iteraremos sobre cada uno de los equipos y le pediremos al usuario que ingrese los valores de PG, PP,
PE, GF y GC.

Luego programaremos un metodo boolean mayor(Equipo otroEquipo) que retornar


a verdadero
cuando un equipo sea mayor que otro.
Usando este metodo, modificaremos el algoritmo Insertion Sort para que compare y ordene Equipos.
Finalmente imprimiremos en un nuevo archivo la tabla de posiciones final.

IIC1103 Captulo 8: Archivos 8


Posible soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
import java . io .*;
import java . util . Scanner ;

public class T a b l a P o s i c i o n e s {
private static String A R C H I V O _ E Q U I P O S = " equipos . txt " ;
private static String A R C H I V O _ T A B L A = " t a b l a D e P o s i c i o n e s. txt " ;
private static Equipo [] equipos ;

public static void main ( String [] args ) throws I O E x c e p t i o n {

Usuario . mensaje ( " C o m e n z a n d o el proceso de creacion de Tabla de P o s i c i o n e s. " );


Usuario . mensaje ( " Leyendo archivo de Equipos ... " );

// primero leemos el archivo de equipos


l e e r A r c h i v o();

/* Ahora debemos p r e g u n t a r los datos para cada equipo


* En tabla se alcenara : PTS PJ PG PP PE GF GC DIF pero solo se pregunta
* al usuario por los datos n e c e s a r i o s para calcular la tabla .
*/

for ( int i = 0; i < equipos . length ; ++ i ) {


Usuario . mensaje ( " Equipo : " + equipos [ i ]. g e t N o m b r e ());
int input ;
input = Usuario . entero ( " Partidos Ganados : " );
equipos [ i ]. setPG ( input );
input = Usuario . entero ( " Partidos Perdidos : " );
equipos [ i ]. setPP ( input );
input = Usuario . entero ( " Partidos E m p a t a d o s: " );
equipos [ i ]. setPE ( input );
input = Usuario . entero ( " Goles a Favor : " );
equipos [ i ]. setGF ( input );
input = Usuario . entero ( " Goles en Contra : " );
equipos [ i ]. setGC ( input );
}

// o r d e n a m o s la tabla
o r d e n a r T a b l a();

// ahora e s c r i b i m o s el archivo de salida


e s c r i b i r A r c h i v o ();

Usuario . mensaje ( " E n h o r a b u e n a\ nEl archivo " + A R C H I V O _ T A B L A


+ " ha sido creado . " );
}

private static void e s c r i b i r A r c h i v o() throws I O E x c e p t i o n {

File n u e v o A r c h i v o = new File ( A R C H I V O _ T A B L A);


F i l e W r i t e r imprimir = new F i l e W r i t e r( n u e v o A r c h i v o);
imprimir . write ( " TABLA DE P O S I C I O N E S\ r \ n \ r \ n " );
imprimir . write ( " EQUIPO \ t \ tPTS \ tPJ \ tPG \ tPP \ tPE \ tGF \ tGC \ tDIF \ r \ n " );
String linea ;
for ( int i = 0; i < equipos . length ; ++ i ) {
linea = equipos [ i ]. g e t N o m b r e() + " \ t " ;
// agregar dos \ t si el largo del nombre es menor que 8 ,
// para que quede ordenado
if ( equipos [ i ]. g e t N o m b r e(). length () < 8) {
linea += " \ t " ;
}

linea += equipos [ i ]. getPTS () + " \ t " ;


linea += equipos [ i ]. getPJ () + " \ t " ;
linea += equipos [ i ]. getPG () + " \ t " ;
linea += equipos [ i ]. getPP () + " \ t " ;
linea += equipos [ i ]. getPE () + " \ t " ;
linea += equipos [ i ]. getGF () + " \ t " ;
linea += equipos [ i ]. getGC () + " \ t " ;
linea += equipos [ i ]. getDIF ();

imprimir . write ( linea + " \ r \ n " );


}
imprimir . close ();
}

IIC1103 Captulo 8: Archivos 9


public static void l e e r A r c h i v o() throws I O E x c e p t i o n {

File archivo = new File ( A R C H I V O _ E Q U I P O S);


// v e r i f i c a m o s si el archivo existe y si tenemos acceso para leerlo
if (! archivo . exists () || ! archivo . canRead ()) {
Usuario . mensaje ( " No se pudo abrir el archivo " + A R C H I V O _ E Q U I P O S);
// si no existe o no podemos abrirlo , r e t o r n a m o s para salir del metodo
return ;
}

Scanner lector = new Scanner ( archivo );


String linea ;

// hay dos opciones :


// int n u m e r o D e E q u i p o s = lector . nextInt ();
// o bien :
linea = lector . nextLine ();
int n u m e r o D e E q u i p o s = Integer . parseInt ( linea );

equipos = new Equipo [ n u m e r o D e E q u i p o s]; // arreglo de equipos

for ( int i = 0; i < equipos . length ; ++ i ) {


linea = lector . nextLine ();
equipos [ i ] = new Equipo ( linea );
}
lector . close ();
}

public static void o r d e n a r T a b l a() {


// aqui o r d e n a m o s usando I n s e r t i o n Sort
int k ;
Equipo val ;
for ( int i = 1; i < equipos . length ; i = i + 1) {
val = equipos [ i ];
k = i - 1;
while ( k >= 0 && ! equipos [ k ]. mayor ( val )) {
equipos [ k + 1] = equipos [ k ];
k = k - 1;
}
equipos [ k + 1] = val ;
}
}
}
public class Equipo {

private String nombre ;


private int PG , PP , PE , GF , GC ;

public Equipo ( String nombre ) {


this . nombre = nombre ;
}

public String g e t N o m b r e() {


return nombre ;
}

public void s e t N o m b r e( String nombre ) {


this . nombre = nombre ;
}

public int getPTS () {


return 3 * getPG () + getPE ();
}

public int getPJ () {


return getPG () + getPP () + getPE ();
}

public int getPG () {


return PG ;
}

public void setPG ( int pG ) {


PG = pG ;
}

IIC1103 Captulo 8: Archivos 10


public int getPP () {
return PP ;
}

public void setPP ( int pP ) {


PP = pP ;
}

public int getPE () {


return PE ;
}

public void setPE ( int pE ) {


PE = pE ;
}

public int getGF () {


return GF ;
}

public void setGF ( int gF ) {


GF = gF ;
}

public int getGC () {


return GC ;
}

public void setGC ( int gC ) {


GC = gC ;
}

public int getDIF () {


return getGF () - getGC ();
}

public boolean mayor ( Equipo val ) {

if ( getPTS () > val . getPTS ()) {


return true ;
}
if ( getPTS () == val . getPTS ()) {
if ( getDIF () > val . getDIF ()) {
return true ;
}

}
return false ;
}
}

IIC1103 Captulo 8: Archivos 11


Problema 4: Buscar Palabra
Enunciado
En este ejercicio usted debera desarrollar un metodo que permita buscar una palabra secreta en un conjunto
de archivos. De manera precisa, en este ejercicio usted debe considerar archivos que en la primera lnea
contienen dos n umeros, y en las siguientes lneas contienen alg
un texto. El primero de estos n umeros indica
un numero i de fila (i > 0) y el segundo un n umero j de columna (j 0). Cuando se abre este archivo, su
metodo debe ir a la fila i y columna j (la primera fila es la n umero 0, y la primera columna tambien es la
numero 0), y debe leer la palabra en esa posici on hasta encontrar un espacio o el fin de linea. Si esta palabra
es de la forma texto.txt (termina en .txt), entonces su metodo debe ir al archivo texto.txt y seguir con
la b
usqueda. Si la palabra no es de la forma descrita anteriormente, entonces es la clave que buscaba y su
metodo la debe retornar.

El metodo que usted debe desarrollar debe tener como encabezado:

public String busqueda(String inicio) throws IOException

donde inicio es el archivo desde el cual debe iniciar su b


usqueda. Por ejemplo, suponga que tiene los
siguientes archivos:

5 0 4 8 3 10
hola, como este finalmente aqui
has es otro archivo esta
estado donde la clave: iic1103
hoy? esta el otro.txt nombre
segundo.txt de archivo
bien

inicial.txt segundo.txt otro.txt

y que realiza la invocaci on busqueda("inicial.txt"). Entonces busqueda lee la primera linea del archi-
vo inicial.txt y determina que debe ir a la fila 5 y columna 15 de este archivo, y leer la palabra que
este en esa posici
on. Como esta palabra es segundo.txt, entonces su metodo debe ir al archivo con nom-
bre segundo.txt. Como la primera linea de este archivo tiene los valores 4 y 8, entonces su metodo debe
ir a la fila 4 y columna 8 del archivo, y leer la palabra que este en esa posici on. Como esta palabra es
otro.txt (tambien termina en .txt), su metodo debe abrir el archivo otro.txt. En este caso, despues de
leer la primera fila el metodo sabe que debe ir a la fila 3 y columna 10, donde ahora se encuentra la palabra
iic1103. Como esta palabra no termina en .txt, entonces busqueda la retorna ya que es la palabra buscada.

Importante: En esta pregunta puede suponer que los archivos utilizados siempre existen, y que tiene
el formato adecuado. En particular, si en la primera linea de una archivo se indica que debe ir a la fila i y
columna j, entonces puede suponer que esta posicion existe en el archivo.

Criterios de soluci
on
Posible soluci
on
public String busqueda ( String inicio ) throws I O E x c e p t i o n {
File archivo = new File ( inicio );
Scanner lector = new Scanner ( archivo );
int i , fila , columna ;
String linea , palabra ;
boolean t i e n e _ p u n t o;

while ( true ) {
fila = lector . nextInt ();

IIC1103 Captulo 8: Archivos 12


columna = lector . nextInt ();
for ( i = 0; i < fila ; i ++) {
lector . nextLine ();
}
linea = lector . nextLine ();
palabra = " " ;
t i e n e _ p u n t o = false ;
for ( i = columna ; ( i < linea . length () && linea . charAt ( i ) != ); i ++) {
palabra = palabra + linea . charAt ( i );
if ( linea . charAt ( i ) == . ) {
t i e n e _ p u n t o = true ;
}
}
if ( t i e n e _ p u n t o) {
archivo = new File ( palabra );
lector = new Scanner ( archivo );
} else {
return ( palabra );
}
}
}

IIC1103 Captulo 8: Archivos 13


Problema 5: Sensores
Enunciado
En una fabrica de alimentos se han instalado sensores para monitorear la temperatura de distintos lugares
de la fabrica en ciertos momentos de tiempo. La informacion tomada por estos sensores es almacenada en
un archivo mediciones.txt que tiene el siguiente formato:

5
s2 9 10 11 9 9
s23 8 8 7 10 6
s211 9
s12 8 7 6 9 9
s14 10 10

El primer n umero en el archivo indica el n umero de sensores que estuvieron registrando temperaturas (5
en el ejemplo), y las siguientes lneas almacenan las temperaturas registradas por cada sensor. Cada una
de estas lneas tiene el identificador del sensor seguido por una lista de temperaturas. Por ejemplo, para el
sensor con identificador s12 se registraron las temperaturas 8, 7, 6, 9 y 9.

En este ejercicio usted debe crear las funciones necesarias para leer la informacion contenida en el archivo
mediciones.txt, extraer para cada sensor la temperatura mnima que registr o y almacenar esta informacion
ordenada de menor a mayor temperatura en el archivo medicionesmin.txt, que tiene el siguiente formato:

s23 6
s12 6
s2 9
s211 9
s14 10

Notese que en el archivo medicionesmin.txt se almacena para cada sensor su identificador y la temperatura
mnima que registro, y esta informaci
on se encuentra ordenada desde el sensor que registr
o la menor tempe-
ratura hasta el que registro la mayor.

Para resolver este ejercicio, usted debe implementar las tres funciones que son detalladas a continuaci
on. En
la construcci
on de estas funciones, usted debe usar la clase Tupla que fue creada para almacenar el identificar
de un sensor y una temperatura registrada por el (en el desarrollo de este ejercicio, usted va a almacenar la
menor temperatura registrada por el sensor usando la clase Tupla):

public class Tupla {


private String i d e n t i f i c a d o r;
private int t e m p e r a t u r a;

public Tupla ( String id , int temp ) {


i d e n t i f i c a d o r = id ;
t e m p e r a t u r a = temp ;
}

public String g e t I d e n t i f i c a d o r() {


return i d e n t i f i c a d o r;
}

public int g e t T e m p e r a t u r a() {


return t e m p e r a t u r a;
}
}

IIC1103 Captulo 8: Archivos 14


Implemente la funci on Minimo: public int Minimo(String numeros) que recibe como par ametro un
String numeros que almacena una lista de n umeros, y retorna el menor de estos n umeros. Para resolver
esta pregunta suponga que numeros contiene al menos un n umero y los valores en este string estan sepa-
rados por un espacio. Por ejemplo, si numeros es 8 8 7 10 6, entonces Minimo debe retornar el valor entero 6.

Implemente la funci on Extraer: public Tupla[] Extraer() throws IOException que retorna un arre-
glo de objetos de tipo Tupla que corresponden a los sensores mencionados en el archivo mediciones.txt junto
con las temperaturas mnimas registradas para cada uno de ellos. Para resolver esto suponga que cada sensor
mencionado en el archivo mediciones.txt tiene registrado al menos una temperatura y estas temperaturas se
encuentran separadas por un espacio. Por ejemplo, si mediciones.txt es el archivo mostrado al principio de
esta pregunta, entonces el arreglo retornado por Extraer debe tener 5 objetos, siendo el primero un objeto
de tipo Tupla con identificador s2 y temperatura 9 (que corresponde a la menor temperatura del sensor s2)
y el segundo un objeto de tipo Tupla con identificador s23 y temperatura 6.

Implemente la funci on Almacenar: public void Almacenar(Tupla[] lista) throws IOException que
recibe como parametro una lista de objetos de tipo Tupla, los ordena de manera ascendente de acuerdo
a la temperatura asociada a cada uno de estos objetos (que corresponde a la temperatura asociada a un
sensor) y finalmente los almacena en el archivo medicionesmin.txt. Por ejemplo, si Almacenar recibe como
parametro el resultado de la funci
on Extraer, entonces medicionesmin.txt es el archivo mostrado al princi-
pio de esta pregunta, el cual almacena ordenados de menor a mayor temperaturas las temperatura mnimas
registradas por los sensores.

Importante: Para resolver este ejercicio no se puede utilizar el metodo split de la clase String.

Criterios de soluci
on
Posible soluci
on

public int Minimo ( String numeros ) {


if ( numeros . indexOf ( " " ) < 0) {
return ( Integer . parseInt ( numeros ));
} else {
int actual , siguiente , min , c a n d i d a t o;
actual = numeros . indexOf ( " " );
min = Integer . parseInt ( numeros . s u b s t r i n g(0 , actual ));
while ( actual >= 0) {
s i g u i e n t e = numeros . indexOf ( " " , actual + 1);
if ( s i g u i e n t e >= 0) {
c a n d i d a t o = Integer . parseInt ( numeros . s u b s t r i n g( actual + 1 ,
s i g u i e n t e ));
} else {
c a n d i d a t o = Integer . parseInt ( numeros . s u b s t r i n g( actual + 1));
}

if ( min > c a n d i d a t o) {
min = c a n d i d a t o;
}
actual = s i g u i e n t e;
}
return ( min );
}
}

public Tupla [] Extraer () throws I O E x c e p t i o n {


File entrada = new File ( " m e d i c i o n e s. txt " );
Scanner lector = new Scanner ( entrada );
String linea ;
int cantidad , i ;
cantidad = Integer . parseInt ( lector . nextLine ());
Tupla [] lista = new Tupla [ cantidad ];
for ( i = 0; i < cantidad ; i ++) {
linea = lector . nextLine ();

IIC1103 Captulo 8: Archivos 15


lista [ i ] = new Tupla ( linea . s u b s t r i n g(0 , linea . indexOf ( " " )) ,
Minimo ( linea . s u b s t r i n g( linea . indexOf ( " " ) + 1)));
}
lector . close ();
return ( lista );
}

public void A l m a c e n a r( Tupla [] lista ) throws I O E x c e p t i o n {


int i , k ;
Tupla aux ;
for ( i = 1; i < lista . length ; i ++) {
aux = lista [ i ];
k = i - 1;
while ( k >= 0 && lista [ k ]. g e t T e m p e r a t u r a() > aux . g e t T e m p e r a t u r a ()) {
lista [ k + 1] = lista [ k ];
k = k - 1;
}
lista [ k + 1] = aux ;
}
File salida = new File ( " m e d i c i o n e s _ m i n. txt " );
P r i n t W r i t e r imprimir = new P r i n t W r i t e r( salida );
for ( i = 0; i < lista . length ; i ++)
imprimir . println ( lista [ i ]. g e t I d e n t i f i c a d o r() + " "
+ lista [ i ]. g e t T e m p e r a t u r a ());
imprimir . close ();
}

IIC1103 Captulo 8: Archivos 16


Problema 6: Supermercado
Enunciado
Un supermercado ha puesto en funcionamiento la posibilidad de realizar los pedidos de forma telefonica. Los
clientes realizan sus pedidos a las operadoras, las cuales generan objetos de la clase ListaCompra (descrita
mas adelante). Usted debe completar la implementaci on de la clase Supermercado, realizando los metodos
que se piden a continuacion:
boolean leerProductos(String nombreArchivo) este metodo lee desde el archivo recibido los
productos con los que cuenta el supermercado. Cada producto posee un precio, un c odigo y un
nombre. La primera lnea del archivo indica la cantidad de productos existentes. Debe crear la lis-
ta listaProductos y agregar todos los productos que hay en el archivo. A continuaci
on se muestra un
ejemplo del contenido del archivo con los productos.
5
6000 101 Carne filete
690 201 Pan corriente
489 032 Arroz
1100 980 Mayonesa
699 202 Tomates

El metodo debe retornar true si el archivo exista, false en otro caso.


void crearOrdenDeCompra(String nombreArchivo, ListaCompra compras) este metodo crea
un archivo, llamado nombreArchivo, con la informaci on de la compra de un usuario. Para ello es-
cribe en el archivo el nombre del usuario, los productos que compr o y el costo total de su compra. La
informacion la extrae del objeto compras y el total lo calcula utilizando los costos de los productos. A
continuacion se muestra un ejemplo del contenido de este archivo generado.
Cliente: Maria Paz
2 Mayonesa
1,5 Pan corriente
1 Arroz
0,5 Carne filete
TOTAL: 6724

Las siguientes son las clases involucradas en el problema. Usted debe utilizarlas sin modificarlas.

public class Producto {


public Producto ( String codigo , String nombre , int precio ){...}
public String g e t C o d i g o (){...}
public String g e t N o m b r e (){...}
public int g e t P r e c i o (){...}
}

public class L i s t a C o m p r a {
// Retorna la lista con los codigos de los p r o d u c t o s a comprar
public String [] g e t P r o d u c t o s (){...}
// Retorna la cantidad de p r o d u c t o s para el codigo pasado como p a r a m e t r o
public int g e t C a n t i d a d( String codigo ){...}
public String g e t N o m b r e C l i e n t e (){...}
}

public class S u p e r m e r c a d o {
private Producto [] l i s t a P r o d u c t o s;

public boolean l e e r P r o d u c t o s( String n o m b r e A r c h i v o) {...}


public void c r e a r O r d e n D e C o m p r a( String nombreArchivo , L i s t a C o m p r a compras ) {...}
}

IIC1103 Captulo 8: Archivos 17


Criterios de soluci
on
Posible soluci
on

import java . io .*;


import java . util . Scanner ;

public class S u p e r m e r c a d o {

private Producto [] l i s t a P r o d u c t o s;

public boolean l e e r P r o d u c t o s( String n o m b r e A r c h i v o) throws I O E x c e p t i o n {


File archivo = new File ( n o m b r e A r c h i v o);
if (! archivo . exists ()) {
return false ;
}

Scanner lector = new Scanner ( archivo );

String linea = lector . nextLine ();


int n u m P r o d u c t o s = Integer . parseInt ( linea );
l i s t a P r o d u c t o s = new Producto [ n u m P r o d u c t o s];

for ( int i = 0; i < l i s t a P r o d u c t o s. length ; i ++) {


linea = lector . nextLine ();
int p r i m e r E s p a c i o = linea . indexOf ( " " );
int precio = Integer . parseInt ( linea . s u b s t r i n g(0 , p r i m e r E s p a c i o ));
int s e g u n d o E s p a c i o = linea . indexOf ( " " , p r i m e r E s p a c i o + 1);
String codigo = linea . s u b s t r i n g( p r i m e r E s p a c i o + 1 , s e g u n d o E s p a c i o);
String nombre = linea . s u b s t r i n g( s e g u n d o E s p a c i o + 1);

l i s t a P r o d u c t o s[ i ] = new Producto ( codigo , nombre , precio );


}

lector . close ();


return true ;
}

public void c r e a r O r d e n D e C o m p r a( String nombreArchivo , L i s t a C o m p r a compras )


throws I O E x c e p t i o n {
File archivo = new File ( n o m b r e A r c h i v o);
F i l e W r i t e r escritor = new F i l e W r i t e r( archivo );

escritor . write ( " Cliente : " + compras . g e t N o m b r e C l i e n t e() + " \ n " );


String [] p r o d u c t o s = compras . g e t P r o d u c t o s ();
int total = 0;
for ( int i = 0; i < p r o d u c t o s. length ; i ++) {
int cantidad = compras . g e t C a n t i d a d( p r o d u c t o s[ i ]);
// Buscamos el producto c o r r e s p o n d i e n t e.
Producto prod = null ;
for ( int j = 0; j < l i s t a P r o d u c t o s. length ; j ++) {
if ( l i s t a P r o d u c t o s[ j ]. g e t C o d i g o (). equals ( p r o d u c t o s[ i ])) {
prod = l i s t a P r o d u c t o s[ j ];
}
}
total += cantidad * prod . g e t P r e c i o ();

escritor . write ( cantidad + " " + prod . g e t N o m b r e() + " \ n " );


}
escritor . write ( " TOTAL : " + total );
escritor . close ();
}
}

IIC1103 Captulo 8: Archivos 18


Problema 7: Cargar Mapa
Enunciado
En este ejercicio deber
a realizar un programa que permita cargar un mapa desde un archivo. Este mapa es
una matriz de celdas, donde cada celda representa una cuadra. El mapa contiene las construcciones ubicadas
en cada celda, pudiendo una construccion utilizar una o mas celdas (no menos de una). Una celda podr
a estar
utilizada a lo m
as por una construccion (tambien podra estar vaca).

Su programa deber a ser capaz de cargar el mapa, mostrarlo y permitir hacer consultar sobre los vecinos
de una cierta construccion.

El programa lo dividiremos en 2 subconjuntos incrementales. Le recomendamos no comenzar con el siguiente


subconjunto hasta terminar y probar el funcionamiento correcto del subconjunto actual.

Incremento 1
En este subconjunto su programa deber
a ser capaz de cargar el mapa desde un archivo, as como tambien
mostrar el mapa en la consola.

El archivo con el mapa mantendr a siempre el siguiente formato. En la primera lnea vendr a el numero
de filas y el n
umero de columnas que forman el mapa. Luego en la siguiente lnea vendr a el n
umero de
construcciones que contendra el mapa. Luego de ello, el archivo contendr
a una lnea que describe a cada una
de las construcciones que forman el mapa, esta lnea estar
a formada por el nombre de la construcci on, la fila
y la columna de ubicacion dentro del mapa (esquina superior izquierda), el n umero de filas y el n
umero de
columnas que utiliza la construcci
on, y por u
ltimo la cantidad de pisos de la construcci
on.

A continuaci
on se muestra el contenido de un archivo de ejemplo:

10 6
8
hospital 0 2 3 4 6
casa1 4 2 1 1 1
casa2 9 1 1 1 1
edificio 7 1 3 2 18
policia 3 4 2 2 1
colegio 8 3 2 3 3
universidad 1 0 6 2 4
mall 5 3 3 3 4

En el archivo anterior, el hospital se encuentra en la fila 0, en la columna 2, ocupa 3 casillas de alto y 4


casillas de ancho, y tiene 6 pisos.

Su programa debe mostrar en la consola el mapa, para lo cual debe mostrar la matriz que lo represen-
ta, poniendo una X en los espacio que no hay construcciones, y el nombre de la construcci on en conjunto
con el n
umero de pisos, en los lugares utilizados por una construcci
on. Por ejemplo, para el archivo anterior
se debera mostrar lo siguiente:

X X hospital(6) hospital(6) hospital(6) hospital(6)


universidad(4) universidad(4) hospital(6) hospital(6) hospital(6) hospital(6)
universidad(4) universidad(4) hospital(6) hospital(6) hospital(6) hospital(6)
universidad(4) universidad(4) X X policia(1) policia(1)
universidad(4) universidad(4) casa1(1) X policia(1) policia(1)

IIC1103 Captulo 8: Archivos 19


universidad(4) universidad(4) X mall(4) mall(4) mall(4)
universidad(4) universidad(4) X mall(4) mall(4) mall(4)
X edificio(18) edificio(18) mall(4) mall(4) mall(4)
X edificio(18) edificio(18) colegio(3) colegio(3) colegio(3)
X edificio(18) edificio(18) colegio(3) colegio(3) colegio(3)

En este incremento deber a crear un main donde se le pide al usuario que ingrese el nombre del archivo a
cargar y luego se muestre el mapa cargado.

Incremento 2
En este incremento deber a agregar a su programa la funcionalidad para poder ver los vecinos de una cons-
truccion particular. Para ello deber
a pedirle al usuario que ingrese el nombre de la construcci
on y en base a
ella debera mostrar en la consola los nombres de las construcciones vecinas. Si el nombre entregado no existe
se le debe indicar esto al usuario. Una construccion es vecina de otra cuando comparten al menos un vertice
en com un.

Para el archivo anterior, si se ingresa casa1 se debera mostrar universidad y mall, si se ingresa mall
se debera mostrar casa1, edificio, policia y colegio. Tenga en consideraci
on que al mostrar los vecinos
se debe mostrar el nombre de cada vecino una sola vez, y no se puede mostrar nuevamente el nombre de la
construccion sobre la cual se esta trabajando.

Ahora su main luego de pedir el nombre del archivo y cargar el mapa, debe mostrar un men u desde donde el
usuario pueda elegir ver el mapa, ver los vecinos de una cierta construcci
on, o salir. Este men
u debe aparecer
constantemente hasta que el usuario seleccione salir.

Criterios de soluci
on
Posible soluci
on
import java . io .*;
import java . util .*;
import i i c 1 1 0 3 P a c k a g e .*;

public class Mapa {


private int [][] p o s i c i o n e s;
private Sitio [] sitios ;

public Mapa ( String filename ) throws I O E x c e p t i o n {


File archivo = new File ( filename );
if ( archivo . exists ()) {
Scanner lector = new Scanner ( archivo );
// Leemos las d i m e n s i o n e s del mapa
int filas = lector . nextInt ();
int columnas = lector . nextInt ();
p o s i c i o n e s = new int [ filas ][ columnas ];
// I n i c i a l i z a m o s las p o s i c i o n e s como vacias ( -1)
for ( int i = 0; i < p o s i c i o n e s. length ; i ++) {
for ( int j = 0; j < p o s i c i o n e s[ i ]. length ; j ++) {
p o s i c i o n e s[ i ][ j ] = -1;
}
}
// Leemos la cantidad de sitios
int n u m S i t i o s = lector . nextInt ();
sitios = new Sitio [ n u m S i t i o s];

// Leemos la i n f o r m a c i o n de cada sitio


for ( int i = 0; i < sitios . length ; i ++) {
// Leemos los datos c o r r e s p o n d i e n t e s al sitio
String nombre = lector . next ();
int x = lector . nextInt ();
int y = lector . nextInt ();
int f i l a s S i t i o = lector . nextInt ();
int c o l s S i t i o = lector . nextInt ();

IIC1103 Captulo 8: Archivos 20


int pisos = lector . nextInt ();
// Creamos el sitio
sitios [ i ] = new Sitio ( nombre , filasSitio , colsSitio , pisos );
// En la matriz a s i g n a m o s las p o s i c i o n e s que utiliza
for ( int u = x ; u < x + f i l a s S i t i o; u ++) {
for ( int v = y ; v < y + c o l s S i t i o; v ++) {
p o s i c i o n e s[ u ][ v ] = i ;
}
}
}
}
}

public void M o s t r a r M a p a() {


String mapa = " Detalle del Mapa \ n \ n " ;
// R e c o r r e m o s todas las p o s i c i o n e s del mapa
for ( int i = 0; i < p o s i c i o n e s. length ; i ++) {
for ( int j = 0; j < p o s i c i o n e s[ i ]. length ; j ++) {
// R e v i s a m o s si la posicion esta vacia o si existe un sitio
// o c u p a n d o l a
if ( p o s i c i o n e s[ i ][ j ] == -1) {
mapa += " X \ t \ t " ;
} else if ( sitios [ p o s i c i o n e s[ i ][ j ]]. g e t I d e n t i f i c a i o n (). length () > 7) {
mapa += sitios [ p o s i c i o n e s[ i ][ j ]]. g e t I d e n t i f i c a i o n() + " \ t " ;
} else {
mapa += sitios [ p o s i c i o n e s[ i ][ j ]]. g e t I d e n t i f i c a i o n() + " \ t \ t " ;
}
}
mapa += " \ n " ;
}

Usuario . m e n s a j e C o n s o l a( mapa );
}

public boolean M o s t r a r V e c i n o s( String n o m b r e S i t i o) {


// E n c o n t r a m o s el sitio
int idxSitio = E n c o n t r a r S i t i o( n o m b r e S i t i o);
if ( idxSitio != -1) {
// Creamos un arreglo donde m a r c a r e m o s los sitios vecinos
boolean [] vecinos = new boolean [ sitios . length ];
for ( int i = 0; i < vecinos . length ; i ++) {
vecinos [ i ] = false ;
}
// R e c o r r e m o s todas las posiciones , para todas aquellas donde se
// e n c u e n t r a el elemento buscados , vemos si
// a l r e d e d o r hay un sitio vecino
for ( int i = 0; i < p o s i c i o n e s. length ; i ++) {
for ( int j = 0; j < p o s i c i o n e s[ i ]. length ; j ++) {
if ( p o s i c i o n e s[ i ][ j ] == idxSitio ) {
// R e c o r r e m o s las p o s i c i o n e s de a l r e d e d o r
for ( int u = i - 1; u <= i + 1; u ++) {
for ( int v = j - 1; v <= j + 1; v ++) {
// R e v i s a m o s que estemos dentro de los limites y
// que la posicion no sea vacia
if ( u >= 0 && u < p o s i c i o n e s. length && v >= 0
&& v < p o s i c i o n e s[ i ]. length
&& p o s i c i o n e s[ u ][ v ] != -1) {
vecinos [ p o s i c i o n e s[ u ][ v ]] = true ;
// Lo marcamos como vecino
}
}
}
}
}
}
// Ahora s i m p l e m e n t e m o s t r a m o s los vecinos r e c o r r i e n d o el arreglo
Usuario . m e n s a j e C o n s o l a( " Los vecinos de " + sitios [ idxSitio ]. g e t N o m b r e() + " son : " );
for ( int i = 0; i < vecinos . length ; i ++) {
if ( i != idxSitio && vecinos [ i ]) {
Usuario . m e n s a j e C o n s o l a( sitios [ i ]. g e t N o m b r e ());
}
}
return true ;
}
return false ;
}

IIC1103 Captulo 8: Archivos 21


public int E n c o n t r a r S i t i o( String nombre ) {
// R e c o r r e m o s todos los sitios buscando el que posea este nombre
for ( int i = 0; i < sitios . length ; i ++) {
if ( sitios [ i ]. g e t N o m b r e(). e q u a l s I g n o r e C a s e( nombre )) {
return i ;
}
}
return -1;
}
}
import java . io .*;
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 ) throws I O E x c e p t i o n {
// Pedimos el nombre del archivo e i n i c i a l i z a m o s el mapa
String n o m b r e A r c h i v o = Usuario . texto ( " Ingrese el nombre del archivo con el mapa " );
Mapa ciudad = new Mapa ( n o m b r e A r c h i v o);

int opcion = 1;
while ( opcion != 3) {
opcion = Usuario . entero (" S e l e c c i o n e una opcion :\ n (1) Ver Mapa \ n (2) Ver vecinos \ n (3) Salir " );
if ( opcion == 1) { // Ver mapa
ciudad . M o s t r a r M a p a ();
} else if ( opcion == 2) { // Ver vecinos
String n o m b r e S i t i o = Usuario . texto ( " Ingrese el nombre del sitio " );
if (! ciudad . M o s t r a r V e c i n o s( n o m b r e S i t i o)) {
Usuario . mensaje ( " El sitio i n g r e s a d o no existe . " );
}
}
}
}
}
public class Sitio {
private String nombre ;
private int filas ;
private int columnas ;
private int pisos ;

public Sitio ( String nombre , int filas , int columnas , int pisos ) {
this . nombre = nombre ;
this . filas = filas ;
this . columnas = columnas ;
this . pisos = pisos ;
}

public String g e t N o m b r e() {


return nombre ;
}

public String g e t I d e n t i f i c a i o n() {


return nombre + " ( " + pisos + " ) " ;
}

public int getFilas () {


return filas ;
}

public int g e t C o l u m n a s() {


return columnas ;
}

public int getPisos () {


return pisos ;
}
}

IIC1103 Captulo 8: Archivos 22


Problema 8: Distribuci
on Encomiendas
Enunciado
En este ejercicio debera realizar un programa que permita determinar la distribucion inicial de encomiendas
en la bodega de una empresa de logstica. La bodega estar a representada como una matriz, donde cada celda
representara un espacio en la bodega. En un comienzo, cada espacio podr a estar vaco o estar reservado
para el tr
ansito al interior de la bodega (pasillos). Al momento de disponer las encomiendas al interior de la
bodega no se podr an utilizar aquellos espacios que se encuentren reservados.

Cada encomienda se caracterizara por su nombre, sus dimensiones (largo, ancho y alto que requiere su
embalaje) y por si es de naturaleza fragil o no.

El programa lo dividiremos en 2 subconjuntos incrementales. Le recomendamos no comenzar con el siguiente


subconjunto hasta terminar y probar el funcionamiento correcto del subconjunto actual.

Incremento 1
En este subconjunto su programa deber a ser capaz de obtener el plano de la bodega desde un archivo, as co-
mo tambien distribuir en su interior las encomiendas iniciales.

El archivo con la bodega mantendr a siempre el mismo formato. En la primera lnea se indicar a el n
umero de
filas y columnas de la bodega. Luego el archivo contendr a la descripcion de cada celda de su superficie, donde
el caracter - indicar a un espacio vaco, y el caracter + indicara un espacio reservado. A continuaci on, el
archivo contendr a el n
umero de encomiendas a distribuir inicialmente, seguido por el detalle (en cada linea
subsiguiente) de cada uno de estas. Para cada encomienda se encontrar a su nombre (puede asumir que nunca
contendr a espacio), el largo, el ancho y el alto de su embalaje, y un u ltimo dato que dara cuenta de si es
fragil (1) o no (0).

A continuaci
on se muestra el contenido de un archivo de ejemplo:

12 15
- - - - + + - - - - - - - - -
- - - - + + - - - - - - - - -
- - - - + + - - - - - - - - -
- - - - + + - - - - - - - - -
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
- - - - + + - - - - - - - - -
- - - - + + - - - - - - - - -
- - - - + + - - - - - - - - -
- - - - + + - - - - - - - - -
- - - - + + - - - - - - - - -
- - - - + + - - - - - - - - -

10
bicicleta 2 1 1 0
comedor 3 4 1 1
lavadora 1 1 1 1
refrigerador 2 2 2 1
computadores 7 6 2 0
maletas 3 5 2 0
muebles 5 4 2 1

IIC1103 Captulo 8: Archivos 23


ropa 3 4 3 0
escritorio 2 3 1 0
armario 3 3 4 0

En el archivo anterior, la bodega posee 12 filas y 15 columnas, donde los + indican los espacio que siempre
deben estar libres, y los - indican los espacios que pueden ser utilizados por las encomiendas.

Su programa deber a asignar las encomiendas a la bodega, para lo cual debera buscar la primera ubicaci
on
con la cantidad de espacios vacos que permita posicionar cada encomienda respetando las dimensiones de su
embalaje. Debe mostrar en la consola el nombre de las encomiendas que no haya podido guardar en la bodega.

En este incremento deber a crear un main donde se le pide al usuario que ingrese el nombre del archivo
a cargar y se cargue el archivo asignando la distribuci
on correspondientes.

Incremento 2
En este incremento deber a agregar a su programa la funcionalidad que permita mostrar el estado de la
bodega posterior a la distribuci on de las encomiendas. Para esto debe mostrar la matriz que la representa,
poniendo una + en los espacio libres, un - en los espacio vacos y el identificador de la encomienda en
las celdas que esten utilizadas por una. Por ejemplo, para el archivo anterior se debera mostrar lo siguiente:

No fue posible asignar la encomienda: computadores

La distribucion de la Bodega es la siguiente:


1. bicicleta
2. comedor
3. lavadora
4. refrigerador
5. computadores
6. maletas
7. muebles
8. ropa
9. escritorio
10. armario

1 3 4 4 + + 2 2 2 2 6 6 6 6 6
1 - 4 4 + + 2 2 2 2 6 6 6 6 6
9 9 9 - + + 2 2 2 2 6 6 6 6 6
9 9 9 - + + - - - - - - - - -
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
7 7 7 7 + + 8 8 8 8 10 10 10 - -
7 7 7 7 + + 8 8 8 8 10 10 10 - -
7 7 7 7 + + 8 8 8 8 10 10 10 - -
7 7 7 7 + + - - - - - - - - -
7 7 7 7 + + - - - - - - - - -
- - - - + + - - - - - - - - -

Adem as, debera complementar la asignaci on de espacios realizada anteriormente, de manera que ahora su
programa sea capaz de rotar (probar intercambiando su largo con su ancho y viceversa) una encomienda
en caso que no sea posible asignarle una posicion de acuerdo con el criterio anterior. Por ejemplo, para el
archivo anterior se debera mostrar lo siguiente:

IIC1103 Captulo 8: Archivos 24


No fue posible asignar la encomienda: ropa
No fue posible asignar la encomienda: armario

La distribucion de la Bodega es la siguiente:


1. bicicleta
2. comedor
(...)

1 3 4 4 + + 2 2 2 2 6 6 6 6 6
1 - 4 4 + + 2 2 2 2 6 6 6 6 6
9 9 9 - + + 2 2 2 2 6 6 6 6 6
9 9 9 - + + - - - - - - - - -
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
7 7 7 7 + + 5 5 5 5 5 5 5 - -
7 7 7 7 + + 5 5 5 5 5 5 5 - -
7 7 7 7 + + 5 5 5 5 5 5 5 - -
7 7 7 7 + + 5 5 5 5 5 5 5 - -
7 7 7 7 + + 5 5 5 5 5 5 5 - -
- - - - + + 5 5 5 5 5 5 5 - -

Finalmente, deber a complementar nuevamente la asignaci on de espacios permitiendo que ahora su programa
sea capaz de ubicar una encomienda sobre otra ya asignada a la bodega en caso que no sea posible asignarle
una posicion de acuerdo con los criterios anteriores. Para ello, deber
a considerar que la encomienda sobre la
que se dispondra otra NO sea fragil, que tanto el largo como el ancho de la encomienda que quedar a arriba
sean menores o iguales que el ancho y que el largo de la que quedar a abajo, y que la altura de la nueva pila
no sea superior a 5. Considere que sobre una encomienda puede apilar s olo 1 encomienda. Por ejemplo, para
el archivo anterior se debera mostrar lo siguiente:
No fue posible asignar la encomienda: armario

La distribucion de la Bodega es la siguiente:


1. bicicleta
2. comedor
(...)

1 3 4 4 + + 2 2 2 2 6 6 6 6 6
1 - 4 4 + + 2 2 2 2 6 6 6 6 6
9 9 9 - + + 2 2 2 2 6 6 6 6 6
9 9 9 - + + - - - - - - - - -
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
7 7 7 7 + + 8(5) 8(5) 8(5) 8(5) 5 5 5 - -
7 7 7 7 + + 8(5) 8(5) 8(5) 8(5) 5 5 5 - -
7 7 7 7 + + 8(5) 8(5) 8(5) 8(5) 5 5 5 - -
7 7 7 7 + + 5 5 5 5 5 5 5 - -
7 7 7 7 + + 5 5 5 5 5 5 5 - -
- - - - + + 5 5 5 5 5 5 5 - -

Criterios de soluci
on
Posible soluci
on

IIC1103 Captulo 8: Archivos 25


import java . io .*;
import java . util .*;
import i i c 1 1 0 3 P a c k a g e .*;

public class Bodega {


private int [][] p o s i c i o n e s;
private E n c o m i e n d a[] e n c o m i e n d a s;
private int [] c a r g a A r r i b a;

public Bodega ( String filename ) throws I O E x c e p t i o n {


File archivo = new File ( filename );
if ( archivo . exists ()) {
Scanner lector = new Scanner ( archivo );
int filas = lector . nextInt ();
int cols = lector . nextInt ();
p o s i c i o n e s = new int [ filas ][ cols ];

// Leemos la i n f o r m a c i o n inicial desde el archivo


for ( int i = 0; i < p o s i c i o n e s. length ; i ++) {
for ( int j = 0; j < p o s i c i o n e s[ i ]. length ; j ++) {
String signo = lector . next ();
if ( signo . equals ( " -" )) {
p o s i c i o n e s[ i ][ j ] = -1;
} else {
p o s i c i o n e s[ i ][ j ] = -2;
}
}
}
// Leemos la cantidad de e n c o m i e n d a s
int n u m E n c o m i e n d a s = lector . nextInt ();
e n c o m i e n d a s = new E n c o m i e n d a[ n u m E n c o m i e n d a s ];
c a r g a A r r i b a = new int [ n u m E n c o m i e n d a s];
for ( int i = 0; i < c a r g a A r r i b a. length ; i ++) {
c a r g a A r r i b a[ i ] = -1;
}
// Leemos la i n f o r m a c i o n de cada e n c o m i e n d a
for ( int i = 0; i < e n c o m i e n d a s. length ; i ++) {
String nombre = lector . next ();
int largo = lector . nextInt ();
int ancho = lector . nextInt ();
int alto = lector . nextInt ();
int esFragil = lector . nextInt ();
boolean fragil = false ;
if ( esFragil == 1)
fragil = true ;
// Creamos la e n c o m i e n d a
e n c o m i e n d a s[ i ] = new E n c o m i e n d a( nombre , largo , ancho , alto , fragil );
// Le a s i g n a m o s una posicion en la matriz
if (! G u a r d a r E n c o m i e n d a( e n c o m i e n d a s[ i ] , i , false )
&& ! G u a r d a r E n c o m i e n d a( e n c o m i e n d a s[ i ] , i , true )
&& ! G u a r d a r E n c o m i e n d a E n c i m a( e n c o m i e n d a s[ i ] , i )) {
Usuario . m e n s a j e C o n s o l a( " No fue posible asignar la e n c o m i e n d a: "
+ e n c o m i e n d a s[ i ]. g e t N o m b r e ());
}
}
lector . close ();
}
}

public boolean G u a r d a r E n c o m i e n d a( E n c o m i e n d a encomienda , int idEncomienda , boolean rotar ) {


// R e c o r r e m o s toda la bodaga buscando una u b i c a c i o n con el espacio adecuado
int largo , ancho ;
if ( rotar ) {
largo = e n c o m i e n d a. getAncho ();
ancho = e n c o m i e n d a. getLargo ();
} else {
largo = e n c o m i e n d a. getLargo ();
ancho = e n c o m i e n d a. getAncho ();
}
// Primero buscamos si hay espacio vacio s u f i c i e n t e para g u a r d a r l o
for ( int i = 0; i <= p o s i c i o n e s. length - largo ; i ++) {
for ( int j = 0; j <= p o s i c i o n e s[ i ]. length - ancho ; j ++) {
boolean e n c o n t r a d o = true ;
for ( int u = i ; u < i + largo ; u ++) {
for ( int v = j ; v < j + ancho ; v ++) {
if ( p o s i c i o n e s[ u ][ v ] != -1) {

IIC1103 Captulo 8: Archivos 26


e n c o n t r a d o = false ;
}
}
}
// Al e n c o n t r a r un sector disponible , lo g u a r d a m o s ahi
if ( e n c o n t r a d o) {
for ( int u = i ; u < i + largo ; u ++) {
for ( int v = j ; v < j + ancho ; v ++) {
p o s i c i o n e s[ u ][ v ] = i d E n c o m i e n d a;
}
}
return true ;
}
}
}
return false ;
}

public boolean G u a r d a r E n c o m i e n d a E n c i m a( E n c o m i e n d a encomienda ,


int i d E n c o m i e n d a) {
// Si no hay s u p e r f i c i e s u f i c i e n t e desocupada , buscamos si hay un
// espacio sobre otras e n c o m i e n d a s
for ( int i = 0; i < i d E n c o m i e n d a; i ++) {
if ( e n c o m i e n d a s[ i ]. getLargo () >= e n c o m i e n d a. getLargo ()
&& e n c o m i e n d a s[ i ]. getAncho () >= e n c o m i e n d a. getAncho ()
&& e n c o m i e n d a s[ i ]. getLargo () >= e n c o m i e n d a. getAncho ()
&& e n c o m i e n d a s[ i ]. getAncho () >= e n c o m i e n d a. getLargo ()
&& ( e n c o m i e n d a s[ i ]. getAlto () + e n c o m i e n d a. getAlto ()) <= 5
&& ! e n c o m i e n d a s[ i ]. isFragil () && c a r g a A r r i b a[ i ] == -1) {
// Vamos a la esquina superior i z q u i e r d a de la e n c o m i e n d a que
// quedara debajo
for ( int j = 0; j < p o s i c i o n e s. length ; j ++) {
for ( int k = 0; k < p o s i c i o n e s[ j ]. length ; k ++) {
if ( p o s i c i o n e s[ j ][ k ] == i ) {
// G u a r d a m o s la e n c o m i e n d a encima de otra
for ( int u = j ; u < j + e n c o m i e n d a. getLargo (); u ++) {
for ( int v = k ; v < k + e n c o m i e n d a. getAncho (); v ++) {
p o s i c i o n e s[ u ][ v ] = i d E n c o m i e n d a;
}
}
// Marcamos la e n c o m i e n d a que queda abajo con el
// i d e n t i f i c a d o r de la que pusimos encima
c a r g a A r r i b a[ i ] = i d E n c o m i e n d a;
// Marcamos la e n c o m i e n d a que queda arriba para no
// seguir apilando sobre ambas
c a r g a A r r i b a[ i d E n c o m i e n d a] = i d E n c o m i e n d a;
return true ;
}
}
}
}
}
return false ;
}

public void M o s t r a r B o d e g a() {


Usuario . m e n s a j e C o n s o l a( " \ nLa d i s t r i b u c i o n de la Bodega es la s i g u i e n t e: " );
for ( int i = 0; i < e n c o m i e n d a s. length ; i ++) {
Usuario . m e n s a j e C o n s o l a (( i + 1) + " . " + e n c o m i e n d a s[ i ]. g e t N o m b r e());
}
String bodega = " \ n " ;
for ( int i = 0; i < p o s i c i o n e s. length ; i ++) {
for ( int j = 0; j < p o s i c i o n e s[ i ]. length ; j ++) {
if ( p o s i c i o n e s[ i ][ j ] == -2) {
bodega += " +\ t " ;
} else if ( p o s i c i o n e s[ i ][ j ] == -1) {
bodega += " -\ t " ;
} else {
bodega += ( p o s i c i o n e s[ i ][ j ] + 1);
for ( int k = 0; k < c a r g a A r r i b a. length ; k ++) {
if ( c a r g a A r r i b a[ k ] == p o s i c i o n e s[ i ][ j ]) {
bodega += " ( " + ( k + 1) + " ) " ;
break ;
}
}
bodega += " \ t " ;
}

IIC1103 Captulo 8: Archivos 27


}
bodega += " \ n " ;
}
Usuario . m e n s a j e C o n s o l a( bodega );
}
}
public class E n c o m i e n d a {
private String nombre ;
private int largo ;
private int ancho ;
private int alto ;
private boolean fragil ;

public E n c o m i e n d a( String nombre , int largo , int ancho , int alto ,


boolean fragil ) {
this . nombre = nombre ;
this . largo = largo ;
this . ancho = ancho ;
this . alto = alto ;
this . fragil = fragil ;
}

public String g e t I d e n t i f i c a i o n() {


return nombre + " ( " + alto + " ) " ;
}

public int getAlto () {


return alto ;
}

public int getAncho () {


return ancho ;
}

public int getLargo () {


return largo ;
}

public String g e t N o m b r e() {


return nombre ;
}

public boolean isFragil () {


return fragil ;
}
}
import java . io .*;
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 ) throws I O E x c e p t i o n {
// Pedimos al usuario el nombre del archivo
String n o m b r e A r c h i v o = Usuario . texto ( " Ingrese el nombre del archivo : " );
Bodega bodega = new Bodega ( n o m b r e A r c h i v o);
bodega . M o s t r a r B o d e g a ();
}
}

IIC1103 Captulo 8: Archivos 28


Problema 9: Mapa de Cotas
Enunciado
En este ejercicio deber
a realizar un programa que permita cargar un mapa de cotas desde un archivo. Este
mapa es una matriz de celdas, donde cada celda representa una peque na area de terreno monta noso. El
mapa contiene la altura del terreno junto con la densidad de oxigeno presente, pudiendo esta ir de 0 (nada
de oxigeno) a 100 % (completamente oxigenado).

Su programa deber
a ser capaz de cargar la informaci
on, mostrarla y permitir hacer consultar sobre el estado
del terreno.

El programa lo dividiremos en 2 subconjuntos incrementales. Le recomendamos no comenzar con el siguiente


subconjunto hasta terminar y probar el funcionamiento correcto del subconjunto actual.

Incremento 1
En este subconjunto su programa deber
a ser capaz de cargar el mapa desde un archivo, as como tambien
mostrar el mapa en la consola.

El archivo con el mapa mantendr a siempre el siguiente formato. En la primera lnea vendra el numero
de filas y el n
umero de columnas que conforman el terreno. Luego en cada lnea siguiente viene descrita la
informaci on para cada fila del mapa, indicando la altura para cada area, seguida de un y la calidad de
oxgeno; la informaci
on para cada area viene separada por un espacio.

A continuaci
on se muestra el contenido de un archivo de ejemplo:

3 3
1000*60 1000*70 1000*60
1000*80 3000*40 2000*70
1000*80 1000*80 2000*60

El archivo anterior muestra un terreno que en la primera fila tiene una altura de 1000 metros con densidades
de oxigeno de 60 %, 70 % y 60 %, la segunda fila tiene una altura de 1000, 3000 y 2000 metros con densidades
de oxigeno de 80 %, 40 % y 70 % y la tercera fila tiene una alturas de 1000, 1000 y 2000 metros con densidades
de oxigeno de 80 %, 80 % y 60 % .

Su programa debe mostrar en la consola el mapa de cotas y de oxigeno, para lo cual debe mostrar la
matriz que los representa, debe preguntar al usuario si desea ver las alturas o las densidades de oxigeno. Por
ejemplo, para el archivo anterior se debera mostrar el siguiente mensaje si desea ver las alturas:

ALTURAS
| 1000 | 1000 | 1000 |
| 1000 | 3000 | 2000 |
| 1000 | 1000 | 2000 |

Y debera mostrar el siguiente mensaje si desea ver las densidades de oxigeno:

OXIGENO
| 60 | 70 | 60 |
| 80 | 40 | 70 |
| 80 | 80 | 60 |

IIC1103 Captulo 8: Archivos 29


En este incremento deber a crear un main donde se le pide al usuario que ingrese el nombre del archivo a
cargar y luego se muestre el mapa cargado mostrando las alturas o las densidades de oxigeno.

Incremento 2
En este incremento deber a agregar a su programa la funcionalidad para poder ver los terrenos vecinos de
un area en particular. Para ello deberan pedirle al usuario que ingrese una posicion y en base a ella deber
an
mostrar en la consola las alturas junto con la densidades de las areas que la circundan. Un area es vecina de
otra cuando comparten al menos un vertice en com un. Tambien debe indicar si el area consultada es cima
(
area mas alta de entre las que la circundan), valle (area mas baja de entre las que la circundan) o nada en
particular.

Por ejemplo, si se pregunta para la hect


area en la posici
on (1, 1) se debera mostrar el siguiente mensa-
je:

Los terrenos vecinos tienen las siguientes caracteristicas [Oxigeno(Altura)]:


60%(1000) , 60%(1000) , 70%(1000) , 80%(1000) , 60%(2000) , 80%(1000) ,
80%(1000) , 70%(2000
El area consultada es cima.

Ahora su main luego de pedir el nombre del archivo y cargar el mapa, debe mostrar un men u desde donde
el usuario pueda elegir cargar mapa, ver el mapa (por alturas o densidades de oxigeno), ver los vecinos de
una cierta posicion (junto con consultar si el area es cima, valle o nada), o salir. Este men
u debe aparecer
constantemente hasta que el usuario seleccione salir.

Criterios de soluci
on
Posible soluci
on
public class Area {

private int altura ;


private int oxigeno ;

public Area ( int altura , int oxigeno ) {


this . altura = altura ;
this . oxigeno = oxigeno ;
}

public int g e t A l t u r a() {


return altura ;
}

public int g e t O x i g e n o() {


return oxigeno ;
}

}
import java . io .*;
import java . util .*;
import i i c 1 1 0 3 P a c k a g e .*;

public class Mapa {

Area [][] areas ;


String [] tipos ;

public Mapa ( String filename ) throws I O E x c e p t i o n {

File archivo = new File ( filename );

if ( archivo . exists ()) {


Scanner lector = new Scanner ( archivo );
// Leemos las d i m e n s i o n e s del mapa

IIC1103 Captulo 8: Archivos 30


int filas = lector . nextInt ();
int columnas = lector . nextInt ();
areas = new Area [ filas ][ columnas ];

for ( int i = 0; i < areas . length ; i ++) {


for ( int j = 0; j < areas [ i ]. length ; j ++) {
String info = lector . next ();
int altura = Integer . parseInt ( info . s u b s t r i n g(0 , info . indexOf ( " * " )));
int oxigeno = Integer . parseInt ( info . s u b s t r i n g( info . indexOf ( " * " ) + 1));
areas [ i ][ j ] = new Area ( altura , oxigeno );
}
}
} else {
Usuario . mensaje ( " No se e n c u e n t r a el Archivo : " + filename );
}
}

public void imprimir ( int s e l e c c i o n) {


String display = " " ;
if ( s e l e c c i o n == 1) {
Usuario . m e n s a j e C o n s o l a( " ALTURAS " );
} else {
Usuario . m e n s a j e C o n s o l a( " OXIGENO " );
}
for ( int i = 0; i < areas . length ; i ++) {
for ( int j = 0; j < areas [ i ]. length ; j ++) {
if ( s e l e c c i o n == 1) {
display += " \ t |\ t " + areas [ i ][ j ]. g e t A l t u r a();
} else {
display += " \ t |\ t " + areas [ i ][ j ]. g e t O x i g e n o();
}
}
display += " \ t |\ n " ;
}
Usuario . m e n s a j e C o n s o l a( display );
}

public void vecinos ( int i , int j ) {


String nombres = " Los terrenos vecinos tienen las s i g u i e n t e s c a r a c t e r i s t i c a s [ Oxigeno ( Altura )]: " ;
boolean cima = true , valle = true ;
// r e v i s a m o s arriba
if ( i >= 1) {
if ( j >= 1) {
nombres += " , " + areas [ i - 1][ j - 1]. g e t O x i g e n o() + " %("
+ areas [ i - 1][ j - 1]. g e t A l t u r a() + " ) " ;
if ( areas [ i - 1][ j - 1]. g e t A l t u r a() < areas [ i ][ j ]. g e t A l t u r a ()) {
valle = false ;
} else if ( areas [ i - 1][ j - 1]. g e t A l t u r a() > areas [ i ][ j ]. g e t A l t u r a()) {
cima = false ;
}
}
if ( j <= areas [ i ]. length - 2) {
nombres += " , " + areas [ i - 1][ j + 1]. g e t O x i g e n o() + " %("
+ areas [ i - 1][ j + 1]. g e t A l t u r a() + " ) " ;
if ( areas [ i - 1][ j + 1]. g e t A l t u r a() < areas [ i ][ j ]. g e t A l t u r a ()) {
valle = false ;
} else if ( areas [ i - 1][ j + 1]. g e t A l t u r a() > areas [ i ][ j ]. g e t A l t u r a()) {
cima = false ;
}
}

nombres += " , " + areas [ i - 1][ j ]. g e t O x i g e n o() + " %("


+ areas [ i - 1][ j ]. g e t A l t u r a() + " ) " ;
if ( areas [ i - 1][ j ]. g e t A l t u r a() < areas [ i ][ j ]. g e t A l t u r a ()) {
valle = false ;
} else if ( areas [ i - 1][ j ]. g e t A l t u r a() > areas [ i ][ j ]. g e t A l t u r a ()) {
cima = false ;
}
}
// r e v i s a m o s abajo
if ( i <= areas . length - 2) {
if ( j >= 1) {
nombres += " , " + areas [ i + 1][ j - 1]. g e t O x i g e n o() + " %("
+ areas [ i + 1][ j - 1]. g e t A l t u r a() + " ) " ;
if ( areas [ i + 1][ j - 1]. g e t A l t u r a() < areas [ i ][ j ]. g e t A l t u r a ()) {
valle = false ;
} else if ( areas [ i + 1][ j - 1]. g e t A l t u r a() > areas [ i ][ j ]. g e t A l t u r a()) {

IIC1103 Captulo 8: Archivos 31


cima = false ;
}
}
if ( j <= areas [ i ]. length - 2) {
nombres += " , " + areas [ i + 1][ j + 1]. g e t O x i g e n o() + " %("
+ areas [ i + 1][ j + 1]. g e t A l t u r a() + " ) " ;
if ( areas [ i + 1][ j + 1]. g e t A l t u r a() < areas [ i ][ j ]. g e t A l t u r a ()) {
valle = false ;
} else if ( areas [ i + 1][ j + 1]. g e t A l t u r a() > areas [ i ][ j ]. g e t A l t u r a()) {
cima = false ;
}
}
nombres += " , " + areas [ i + 1][ j ]. g e t O x i g e n o() + " %("
+ areas [ i + 1][ j ]. g e t A l t u r a() + " ) " ;
if ( areas [ i + 1][ j ]. g e t A l t u r a() < areas [ i ][ j ]. g e t A l t u r a ()) {
valle = false ;
} else if ( areas [ i + 1][ j ]. g e t A l t u r a() > areas [ i ][ j ]. g e t A l t u r a ()) {
cima = false ;
}
}
// r e v i s a m o s i z q u i e r d a
if ( j >= 1) {
nombres += " , " + areas [ i ][ j - 1]. g e t O x i g e n o() + " %("
+ areas [ i ][ j - 1]. g e t A l t u r a() + " ) " ;
if ( areas [ i ][ j - 1]. g e t A l t u r a() < areas [ i ][ j ]. g e t A l t u r a ()) {
valle = false ;
} else if ( areas [ i ][ j - 1]. g e t A l t u r a() > areas [ i ][ j ]. g e t A l t u r a ()) {
cima = false ;
}
}

// r e v i s a m o s derecha1
if ( j <= areas [ i ]. length - 2) {
nombres += " , " + areas [ i ][ j + 1]. g e t O x i g e n o() + " %("
+ areas [ i ][ j + 1]. g e t A l t u r a() + " ) " ;
if ( areas [ i ][ j + 1]. g e t A l t u r a() < areas [ i ][ j ]. g e t A l t u r a ()) {
valle = false ;
} else if ( areas [ i ][ j + 1]. g e t A l t u r a() > areas [ i ][ j ]. g e t A l t u r a ()) {
cima = false ;
}
}
nombres = nombres . s u b s t r i n g(0 , nombres . length () - 1);
Usuario . m e n s a j e C o n s o l a( nombres );
if ( cima ) {
Usuario . m e n s a j e C o n s o l a( " El area c o n s u l t a d a es cima . " );
} else if ( valle ) {
Usuario . m e n s a j e C o n s o l a( " El area c o n s u l t a d a es valle . " );
} else {
Usuario . m e n s a j e C o n s o l a( " El area c o n s u l t a d a no es nada . " );
}
}
}
import i i c 1 1 0 3 P a c k a g e .*;
import java . io . I O E x c e p t i o n;

public class P r i n c i p a l {

public static void main ( String [] args ) throws I O E x c e p t i o n {

int opcion = 1;
String filename = Usuario . texto ( " Ingrese el nombre del archivo a cargar " );
Mapa map = new Mapa ( filename );

while ( opcion != 4) {
opcion = -1;
while ( opcion < 1 || opcion > 4) {
opcion = Usuario . entero ( " que desea hacer ? " + " \ n1 Cargar mapa . "
+ " \ n2 Ver mapa " + " \ n3 Ver vecinos \ n " + " \ n4 Salir " );
}
if ( opcion == 1) {
map = new Mapa ( Usuario . texto ( " Ingrese el nombre del archivo a cargar " ));
}
if ( opcion == 2) {
int tipo = 0;
while ( tipo != 1 && tipo != 2) {
tipo = Usuario . entero ( " Desea ver :\ n1 Altura ? \ n2 Oxigeno ? " );

IIC1103 Captulo 8: Archivos 32


}
map . imprimir ( tipo );
}
if ( opcion == 3) {
map . vecinos ( Usuario . entero ( " ingrese c o o r e d e n a d a x " ) ,
Usuario . entero ( " ingrese c o o r e d e n a d a y " ));
}
}
}
}

IIC1103 Captulo 8: Archivos 33


Problema 10: Muebles en Habitaci
on
Enunciado
En este ejercicio debera realizar un programa que permita distribuir los muebles en una habitaci
on. La habi-
tacion estar
a representada como una matriz, donde cada celda representar a un espacio en la habitaci
on. En
un comienzo, cada espacio podra estar vaco o estar marcado como libre. Al momento de asignar los muebles
a la habitacion no se podran utilizar aquellos espacios que se encuentren marcados como libres.

Cada mueble tendr


a un nombre y un tama
no definido por la cantidad de celdas que utiliza.

El programa lo dividiremos en 2 subconjuntos incrementales. Le recomendamos no comenzar con el siguiente


subconjunto hasta terminar y probar el funcionamiento correcto del subconjunto actual.

Incremento 1
En este subconjunto su programa deber
a ser capaz de cargar la habitaci
on desde un archivo, as como tam-
bien asignar los muebles a ella.

El archivo con la habitacion mantendra siempre el mismo formato. En la primera lnea se indicar a el n
umero
de filas y columnas de la habitaci on. Luego el archivo contendr a la descripcion de cada celda de la sala,
donde el caracter - indicar
a un espacio vaco, y el caracter X indicar
a un espacio marcado como libre.

Luego de eso, el archivo contendr a el numero de muebles a distribuir, para despues contener en cada li-
nea la descripcion de cada uno de los muebles. Para cada mueble se encontrara el nombre del mueble (puede
asumir que nunca contendr a espacio), el tama
no en filas y el tama
no en columnas.

A continuaci
on se muestra el contenido de un archivo de ejemplo:

8 11
- - X - - - - - X - -
- - X - - - - - X - -
- - X X X - - - X - -
- - - - X - - X X - -
- - - X X - - X - - -
- - - X X - - X - - -
- - - X X X X X - - -
- - - - - X X - - - -
10
silla1 2 2
silla2 2 2
sillon1 4 2
mesa1 5 3
velador 1 2
sofa1 2 3
mesa2 2 5
sofa2 2 3
sillon2 2 3
silla3 2 2

En el archivo anterior, la sala posee 8 filas y 11 columnas, donde las X indican los espacio que siempre deben
estar libres, y los - indican los espacios que pueden ser utilizados por los muebles.

IIC1103 Captulo 8: Archivos 34


Su programa deber a asignar los muebles a la sala, para lo cual deber
a buscar la primera ubicaci
on con la can-
tidad de espacios vacos que permita posicionar el mueble, respetando las dimensiones de filas y columnas del
mueble. Debe mostrar en la consola el nombre de aquellos muebles que no hayan podido posicionar en la sala.

En este incremento deber a crear un main donde se le pide al usuario que ingrese el nombre del archivo
a cargar y se cargue el archivo asign
andose los muebles correspondientes.

Incremento 2
En este incremento deber a agregar a su programa la funcionalidad que permita mostrar el estado de la sala
posterior a la distribuci
on de los muebles. Para esto debe mostrar la matriz que lo representa, poniendo una
X en los espacio libres, un - en los espacio vacos y el nombre del mueble en los lugares utilizados por un
mueble. Por ejemplo, para el archivo anterior se debera mostrar lo siguiente:

silla1 silla1 X silla2 silla2 sillon1 sillon1 - X velador velador


silla1 silla1 X silla2 silla2 sillon1 sillon1 - X silla3 silla3
- - X X X sillon1 sillon1 - X silla3 silla3
mesa1 mesa1 mesa1 - X sillon1 sillon1 X X - -
mesa1 mesa1 mesa1 X X - - X sofa1 sofa1 sofa1
mesa1 mesa1 mesa1 X X - - X sofa1 sofa1 sofa1
mesa1 mesa1 mesa1 X X X X X sofa2 sofa2 sofa2
mesa1 mesa1 mesa1 - - X X - sofa2 sofa2 sofa2

Adem as su programa deber a ser capaz de, al momento de asignar un mueble, en caso de no ser posible
asignarlo, rotarlo y volver a probar. Por ejemplo si las dimensiones del mueble son 3 filas y 2 columnas y no
es posible asignarlo, se debe probar la asignaci on para 2 filas y 3 columnas. En este caso, la asignaci
on al
archivo anterior sera la siguiente:

silla1 silla1 X silla2 silla2 sillon1 sillon1 - X velador velador


silla1 silla1 X silla2 silla2 sillon1 sillon1 - X sillon2 sillon2
- - X X X sillon1 sillon1 - X sillon2 sillon2
mesa1 mesa1 mesa1 - X sillon1 sillon1 X X sillon2 sillon2
mesa1 mesa1 mesa1 X X silla3 silla3 X sofa1 sofa1 sofa1
mesa1 mesa1 mesa1 X X silla3 silla3 X sofa1 sofa1 sofa1
mesa1 mesa1 mesa1 X X X X X sofa2 sofa2 sofa2
mesa1 mesa1 mesa1 - - X X - sofa2 sofa2 sofa2

Por u ltimo, su programa deber a mostrar en consola las dimensiones del mueble m as grande que podra ser
asignado, buscando el espacio (rectangular) m as grande dentro de la sala. Por ejemplo, para el archivo an-
terior el espacio mas grande es 3, 1.

El main debera pedir al usuario el nombre del archivo, cargar el mapa asignando los muebles, mostrar
el mapa y luego mostrar el espacio m
as grande en la sala.

Criterios de soluci
on
Posible soluci
on
import java . io .*;
import java . util .*;
import i i c 1 1 0 3 P a c k a g e .*;

public class Sala {


private int [][] p o s i c i o n e s;
private String [] muebles ;

IIC1103 Captulo 8: Archivos 35


public Sala ( String filename ) throws I O E x c e p t i o n {
File archivo = new File ( filename );
if ( archivo . exists ()) {
Scanner lector = new Scanner ( archivo );
int filas = lector . nextInt ();
int cols = lector . nextInt ();
p o s i c i o n e s = new int [ filas ][ cols ];

// Leemos la i n f o r m a c i o n inicial desde el archivo


for ( int i = 0; i < p o s i c i o n e s. length ; i ++) {
for ( int j = 0; j < p o s i c i o n e s[ i ]. length ; j ++) {
// Segun el signo d e f i n i m o s algun valor , el cual es invalido
String signo = lector . next ();
if ( signo . equals ( " -" )) {
p o s i c i o n e s[ i ][ j ] = -1;
} else {
p o s i c i o n e s[ i ][ j ] = -2;
}
}
}

// Ahora leemos los muebles


int n u m M u e b l e s = lector . nextInt ();
muebles = new String [ n u m M u e b l e s];
for ( int i = 0; i < muebles . length ; i ++) {
// Leemos los datos del mueble e i n t e n t a m o s p o s i c i o n a r l o
String nombre = lector . next ();
int f i l a s M u e b l e = lector . nextInt ();
int c o l s M u e b l e = lector . nextInt ();
muebles [ i ] = nombre ;
if (! A s i g n a r M u e b l e(i , filasMueble , c o l s M u e b l e)
&& ! A s i g n a r M u e b l e(i , colsMueble , f i l a s M u e b l e)) {
Usuario . m e n s a j e C o n s o l a( " No fue posible asignar el mueble : "
+ nombre );
}
}
lector . close ();
}
}

public boolean A s i g n a r M u e b l e( int idx , int filas , int columnas ) {


// R e c o r r e m o s toda la sala buscando una u b i c a c i o n con el espacio
// adecuado . Desde cada posicion
// posible c o m e n z a m o s a buscar si es posible ubicarlo en esa posicion
for ( int i = 0; i <= p o s i c i o n e s. length - filas ; i ++) {
for ( int j = 0; j <= p o s i c i o n e s[ i ]. length - columnas ; j ++) {
// R e v i s a m o s si es posible p o s i c i o n a r en esta u b i c a c i o n el mueble
boolean e n c o n t r a d o = true ;
for ( int u = i ; u < i + filas ; u ++) {
for ( int v = j ; v < j + columnas ; v ++) {
if ( p o s i c i o n e s[ u ][ v ] != -1) {
e n c o n t r a d o = false ;
}
}
}
if ( e n c o n t r a d o) { // Indica que e n c o n t r a m o s una posicion
// A s i g n a m o s el mueble
for ( int u = i ; u < i + filas ; u ++) {
for ( int v = j ; v < j + columnas ; v ++) {
p o s i c i o n e s[ u ][ v ] = idx ;
}
}
return true ;
}
}
}
return false ;
}

public void M o s t r a r S a l a() {


String sala = " Detalle de la H a b i t a c i o n\ n \ n " ;
for ( int i = 0; i < p o s i c i o n e s. length ; i ++) {
for ( int j = 0; j < p o s i c i o n e s[ i ]. length ; j ++) {
// R e v i s a m o s si la posicion esta vacia , es camino , o existe
// algun mueble
if ( p o s i c i o n e s[ i ][ j ] == -2) {
sala += " X \ t " ;

IIC1103 Captulo 8: Archivos 36


} else if ( p o s i c i o n e s[ i ][ j ] == -1) {
sala += " -\ t " ;
} else {
sala += muebles [ p o s i c i o n e s[ i ][ j ]] + " \ t " ;
}
}
sala += " \ n " ;
}
Usuario . m e n s a j e C o n s o l a( sala );
}

public void E s p a c i o M a y o r() {


// Probamos los d i s t i n t o s tamanos hasta que alguno ya no sea posible
// ninguno
// Para ello r e u t i l i z a m o s el metodo asignar mueble
int m e j o r F i l a s = 0;
int m e j o r C o l s = 0;
for ( int filas = 1; filas < p o s i c i o n e s. length ; filas ++) {
for ( int cols = 1; cols < p o s i c i o n e s[ filas - 1]. length ; cols ++) {
// R e v i s a m o s si es posible asignar un mueble de las d i m e n s i o n e s
// buscadas
if ( filas + cols > m e j o r F i l a s + m e j o r C o l s
&& A s i g n a r M u e b l e( -1 , filas , cols )) {
m e j o r F i l a s = filas ;
m e j o r C o l s = cols ;
}
}
}
Usuario . m e n s a j e C o n s o l a( " El mueble mas grande puede tener las d i m e n s i o n e s: "
+ m e j o r F i l a s + " , " + m e j o r C o l s);
}
}
import java . io .*;
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 ) throws I O E x c e p t i o n {
// Pedimos al usuario el nombre del archivo
String n o m b r e A r c h i v o = Usuario . texto ( " Ingrese el nombre del archivo : " );
Sala h a b i t a c i o n = new Sala ( n o m b r e A r c h i v o);
h a b i t a c i o n. M o s t r a r S a l a ();
h a b i t a c i o n. E s p a c i o M a y o r ();
}
}

IIC1103 Captulo 8: Archivos 37


Problema 11: Cultivo de Flores
Enunciado
En este ejercicio debera realizar un programa que permita cargar un mapa desde un archivo. Este mapa
es una matriz de celdas, donde cada celda representa una hect area de cultivo de flores. El mapa contiene
la densidad de flores plantadas en cada celda, pudiendo esta ir de 0 (ninguna flor) a 100 (completamente
plantada). Cada hect area puede estar plantada con s
olo un tipo de flor, existiendo tres posibilidades: rosas,
claveles y tulipanes.

Su programa debera ser capaz de cargar la informaci


on, mostrarla y permitir hacer consultar sobre el estado
del predio completo.

El programa lo dividiremos en 2 subconjuntos incrementales. Le recomendamos no comenzar con el siguiente


subconjunto hasta terminar y probar el funcionamiento correcto del subconjunto actual.

Incremento 1
En este subconjunto su programa deber
a ser capaz de cargar el mapa desde un archivo, as como tambien
mostrar el mapa en la consola.

El archivo con el mapa mantendr a siempre el siguiente formato. En la primera lnea vendr a el n
umero
de filas y el numero de columnas que forman el mapa. Luego en la siguiente lnea vendr a el tipo de flor
seguido por un espacio, y por el n umero de hectareas que tienen plantada esa flor. Luego de ello, se indi-
car
a la fila, columna y densidad de cada una de las hectareas correspondientes al tipo de flor indicado. Esta
estructura se repite para los tres tipos de flor.

A continuaci
on se muestra el contenido de un archivo de ejemplo:

3 3
rosa 3
1 1 10
1 2 20
1 3 30
clavel 2
2 1 40
2 3 60
tulipan 3
3 1 70
3 2 80
3 3 90

En el archivo anterior, se encuentran rosas plantadas en la primera fila con densidades del 10 %, 20 % y 30 %,
claveles en la segunda, con densidades del 40 % y 60 %, y tulipanes en la tercera con densidades del 70 %,
80 % y 90 %,.

Su programa debe mostrar en la consola el mapa, para lo cual debe mostrar la matriz que lo represen-
ta, poniendo una X en los espacio que no hay plantaciones, y, el nombre de la plantaci on en conjunto con su
densidad, en las hect
areas plantadas. Por ejemplo, para el archivo anterior se debera mostrar lo siguiente:

| rosa(10) | rosa(20) | rosa(30) |


| clavel(40) | X | clavel(60) |
| tulipan(70) | tulipan(80) | tulipan(90) |

IIC1103 Captulo 8: Archivos 38


En este incremento debera crear un main donde se le pide al usuario que ingrese el nombre del archivo a
cargar y luego se muestra el mapa cargado.

Incremento 2
En este incremento debera agregar a su programa la funcionalidad para poder ver las densidades promedio
de los vecinos de una hect
area particular. Para ello deber
an pedirle al usuario que ingrese una posici
on y
en base a ella debera mostrar en la consola los nombres de los tipos de flores plantadas alrededor de ella
junto con las densidades promedio para ellos. Una hectarea es vecina de otra cuando comparten al menos
un vertice en com
un.

Por ejemplo, si se pregunta para la hect


area en la posici
on (1, 1) se debera mostrar el siguiente mensa-
je:

Las densidades promedio de los vecinos son:


tulipan(80)
clavel(50)
rosa(20)

Donde tulipan(80) se forma por el promedio de las tres hect


areas vecinas que tienen plantados tulipanes.

En caso de que se pregunte para la hect


area en la posici
on (1, 2) se debera mostrar el siguiente mensa-
je:

Las densidades promedio de los vecinos son: rosa(25), tulipan(85).

Ahora su main luego de pedir el nombre del archivo y cargar el mapa, debe mostrar un men u desde donde el
usuario pueda elegir cargar mapa, ver el mapa, ver los vecinos de una cierta posicion, o salir. Este men
u debe
aparecer constantemente hasta que el usuario seleccione salir.

Criterios de soluci
on
Posible soluci
on
public class Hectarea {
private String tipo ;
private int densidad ;

public Hectarea ( String tipo , int densidad ) {


this . tipo = tipo ;
this . densidad = densidad ;
}

public int g e t D e n s i d a d() {


return densidad ;
}

public String getTipo () {


return tipo ;
}

public String getInfo () {


return tipo + " ( " + densidad + " ) " ;
}
}
import java . io .*;
import java . util .*;
import i i c 1 1 0 3 P a c k a g e .*;

public class Mapa {


private Hectarea [][] terreno ;
private String [] tipos ;

IIC1103 Captulo 8: Archivos 39


public Mapa ( String filename ) throws I O E x c e p t i o n {
File archivo = new File ( filename );
String t i p o s J u n t o s = " " ;

if ( archivo . exists ()) {


Scanner lector = new Scanner ( archivo );
// Leemos las d i m e n s i o n e s del mapa
int filas = lector . nextInt ();
int columnas = lector . nextInt ();
terreno = new Hectarea [ filas ][ columnas ];

// Leemos la i n f o r m a c i o n de cada tipo de flor y la cargamos en el


// terreno
for ( int i = 0; i < 3; i ++) {
String nombre = lector . next ();
t i p o s J u n t o s += nombre + " " ;
int total = lector . nextInt ();
// Vemos la i n f o r m a c i o n de cada hectarea p e r t e n e c i e n t e a este
// tipo de flor
for ( int j = 0; j < total ; j ++) {
int posx = lector . nextInt ();
int posy = lector . nextInt ();
int densidad = lector . nextInt ();
terreno [ posx ][ posy ] = new Hectarea ( nombre , densidad );
}
}
tipos = t i p o s J u n t o s. split ( " " );
} else {
Usuario . mensaje ( " No se e n c u e n t r a el Archivo : " + filename );
}
}

public void Imprimir () {


String display = " " ;
// R e c o r r e m o s cada posicion y segun su c o n t e n i d o g e n e r a m o s el ouput
for ( int i = 0; i < terreno . length ; i ++) {
for ( int j = 0; j < terreno [ i ]. length ; j ++) {
if ( terreno [ i ][ j ] != null ) {
display += " \ t |\ t " + terreno [ i ][ j ]. getInfo ();
} else {
display += " \ t |\ tX \ t " ;
}
}
display += " \ t |\ n " ;
}
Usuario . m e n s a j e C o n s o l a( display );
}

public void D e n s i d a d V e c i n o s( int i , int j ) {


// Creamos dos arreglos , uno para contar la cantidad de vecinos de cada
// tipo y otro para acumular los valores
int [] c a n t i d a d T i p o = new int [ tipos . length ];
int [] sumaTipo = new int [ tipos . length ];

// R e c o r r e m o s las p o s i c i o n e s de a l r e d e d o r del punto indicado


for ( int u = i - 1; u <= i + 1; u ++) {
for ( int v = j - 1; v <= j + 1; v ++) {
// R e v i s a m o s que estemos dentro de los limites y que la posicion
// no sea vacia
if ( u >= 0 && u < terreno . length && v >= 0
&& v < terreno [ i ]. length && terreno [ u ][ v ] != null ) {
// Lo acumulamos , para ello buscamos el indice segun el tipo
int idx = 0;
for ( int k = 0; k < tipos . length ; k ++) {
if ( tipos [ k ]. equals ( terreno [ u ][ v ]. getTipo ())) {
idx = k ;
}
}
c a n t i d a d T i p o[ idx ]++;
sumaTipo [ idx ] += terreno [ u ][ v ]. g e t D e n s i d a d();
}
}
}
// G e n e r a m o s el texto a d e s p l e g a r
String display = " Las d e n s i d a d e s promedio de los vecinos son : \ n " ;
for ( int u = 0; u < tipos . length ; u ++) {
if ( c a n t i d a d T i p o[ u ] > 0) {

IIC1103 Captulo 8: Archivos 40


double promedio = (( double ) sumaTipo [ u ]) / c a n t i d a d T i p o[ u ];
display += tipos [ u ] + " ( " + promedio + " )\ n " ;
}
}
Usuario . m e n s a j e C o n s o l a( display );
}
}
import i i c 1 1 0 3 P a c k a g e .*;
import java . io . I O E x c e p t i o n;

public class P r i n c i p a l {
public static void main ( String [] args ) throws I O E x c e p t i o n {
int opcion = 1;
String filename = Usuario . texto ( " Ingrese el nombre del archivo a cargar " );
Mapa p l a n t a c i o n = new Mapa ( filename );

while ( opcion != 4) {
opcion = -1;
while ( opcion < 1 || opcion > 4) {
opcion = Usuario . entero ( " que desea hacer ? "
+ " \ n (1) Cambiar mapa . " + " \ n (2) Ver mapa "
+ " \ n (3) Ver densidad promedio vecinos \ n "
+ " \ n (4) Salir " );
}
if ( opcion == 1) {
p l a n t a c i o n = new Mapa ( Usuario . texto ( " Ingrese el nombre del archivo a cargar " ));
} else if ( opcion == 2) {
p l a n t a c i o n. Imprimir ();
} else if ( opcion == 3) {
int fila = Usuario . entero ( " Ingrese la fila " );
int columna = Usuario . entero ( " Ingrese la columna " );
p l a n t a c i o n. D e n s i d a d V e c i n o s( fila , columna );
}
}
}
}

IIC1103 Captulo 8: Archivos 41


Problema 12: Combate Naval
Enunciado
Debe implementar un programa que simule un juego simplificado de combate naval.

Se le pide implementar una clase, CombateNaval, que simule un juego de combate naval simplificado. Ademas,
existen dos clases mas que ya est
an implementadas: InterfazGrafica, que permite mostrar gr aficamente el
juego, y Principal, que contiene el main del programa.

La clase InterfazGrafica ya est a creada por lo que usted NO DEBE IMPLEMENTARLA. Tiene los
siguientes metodos que usted puede utilizar:

public InterfazGrafica(): constructor, crea un objeto de esta clase.


public int mostrarEstadoJugador(int[][] tablero, int numBombas): muestra gr aficamente el
tablero de ataques del jugador y cu antas bombas le quedan. Adem as, indica al usuario un men u de
opciones, y le permite elegir una. Recibe como par
ametros el tablero del jugador, y el total de bombas
que tiene en ese momento. Retorna 1 si eligio atacar, 2 si eligi
o ver los barcos, o 3 si eligi
o salir del
programa.
public void mostrarTableroBarcos(int[][] tablero): muestra gr aficamente el tablero con los
barcos solamente. Recibe como parametro el tablero de los barcos.
public int[] getCoordenadas(int tamanoMax): pide al usuario un par de coordenadas. Recibe co-
mo par ametro el tama no de filas o columnas del tablero, y pide dos enteros al usuario, validando que
esten entre 1 y ese valor de tama no. Retorna un arreglo de enteros con los dos valores ingresados por
el usuario.

La interfaz gr
afica muestra smbolos en el tablero; la leyenda es la siguiente:

= agua o desconocido
o = parte de un barco
+ = parte de un barco da
nada
* = bomba que dio en el agua

CombateNaval: Esta clase simular a un juego de combate naval, en donde el computador tendr a un tablero
con barcos repartidos en el, cuyas posiciones el jugador no conocer
a. El jugador tendr
a un lmite maximo de
bombas a utilizar para intentar destruir los barcos del computador, adivinando sus posiciones.

Esta clase debe tener los siguientes atributos:

Una matriz para almacenar un mapa con barcos.


Una matriz para almacenar los ataques del jugador.
Un entero para almacenar la cantidad de bombas disponibles.
Un objeto de tipo InterfazGrafica para mostrar el tablero.

Adem
as, esta clase debe tener los siguientes metodos

public CombateNaval(): El constructor crea un nuevo CombateNaval, inicializando su atributo in-


terno de tipo InterfazGrafica.

IIC1103 Captulo 8: Archivos 42


public boolean CargarTablero(String nombreArchivo) throws IOException: metodo encarga-
do de leer un archivo con la informacion del juego, y cargarlo en el objeto CombateNaval. En particular,
debe abrir el archivo indicado por nombreArchivo, y retornar false si no existe. Si existe, debe leerlo y
obtener la informacion de la cantidad de bombas, tama no del tablero y barcos en el tablero. El formato
de un archivo valido es el siguiente:

6
3
0 1 1
0 0 0
1 1 0

En donde cada lnea indica lo siguiente:


La primera lnea contiene 1 entero, que indica la cantidad de bombas inicialmente disponibles al
usuario.
La segunda lnea contiene 1 entero, que indica la cantidad de filas y columnas del tablero (es un
tablero cuadrado).
Las lneas siguientes corresponden a las filas del tablero. Cada lnea contiene un entero para cada
una de las columnas del tablero, separados por 1 espacio. Los valores posibles son 0, si hay agua
en ese lugar del tablero, o 1, si hay parte de un barco en ese lugar del tablero. Se asumir a que la
distribucion de los barcos es siempre horizontal o vertical; es decir, no habran barcos en diagonal.
Este metodo debe adem as inicializar el tablero del jugador con todos los valores en 0, y retornar true
si pudo hacer todo lo indicado.
public boolean Atacar(int x, int y): metodo que lanza una bomba del jugador en el tablero.
Recibe dos par ametros, x e y, indicando la posicion en la matriz, cada uno con valores entre 1 y el
tama no maximo de fila o columna (recuerde que la primera posici on en un arreglo o matriz es la 0).
NO DEBE MODIFICAR EL TABLERO DE BARCOS, solamente debe revisarlo para ver si la bomba
llega sobre un barco en las coordenadas (x, y). Luego debe modificar el tablero del jugador, poniendo
un 2 en el lugar (x, y) si da
no un barco, o un 3 si dio en el agua. Ademas, debe disminuir el total de
bombas del jugador. Est a permitido que un jugador lance una bomba dos veces en el mismo lugar; no
es necesario evitar esto.

public boolean RevisarSiGano(): metodo que revisa si el jugador destruy o todas las partes de todos
los barcos. Debe revisar los tableros, y si da
no todas las partes de todos los barcos, retorna true; si no,
retorna false.
public void IniciarJuego() throws IOException: el metodo principal del juego, debe tener un
ciclo constante en el que obtiene la opci
on del usuario a traves del objeto de InterfazGrafica (mos-
trando el tablero al mismo tiempo), y realiza la acci
on indicada por el usuario (mas abajo se definir
an
los metodos de la clase InterfazGrafica). Las acciones son las siguientes, dependiendo del entero que
se reciba:
(1) Atacar: usa el objeto InterfazGrafica para obtener las coordenadas de fila y columna en donde
lanzar una bomba, y usa la funci on interna de esta clase Atacar() para atacar en un lugar. Revisa
el exito de Atacar(); si da no un barco, muestra el mensaje Da naste un barco!; si no, muestra
el mensaje Al agua. Posteriormente usa la funci on interna de esta clase, RevisarSiGano(); si
retorna true, muestra el mensaje Destruiste todos los barcos! Ganaste!, y termina el programa.
Debe adem as revisar si se acabaron las bombas; en ese caso, debe mostrar el mensaje Te quedaste
sin bombas! Perdiste el juego. y terminar el programa. No debe detectar cuando se destruye 1
barco; solamente debe avisar cuando se destruyen todos.

IIC1103 Captulo 8: Archivos 43


(2) Ver barcos (trampa!): usa el objeto InterfazGrafica para mostrar las posiciones de los
barcos almacenadas en el tablero de los barcos. No debera usarse para jugar, sino que solamente
para revisi
on.
(3) Salir: termina el programa.

La clase Principal, que contiene el main del programa, ya est


a implementada, por lo que usted NO DEBE
IMPLEMENTARLA. A modo de explicaci on, a continuaci
on se indican las acciones realizadas dentro del
main:

Crea un objeto CombateNaval.


Pide al usuario el nombre del archivo a usar (por defecto viene con el nombre test.txt).
Carga el archivo.
Inicia el juego

A continuaci
on se muestran las dos clases ya implementadas

import i i c 1 1 0 3 P a c k a g e .*;

/* * Clase que sirve como interfaz grafica simple del juego C o m b a t e N a v a l */


public class I n t e r f a z G r a f i c a {
/* * Muestra el estado de un jugador y un menu de opciones
* @param tablero el tablero
* @param n u m B o m b a s la cantidad de bombas d i s p o n i b l e s
* @return */
public int m o s t r a r E s t a d o J u g a d o r( int [][] tablero , int n u m B o m b a s) {
// Arma el mensaje a mostrar
String mensaje = " " ;
mensaje += g e t S t r i n g T a b l e r o( tablero );
mensaje += " \ nQuedan " + n u m B o m b a s + " bombas d i s p o n i b l e s.\ n " ;
mensaje += " \ nElija una opcion :\ n (1) Atacar \ n (2) Ver barcos ( trampa !)\ n (3) Salir \ n " ;

// Obtiene la opcion del usuario , m o s t r a n d o l e todo


int opcion = Usuario . entero ( mensaje );
return opcion ;
}

/* * Funcion que muestra en pantalla el tablero con los barcos


* @param tablero el tablero */
public void m o s t r a r T a b l e r o B a r c o s( int [][] tablero ) {
String mensaje = " Tablero con los barcos : " ;
mensaje += g e t S t r i n g T a b l e r o( tablero );
Usuario . mensaje ( mensaje );
}

/* * Pide al usuario las coordenadas , y retorna un arreglo con ellas


* @return */
public int [] g e t C o o r d e n a d a s( int t a m a n o M a x) {
int [] c o o r d e n a d a s = new int [2];
do {
c o o r d e n a d a s[0] = Usuario . entero ( " Ingrese la c o o r d e n a d a x ( entre 1 y "
+ t a m a n o M a x + " ): " );
} while ( c o o r d e n a d a s [0] < 1 || c o o r d e n a d a s [0] > t a m a n o M a x);
do {
c o o r d e n a d a s[1] = Usuario . entero ( " Ingrese la c o o r d e n a d a y ( entre 1 y "
+ t a m a n o M a x + " ): " );
} while ( c o o r d e n a d a s [1] < 1 || c o o r d e n a d a s [1] > t a m a n o M a x);
return c o o r d e n a d a s;
}

/* * Arma un string con el tablero y lo retorna


* @param tablero el tablero con enteros con la i n f o r m a c i o n
* @return un string con el tablero r e p r e s e n t a d o */
private String g e t S t r i n g T a b l e r o( int [][] tablero ) {
// Ponemos borde superior
String t a b l e r o M o s t r a d o = " \ n " ;
for ( int i = 0; i < tablero . length * 4 - 5; i ++) {
t a b l e r o M o s t r a d o += " _ " ;

IIC1103 Captulo 8: Archivos 44


}
t a b l e r o M o s t r a d o += " \ n " ;
// Ciclo para todas las filas
for ( int i = 0; i < tablero . length ; i ++) {
// Armamos fila
t a b l e r o M o s t r a d o += " | " ;
for ( int j = 0; j < tablero . length ; j ++) {
switch ( tablero [ i ][ j ]) {
case 0:
t a b l e r o M o s t r a d o += " ~";
break ;
case 1:
t a b l e r o M o s t r a d o += " o";
break ;
case 2:
t a b l e r o M o s t r a d o += " +";
break ;
case 3:
t a b l e r o M o s t r a d o += " *";
break ;
}
}
t a b l e r o M o s t r a d o += " |\ n " ;
}

// Ponemos borde inferior


for ( int i = 0; i < tablero . length * 4 - 5; i ++) {
t a b l e r o M o s t r a d o += " _ " ;
}
t a b l e r o M o s t r a d o += " \ n " ;
return t a b l e r o M o s t r a d o;
}
}

import i i c 1 1 0 3 P a c k a g e .*;
import java . io .*;
public class P r i n c i p a l {

public static void main ( String [] args ) throws I O E x c e p t i o n {


// Crea el objeto del juego
C o m b a t e N a v a l juego = new C o m b a t e N a v a l ();

// Cargamos archivo con tablero


String n o m b r e A r c h i v o = Usuario . texto ( " Ingrese el nombre del archivo " , " test . txt " );
if ( juego . C a r g a r T a b l e r o( n o m b r e A r c h i v o) == false ) {
Usuario . mensaje ( " Error leyendo archivo " );
return ;
}
// Comienza el juego
juego . I n i c i a r J u e g o ();
}
}

Criterios de soluci
on
Posible soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
import java . io .*;
import java . util . Scanner ;

public class C o m b a t e N a v a l {
int [][] t a b l e r o B a r c o s;
int [][] t a b l e r o J u g a d o r;
int n u m B o m b a s;
I n t e r f a z G r a f i c a GUI ;

/* * C o n s t r u c t o r */
public C o m b a t e N a v a l() {
GUI = new I n t e r f a z G r a f i c a ();
}

/* * Funcion p r i n c i p a l del juego


* @throws I O E x c e p t i o n */

IIC1103 Captulo 8: Archivos 45


public void I n i c i a r J u e g o() throws I O E x c e p t i o n {
// Ciclo p r i n c i p a l
boolean salir = false ;
while (! salir ) {
// M o s t r a m o s tablero , o b t e n e m o s opcion y r e v i s a m o s
int opcion = GUI . m o s t r a r E s t a d o J u g a d o r( tableroJugador , n u m B o m b a s);
switch ( opcion ) {
case 1:
// O b t e n e m o s c o o r d e n a d a s
int [] c o o r d e n a d a s = GUI . g e t C o o r d e n a d a s( t a b l e r o J u g a d o r. length );
// Atacamos y avisamos
boolean exito = Atacar ( c o o r d e n a d a s[0] , c o o r d e n a d a s [1]);
if ( exito ) {
Usuario . mensaje ( " Le diste a un barco ! " );
} else {
Usuario . mensaje ( " Al agua " );
}
// Revisa si gano
if ( R e v i s a r S i G a n o ()) {
Usuario . mensaje ( " D e s t r u i s t e todos los barcos ! Ganaste ! " );
return ;
} else if ( n u m B o m b a s == 0) {
Usuario . mensaje ( " Te quedaste sin bombas ! Perdiste el juego . " );
return ;
}
break ;
case 2:
GUI . m o s t r a r T a b l e r o B a r c o s( t a b l e r o B a r c o s);
break ;
case 3:
salir = true ;
break ;
}
}
}

/* * Lee un archivo con i n f o r m a c i o n del tablero y lo carga en las v a r i a b l e s


* internas
* @param n o m b r e A r c h i v o el nombre del archivo a leer
* @return true si pudo leer el archivo , false si no
* @throws I O E x c e p t i o n */
public boolean C a r g a r T a b l e r o( String n o m b r e A r c h i v o) throws I O E x c e p t i o n {
// Abrimos archivo y r e v i s a m o s si existe
File archivo = new File ( n o m b r e A r c h i v o);
if ( archivo . exists ()) {
// Abrimos lectores
Scanner bLector = new Scanner ( archivo );

// O b t e n e m o s cantidad de bombas
n u m B o m b a s = bLector . nextInt ();

// O b t e n e m o s d i m e n s i o n del tablero y lo creamos


int tamano = bLector . nextInt ();
t a b l e r o B a r c o s = new int [ tamano ][ tamano ];

// Llenamos tablero
for ( int i = 0; i < tamano ; i ++) {
for ( int j = 0; j < tamano ; j ++) {
// O b t e n e m o s valor
int valor = bLector . nextInt ();

// G u a r d a m o s y pasamos a sgte
t a b l e r o B a r c o s[ i ][ j ] = valor ;

}
}

// Cerramos
bLector . close ();

// Creamos tablero jugador y llenamos vacio


t a b l e r o J u g a d o r = new int [ tamano ][ tamano ];
for ( int i = 0; i < tamano ; i ++) {
for ( int j = 0; j < tamano ; j ++) {
t a b l e r o J u g a d o r[ i ][ j ] = 0;
}
}

IIC1103 Captulo 8: Archivos 46


return true ;
} else {
return false ;
}
}

/* * Realiza un ataque
* @param x la posicion entre 1 y max en fila
* @param y la posicion entre 1 y max en columna
* @return si dio en un barco o no */
public boolean Atacar ( int x , int y ) {
// D i s m i n u y e el total de bombas
numBombas - -;

// Revisa si le dio a un barco o no


if ( t a b l e r o B a r c o s[ x - 1][ y - 1] == 1) {
// Marca como danado
t a b l e r o J u g a d o r[ x - 1][ y - 1] = 2;
return true ;
} else {
// Marca como al agua
t a b l e r o J u g a d o r[ x - 1][ y - 1] = 3;
return false ;
}
}

/* * Revisa si gano el juego


* @return true si gano , false si no */
public boolean R e v i s a r S i G a n o() {
// Revisa cada c a s i l l e r o del tablero de barco , r e v i s a n d o si hay un barco
// y si en el tablero del jugador , el jugador puso una bomba ;
// si en alguno no es asi , no ha ganado
for ( int i = 0; i < t a b l e r o B a r c o s. length ; i ++) {
for ( int j = 0; j < t a b l e r o B a r c o s. length ; j ++) {
if ( t a b l e r o B a r c o s[ i ][ j ] == 1 && t a b l e r o J u g a d o r[ i ][ j ] != 2) {
return false ;
}
}
}
return true ;
}
}

IIC1103 Captulo 8: Archivos 47


Problema 13: Buscaminas
Enunciado
Debe implementar un programa que simule un juego simplificado de buscaminas.

Se le pide implementar una clase, BuscaMinas, que simule un juego de buscaminas simplificado.

Ademas, existen dos clases mas que ya est


an implementadas: InterfazGrafica, que permite mostrar gr
afi-
camente el juego, y Principal, que contiene el main del programa.

BuscaMinas: Esta clase simular a un juego de buscaminas, en donde el computador tendr a un tablero
oculto con minas o bombas instaladas en algunos casilleros. El jugador deber a marcar las posiciones que
cree con minas, y puede mostrar el contenido de las posiciones donde cree que no hay minas. Al mostrar un
lugar, si es una mina, el jugador pierde el juego; si no lo es, se muestra un n
umero que indica cu
antas minas
hay en la vecindad. El jugador gana si al terminar de marcar tantos casilleros como minas haba, marc o las
minas reales, y no se equivoco marcando casilleros sin minas. Si no, pierde. NOTA: Como simplificaci on del
juego real, no se puede desmarcar un casillero una vez marcado y al mostrar el contenido de un casillero
sin minas adyacentes, solamente se muestra ese casillero, a diferencia del juego real, donde automaticamente
muestra todos los casilleros sin minas adyacentes.

Esta clase debe tener los siguientes atributos:

Una matriz para almacenar el tablero con las minas. Tendr


a los siguientes valores posibles para cada
casillero:
1: mina
0: sin mina
Una matriz para almacenar el tablero que ve el jugador. Tendr
a los siguientes valores posibles para
cada casillero:
1: desconocido
2: marcado como minado
3: descubierto
Un entero para almacenar la cantidad minas totales.
Un entero para almacenar la cantidad de minas marcadas.
Un objeto de tipo InterfazGrafica para mostrar los tableros.

Adem
as, esta clase debe tener los siguientes metodos:

public BuscaMinas(): El constructor crea un nuevo BuscaMinas, inicializando su atributo interno de


tipo InterfazGrafica, y poniendo en cero los contadores.
public boolean CargarTablero(String nombreArchivo) throws IOException: metodo encarga-
do de leer un archivo con la informaci
on del juego, y cargarlo en el objeto BuscaMinas. En particular,
debe abrir el archivo indicado por nombreArchivo, y retornar false si no existe. Si existe, debe leerlo y
obtener la informacion del tamano del tablero y minas en el tablero, y cargarlos en la matriz interna.
Tambien debe contar la cantidad de minas en el tablero, y almacenarla. El formato de un archivo v alido
es el siguiente:

IIC1103 Captulo 8: Archivos 48


3
0 1 1
0 0 0
1 1 0

En donde cada lnea indica lo siguiente:


La primera lnea contiene un entero, que indica la cantidad de filas y columnas del tablero (es un
tablero cuadrado).
Las lneas siguientes corresponden a las filas del tablero. Cada lnea contiene un entero para cada
una de las columnas del tablero, separados por un espacio. Los valores posibles son 0, si no hay
nada en ese lugar, o 1, si hay una mina en ese lugar del tablero.
Este metodo debe adem as inicializar el tablero del jugador con todos los valores en -1 (que indica que
estan tapados), y retornar true si pudo hacer todo lo indicado.
public void MarcarMina(int x, int y): metodo que marca el lugar indicado por x e y como minado
en el tablero del jugador. El entero para indicar marcado en la matriz es el -2. Los par ametros x
e y tienen valores entre 1 y el tama no m aximo de fila o columna respectivamente (recuerde que la
primera posicion en un arreglo o matriz es la 0). NO DEBE MODIFICAR EL TABLERO DE MINAS.
Solamente debe marcar la posici on indicada como marcado si no se haba mostrado el contenido
de ese casillero (es decir, si estaba todava tapado). Adem as, este metodo debe aumentar el contador
interno de la clase que indica cu antas minas se han marcado, si se marc o un lugar como minado.
public boolean MostrarContenido(int x, int y): metodo que revela el contenido del casillero in-
dicado por x e y. Los parametros x e y tienen valores entre 1 y el tama no maximo de fila o columna
respectivamente (recuerde que la primera posicion en un arreglo o matriz es la 0). El entero para in-
dicar un casillero como mostrado es el -3 (no es necesario preocuparse aqu por contar las casillas
vecinas con minas). NO DEBE MODIFICAR EL TABLERO DE MINAS. Adem as, debe revisar si en
el tablero de minas haba una mina en el lugar destapado; si no haba, retorna true; si haba, retorna
false.
public boolean RevisarSiGano(): metodo que revisa si el jugador marc o correctamente todas las
minas. Debe revisar los tableros, y si marc
o todos los lugares donde haba minas, retorna true; si falta
marcar alguna mina, retorna false.

public void IniciarJuego() throws IOException: el metodo principal del juego, debe tener un
ciclo constante en el que obtiene la opci
on del usuario a traves del objeto de InterfazGrafica (mos-
trando el tablero al mismo tiempo), y realiza la acci
on indicada por el usuario (mas abajo se definir
an
los metodos de la clase InterfazGrafica). Las acciones son las siguientes, dependiendo del entero que
se reciba:
(1) Marcar mina: usa el objeto InterfazGrafica para obtener las coordenadas de fila y colum-
na en donde marcar como minado, y usa la funci on interna de esta clase MarcarMina() para
marcar ese lugar. Si se han marcado tantas minas como total de minas haba, usa la funci on
interna de esta clase, RevisarSiGano(); si retorna true, muestra el mensaje Encontraste todas
las minas! Ganaste!, si no, muestra el mensaje Terminaste de marcar, y marcaste una o m as
minas equivocadamente. Perdiste!. En ambos casos muestra el tablero con minas, y termina el
programa.
(2) Mostrar contenido: usa el objeto InterfazGrafica para obtener las coordenadas de fila y co-
lumna en donde marcar como minado, y usa la funci on interna de esta clase MostrarContenido()
para destapar ese lugar. Si al destapar se retorn
o false (encontr
o una mina), muestra el mensaje
Explotaste! Perdiste el juego., muestra el tablero con minas y termina el programa.

IIC1103 Captulo 8: Archivos 49


(3) Ver minas (trampa!): usa el objeto InterfazGrafica para mostrar las posiciones de las minas
para revisar consistencia del juego.
en el tablero. Util
(4) Salir: termina el programa.

La clase InterfazGrafica ya est a creada, por lo que usted NO DEBE IMPLEMENTARLA. Tiene los
siguientes metodos que usted puede utilizar:

public int mostrarEstadoJugador(int[][] tableroJugador, int[][] tableroMinas, int minasFaltantes):


muestra gr aficamente el tablero del jugador y cu antas minas ha marcado. Adem as, indica al usuario
un men u de opciones. Recibe como par ametros el tablero del jugador, el de minas y el total de minas
que faltan por marcar. Retorna 1 si quiere marcar, 2 si quiere mostrar, 3 para ver las minas, y 4 para
salir. La interfaz gr
afica muestra smbolos en el tablero; la leyenda es la siguiente:
? = casillero tapado
x = casillero marcado como minado
Un numero = la cantidad de casilleros vecinos con bombas (de los a lo m
as 8 vecinos). NOTA:
esto es calculado automaticamente por la interfaz gr
afica.
public void mostrarTableroMinas(int[][] tablero): muestra gr aficamente el tablero con las mi-
nas solamente. Recibe como par
ametro el tablero de minas. Muestra un 1 donde hay mina, y un 0
donde no hay.
public int[] getCoordenadas(int tamanoMax): pide al usuario un par de coordenadas. Recibe co-
mo par ametro el tama no de filas o columnas del tablero, y pide dos enteros al usuario, validando que
esten entre 1 y ese valor de tama no. Retorna un arreglo de enteros con los dos valores ingresados por
el usuario.

La clase Principal, que contiene el main del programa, ya est a creada, por lo que NO DEBE IMPLEMEN-
TARLA. A modo de explicaci on, se indican las acciones realizadas:

Crea un objeto BuscaMinas.


Pide al usuario el nombre del archivo a usar (por defecto viene con el nombre test.txt).
Carga el archivo.
Inicia el juego

A continuaci
on se muestran las dos clases ya implementadas

import i i c 1 1 0 3 P a c k a g e .*;

/* * Clase que sirve como interfaz grafica simple del juego B u s c a M i n a s */


public class I n t e r f a z G r a f i c a {
/* * Muestra el estado de un jugador y un menu de opciones
* @param t a b l e r o J u g a d o r el tablero del jugador
* @param t a b l e r o M i n a s el tablero con las minas
* @param m i n a s F a l t a n t e s la cantidad de bombas f a l t a n t e s por marcar
* @return */
public int m o s t r a r E s t a d o J u g a d o r( int [][] tableroJugador ,
int [][] tableroMinas , int m i n a s F a l t a n t e s) {
// Arma el mensaje a mostrar
String mensaje = " " ;
mensaje += g e t S t r i n g T a b l e r o( tableroJugador , t a b l e r o M i n a s);
mensaje += " \ nFalta marcar " + m i n a s F a l t a n t e s + " minas .\ n " ;
mensaje += " \ nElija una opcion :\ n (1) Marcar mina \ n (2) Mostrar c o n t e n i d o\ n (3) " +
" Ver minas ( trampa !)\ n (4) Salir \ n " ;
// Obtiene la opcion del usuario , m o s t r a n d o l e todo
int opcion = Usuario . entero ( mensaje );
return opcion ;

IIC1103 Captulo 8: Archivos 50


}

/* * Funcion que muestra en pantalla el tablero con las minas


* @param tablero el tablero */
public void m o s t r a r T a b l e r o M i n a s( int [][] tablero ) {
String mensaje = " Tablero con las minas : " ;
mensaje += g e t S t r i n g T a b l e r o( tablero , tablero );
Usuario . mensaje ( mensaje );
}

/* * Pide al usuario las coordenadas , y retorna un arreglo con ellas


* @return */
public int [] g e t C o o r d e n a d a s( int t a m a n o M a x) {
int [] c o o r d e n a d a s = new int [2];
do {
c o o r d e n a d a s[0] = Usuario . entero ( " Ingrese la c o o r d e n a d a x " +
" ( entre 1 y el tamanio de una fila ): " );
} while ( c o o r d e n a d a s [0] < 1 || c o o r d e n a d a s [0] > t a m a n o M a x);
do {
c o o r d e n a d a s[1] = Usuario . entero ( " Ingrese la c o o r d e n a d a y " +
" ( entre 1 el tamanio de una columna ): " );
} while ( c o o r d e n a d a s [1] < 1 || c o o r d e n a d a s [1] > t a m a n o M a x);
return c o o r d e n a d a s;
}

/* * Arma un string con el tablero y lo retorna


* @param tablero el tablero a mostrar ( puede ser el de jugador o el de minas )
* @param t a b l e r o M i n a s el tablero con las minas
* @return un string con el tablero r e p r e s e n t a d o */
private String g e t S t r i n g T a b l e r o( int [][] tablero , int [][] t a b l e r o M i n a s) {
// Ponemos borde superior
String t a b l e r o M o s t r a d o = " \ n " ;
for ( int i = 0; i < tablero . length * 4 - 5; i ++) {
t a b l e r o M o s t r a d o += " _ " ;
}
t a b l e r o M o s t r a d o += " \ n " ;

// Ciclo para todas las filas


for ( int i = 0; i < tablero . length ; i ++) {
// Armamos fila
t a b l e r o M o s t r a d o += " | " ;
for ( int j = 0; j < tablero . length ; j ++) {
switch ( tablero [ i ][ j ]) {
case -1: // Caso lugar oculto ( para tablero de jugador )
t a b l e r o M o s t r a d o += " ?";
break ;
case -2: // Caso marcado como mina ( para tablero de jugador )
t a b l e r o M o s t r a d o += " x";
break ;
case -3: // Caso marcado como d e s t a p a d o ( para tablero de jugador )
t a b l e r o M o s t r a d o += " "
+ c a l c u l a r M i n a s V e c i n a s(i , j , t a b l e r o M i n a s);
break ;
case 0: // Caso no hay mina ( para tablero de minas )
t a b l e r o M o s t r a d o += " 0";
break ;
case 1: // Caso si hay mina ( para tablero de minas )
t a b l e r o M o s t r a d o += " 1";
break ;
}
}
t a b l e r o M o s t r a d o += " |\ n " ;
}

// Ponemos borde inferior


for ( int i = 0; i < tablero . length * 4 - 5; i ++) {
t a b l e r o M o s t r a d o += " _ " ;
}
t a b l e r o M o s t r a d o += " \ n " ;
return t a b l e r o M o s t r a d o;
}

/* * Calcula la cantidad de minas en la v e n c i n d a d


* @param x la posicion en fila
* @param y la posicion en columna
* @param t a b l e r o M i n a s el tablero con las minas
* @return la cantidad de minas en la vecindad */

IIC1103 Captulo 8: Archivos 51


private int c a l c u l a r M i n a s V e c i n a s( int x , int y , int [][] t a b l e r o M i n a s) {
// Busca en los 8 vecinos
int m i n a s V e c i n a s = 0;
if ( x > 0) {
if ( t a b l e r o M i n a s[ x - 1][ y ] == 1) {
m i n a s V e c i n a s ++;
}
}
if ( y > 0) {
if ( t a b l e r o M i n a s[ x ][ y - 1] == 1) {
m i n a s V e c i n a s ++;
}
}
if ( x < t a b l e r o M i n a s. length - 1) {
if ( t a b l e r o M i n a s[ x + 1][ y ] == 1) {
m i n a s V e c i n a s ++;
}
}
if ( y < t a b l e r o M i n a s. length - 1) {
if ( t a b l e r o M i n a s[ x ][ y + 1] == 1) {
m i n a s V e c i n a s ++;
}
}
if ( x > 0 && y > 0) {
if ( t a b l e r o M i n a s[ x - 1][ y - 1] == 1) {
m i n a s V e c i n a s ++;
}
}
if ( x > 0 && y < t a b l e r o M i n a s. length - 1) {
if ( t a b l e r o M i n a s[ x - 1][ y + 1] == 1) {
m i n a s V e c i n a s ++;
}
}
if ( x < t a b l e r o M i n a s. length - 1 && y > 0) {
if ( t a b l e r o M i n a s[ x + 1][ y - 1] == 1) {
m i n a s V e c i n a s ++;
}
}
if ( x < t a b l e r o M i n a s. length - 1 && y < t a b l e r o M i n a s. length - 1) {
if ( t a b l e r o M i n a s[ x + 1][ y + 1] == 1) {
m i n a s V e c i n a s ++;
}
}
return m i n a s V e c i n a s;
}
}

import i i c 1 1 0 3 P a c k a g e .*;
import java . io .*;

public class P r i n c i p a l {

public static void main ( String [] args ) throws I O E x c e p t i o n {


// Crea el objeto del juego
B u s c a M i n a s juego = new B u s c a M i n a s();

// Cargamos archivo con tablero


String n o m b r e A r c h i v o = Usuario . texto ( " Ingrese el nombre del archivo " , " test . txt " );
if ( juego . C a r g a r T a b l e r o( n o m b r e A r c h i v o) == false ) {
Usuario . mensaje ( " Error leyendo archivo " );
return ;
}
// Comienza el juego
juego . I n i c i a r J u e g o ();
}
}

Criterios de soluci
on
Posible soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
import java . io .*;
import java . util . Scanner ;

IIC1103 Captulo 8: Archivos 52


public class B u s c a M i n a s {
private int [][] t a b l e r o M i n a s;
private int [][] t a b l e r o J u g a d o r;
private I n t e r f a z G r a f i c a GUI ;
private int m i n a s D e t e c t a d a s;
private int m i n a s T o t a l e s;

/* * C o n s t r u c t o r */
public B u s c a M i n a s() {
GUI = new I n t e r f a z G r a f i c a ();
m i n a s D e t e c t a d a s = 0;
m i n a s T o t a l e s = 0;
}

/* * Lee un archivo con i n f o r m a c i o n del tablero y lo carga en las v a r i a b l e s


* internas
* @param n o m b r e A r c h i v o el nombre del archivo a leer
* @return true si pudo leer el archivo , false si no
* @throws I O E x c e p t i o n */
public boolean C a r g a r T a b l e r o( String n o m b r e A r c h i v o) throws I O E x c e p t i o n {
// Abrimos archivo y r e v i s a m o s si existe
File archivo = new File ( n o m b r e A r c h i v o);
if ( archivo . exists ()) {
// Abrimos lectores
Scanner bLector = new Scanner ( archivo );

// O b t e n e m o s d i m e n s i o n del tablero y lo creamos


int tamano = bLector . nextInt ();
t a b l e r o M i n a s = new int [ tamano ][ tamano ];

// Llenamos tablero
for ( int i = 0; i < tamano ; i ++) {
for ( int j = 0; j < tamano ; j ++) {
// O b t e n e m o s valor y a u m e n t a m o s la cantidad de minas que vienen
int valor = bLector . nextInt ();
if ( valor == 1) {
m i n a s T o t a l e s ++;
}
// G u a r d a m o s y pasamos a sgte
t a b l e r o M i n a s[ i ][ j ] = valor ;

}
}

// Cerramos
bLector . close ();

// Creamos tablero jugador y llenamos con todo oculto


t a b l e r o J u g a d o r = new int [ tamano ][ tamano ];
for ( int i = 0; i < tamano ; i ++) {
for ( int j = 0; j < tamano ; j ++) {
t a b l e r o J u g a d o r[ i ][ j ] = -1;
}
}
return true ;
} else {
return false ;
}
}

/* * Marca un lugar como minado


* @param x la posicion entre 1 y max en fila
* @param y la posicion entre 1 y max en columna */
public void M a r c a r M i n a( int x , int y ) {
// Aumenta las minas detectadas , y marca el lugar
if ( t a b l e r o J u g a d o r[ x - 1][ y - 1] == -1) {
// Revisa si esta en estado d e s c o n o c i d o
m i n a s D e t e c t a d a s ++;
t a b l e r o J u g a d o r[ x - 1][ y - 1] = -2; // -2 lo marca como minado
}
}

/* * Muestra lo que hay en un lugar


* @param x la posicion entre 1 y max en fila
* @param y la posicion entre 1 y max en columna
* @return true si era un lugar seguro , false si era mina */

IIC1103 Captulo 8: Archivos 53


public boolean M o s t r a r C o n t e n i d o( int x , int y ) {
// Marca el lugar
t a b l e r o J u g a d o r[ x - 1][ y - 1] = -3; // -3 lo marca como d e s c u b i e r t o

// Revisa si no hay mina , ok ; si hay mina , explota y retorna false


if ( t a b l e r o M i n a s[ x - 1][ y - 1] == 0) {
return true ;
} else {
return false ;
}
}

/* * Revisa si gano el juego


* @return true si gano , false si no */
public boolean R e v i s a r S i G a n o() {
// Revisa cada casillero , y si hay una mina no marcada , retorna false
for ( int i = 0; i < t a b l e r o M i n a s. length ; i ++) {
for ( int j = 0; j < t a b l e r o M i n a s. length ; j ++) {
if ( t a b l e r o M i n a s[ i ][ j ] == 1 && t a b l e r o J u g a d o r[ i ][ j ] != -2) {
return false ;
}
}
}
// Si todas las minas estaban marcadas , y todas las marcas estaban en
// las minas , avisa
return true ;
}

/* * Funcion p r i n c i p a l del juego


* @throws I O E x c e p t i o n */
public void I n i c i a r J u e g o() throws I O E x c e p t i o n {
// Ciclo p r i n c i p a l
boolean salir = false ;
while (! salir ) {
// M o s t r a m o s tablero , o b t e n e m o s opcion y r e v i s a m o s
int opcion = GUI . m o s t r a r E s t a d o J u g a d o r( tableroJugador , tableroMinas ,
m i n a s T o t a l e s - m i n a s D e t e c t a d a s);
int [] c o o r d e n a d a s;
switch ( opcion ) {
case 1:
// O b t e n e m o s c o o r d e n a d a s y marcamos
c o o r d e n a d a s = GUI . g e t C o o r d e n a d a s( t a b l e r o J u g a d o r. length );
M a r c a r M i n a( c o o r d e n a d a s[0] , c o o r d e n a d a s [1]);

// Revisa si gano o perdio , si ya marco todas


if ( m i n a s D e t e c t a d a s == m i n a s T o t a l e s) {
if ( R e v i s a r S i G a n o ()) {
Usuario . mensaje ( " E n c o n t r a s t e todas las minas ! Ganaste ! " );
} else {
Usuario . mensaje ( " T e r m i n a s t e de marcar , y marcaste una o mas minas e q u i v o c a d a m e n t e. Perdiste " );
}
GUI . m o s t r a r T a b l e r o M i n a s( t a b l e r o M i n a s);
return ;
}
break ;
case 2:
// O b t e n e m o s c o o r d e n a d a s y d e s t a p a m o s
c o o r d e n a d a s = GUI . g e t C o o r d e n a d a s( t a b l e r o J u g a d o r. length );
if ( M o s t r a r C o n t e n i d o( c o o r d e n a d a s[0] , c o o r d e n a d a s [1]) == false ) {
Usuario . mensaje ( " E x p l o t a s t e! Perdiste el juego . " );
GUI . m o s t r a r T a b l e r o M i n a s( t a b l e r o M i n a s);
return ;
}
break ;
case 3:
GUI . m o s t r a r T a b l e r o M i n a s( t a b l e r o M i n a s);
break ;
case 4:
salir = true ;
break ;
}
}
}
}

IIC1103 Captulo 8: Archivos 54


Problema 14: Mastermind
Enunciado
Debe implementar un programa que simule un juego simplificado de Mastermind (o Toque y Fama).

Se le pide implementar una clase, MasterMind, que simule un juego de mastermind simplificado.

Ademas, existir
an dos clases m
as que ya est
a implementadas: InterfazGrafica, que permite mostrar gr
afi-
camente el juego, y Principal, que contiene el main del programa.

MasterMind: Esta clase simular a un juego de MasterMind, en donde el computador tendr a un codigo
compuesto por una serie ordenada de n umeros, no conocidos por el jugador. El jugador deber a intentar
adivinar la serie de n
umeros oculta por el computador. En cada intento, el programa indicar a cu
antos nume-
ros acerto en el lugar correcto (fama), y cu antos numeros acerto pero en el lugar equivocado (toque).
Por ejemplo, si el codigo oculto es 2 3 4 5, y el jugador ingresa 2 4 3 1, se le indicar a que tuvo un
valor correcto en el lugar correcto (el 2), y 2 valores correctos pero en lugares equivocados (el 3 y el 4). Sin
embargo, NO se le indica que n umeros son los correctos, solamente la cantidad de aciertos. El juego termina
cuando el jugador acierta al codigo, o cuando se acaba el tablero sin que haya adivinado.

NOTA: Como simplificaci on del juego real, no se pueden repetir los numeros dentro del c
odigo; es decir,
no sera valido 2 2 3 4 (pues tiene el 2 repetido), pero s 2 1 5 4.

Esta clase debe tener los siguientes atributos:

Un arreglo para almacenar el c


odigo.
Una matriz para almacenar el tablero de juego que ve el jugador.
Una matriz de ancho 2 para almacenar las ayudas (toques y famas) que se le van dando al jugador
Un entero para almacenar la cantidad de intentos que lleva el jugador.

Un entero para almacenar el n umero m


aximo v
alido para el c
odigo (los n
umeros del c
odigo estar
an
siempre entre 1 y este valor).
Un objeto de tipo InterfazGrafica para mostrar los tableros.

Adem
as, esta clase debe tener los siguientes metodos

public MasterMind(): El constructor crea un nuevo MasterMind, inicializando su atributo interno de


tipo InterfazGrafica, y poniendo en cero los atributos enteros.
public boolean CargarTablero(String nombreArchivo) throws IOException: metodo encarga-
do de leer un archivo con la informacion del juego, y cargarlo en el objeto MasterMind. En particular,
debe abrir el archivo indicado por nombreArchivo, y retornar false si no existe. Si existe, debe leerlo
y obtener la informacion del numero m aximo, tama no del c
odigo, cantidad de intentos posibles, y el
codigo, y almacenarlos en los atributos de la clase. El formato de un archivo v
alido es el siguiente:

6
10
4
2 4 3 6

En donde cada lnea indica lo siguiente:

IIC1103 Captulo 8: Archivos 55


La primera lnea contiene un entero, que es el n
umero m aximo para los valores en el c
odigo (es
decir, cada n
umero en el codigo puede estar entre 1 y este m
aximo).
La segunda lnea contiene un entero, con la cantidad de intentos que puede hacer el jugador (es
decir, la cantidad de filas de ambas matrices).
La tercera lnea contiene un entero con el largo del c
odigo (es decir, la cantidad de columnas del
tablero).
La cuarta lnea contiene el c
odigo oculto, con una serie de enteros separados por un espacio. Los
valores posibles van entre 1 y el maximo indicado en la primera lnea.
Este metodo debe adem as crear e inicializar el tablero de juego con todos los valores en 0 (que indica
que no han sido usados), crear e inicializar el tablero de ayudas (que siempre tendr a 2 columnas, y
tantas filas como indique la segunda lnea) con todos los valores en 0, y retornar true si pudo hacer
todo lo indicado.
public boolean Adivinar(int[] intento): metodo que recibe el intento de adivinar el c odigo del
jugador, lo registra y lo revisa, y avisa si adivino o no. En particular, recibe un arreglo con la serie de
n
umeros que el jugador cree que es el c odigo. Este metodo debe pasar ese arreglo al tablero de juego
en la lnea que corresponda, y luego debe revisar cada valor, compar andolo con el codigo. Debe contar
cuantos toques logr o el usuario, y almacenar la cantidad en la primera columna de la matriz que
almacena las ayudas, en la fila actual; y debe almacenar la cantidad de famas en la segunda columna
de la matriz que almacena las ayudas, en la fila actual. Finalmente, debe revisar si el intento es igual
al c
odigo, y si es as, retorna true; si no, retorna false.
public void IniciarJuego() throws IOException: el metodo principal del juego, debe tener un
ciclo constante en el que obtiene la opci
on del usuario a traves del objeto de InterfazGrafica (mos-
trando el tablero al mismo tiempo), y realiza la acci
on indicada por el usuario (mas abajo se definir
an
los metodos de la clase InterfazGrafica). Las acciones son las siguientes, dependiendo del entero que
se reciba:
(1) Intentar adivinar: usa el objeto InterfazGrafica para obtener la serie de n umeros que ingresa
el usuario como intento, y usa la funci
on interna de esta clase Adivinar() para revisar si adivin oo
no. Si adivin
o, muestra el mensaje Adivinaste! Ganaste el juego., si no, revisa si se le acabaron la
cantidad de intentos posibles; de ser as, muestra el mensaje Se te acabaron los intentos! Perdiste
el juego.. En ambos casos, luego muestra el c odigo, y termina el programa. Si le quedan intentos
posibles, solamente sigue el programa.
(2) Ver codigo (trampa!): usa el objeto InterfazGrafica para mostrar el c para
odigo oculto. Util
revisar consistencia del juego.
(3) Salir: termina el programa.

La clase InterfazGrafica ya est a creada, por lo que usted NO DEBE IMPLEMENTARLA. Tiene los
siguientes metodos que usted puede utilizar:

public int mostrarEstadoJugador(int[][] tableroJuego, int[][] tableroAyudas, int intentosFaltantes)


muestra graficamente el tablero del jugador y la cantidad de toques y famas, indicando cuantos inten-
tos le quedan. Adem as, indica al usuario un menu de opciones. Recibe como par ametros el tablero de
juego, el de ayudas (toques y famas) y el total intentos que quedan disponibles. Retorna 1 si quiere
adivinar, 2 para ver el codigo, y 3 para salir. La interfaz gr
afica muestra smbolos en el tablero; la
leyenda es la siguiente:
o = casillero vaco, a
un no usado
Un n
umero = el n
umero ingresado por el usuario como partes del c
odigo.
T = bajo esta columna, muestra los toques

IIC1103 Captulo 8: Archivos 56


F = bajo esta columna, muestra las famas
public void mostrarCodigo(int[] codigo): muestra el c
odigo. Recibe como par
ametro el c
odigo.
public int[] obtenerIntento(int rangoMax, int cantNumeros): pide al usuario tantos enteros
como haya en el c odigo. Recibe como par ametro el rangoMax, revisando que lo que ingrese el usuario
este entre 1 y ese valor, y la cantidad de n
umeros a pedir (cantNumeros). Adem as, revisa que el usuario
no entregue dos veces un mismo n umero. Retorna un arreglo con los n
umeros ingresados por el usuario.

La clase Principal, que contiene el main del programa, viene ya creada, por lo que NO DEBE IMPLE-
MENTARLA. A modo de explicaci on, se indican las acciones realizadas:

Crea un objeto MasterMind.


Pide al usuario el nombre del archivo a usar (por defecto viene con el nombre test.txt).
Carga el archivo.
Inicia el juego

A continuaci
on se muestran las dos clases ya implementadas.

import i i c 1 1 0 3 P a c k a g e .*;

/* * Clase que sirve como interfaz grafica simple del juego M a s t e r M i n d */


public class I n t e r f a z G r a f i c a {
/* * Muestra el estado de un jugador y un menu de opciones
* @param t a b l e r o J u e g o el tablero del jugador
* @param t a b l e r o A y u d a s el tablero con las ayudas
* @param i n t e n t o s F a l t a n t e s la cantidad de intentos que le quedan por hacer
* @return */
public int m o s t r a r E s t a d o J u g a d o r( int [][] tableroJuego ,
int [][] tableroAyudas , int i n t e n t o s F a l t a n t e s) {
// Arma el mensaje a mostrar
String mensaje = " " ;
mensaje += g e t S t r i n g T a b l e r o( tableroJuego , t a b l e r o A y u d a s);
mensaje += " \ nQuedan " + i n t e n t o s F a l t a n t e s + " intentos .\ n " ;
mensaje += " \ nElija una opcion :\ n (1) Intentar adivinar \ n (2) Ver codigo ( trampa !)\ n (3) Salir \ n " ;

// Obtiene la opcion del usuario , m o s t r a n d o l e todo


int opcion = Usuario . entero ( mensaje );
return opcion ;
}

/* * Funcion que muestra en pantalla el codigo


* @param tablero el codigo */
public void m o s t r a r C o d i g o( int [] codigo ) {
String mensaje = " Codigo :\ n [ " ;
for ( int i = 0; i < codigo . length ; i ++) {
mensaje += codigo [ i ] + " " ;
}
mensaje += " ] " ;
Usuario . mensaje ( mensaje );
}

/* * Pide al usuario los numeros del codigo , y retorna un arreglo con ellos
* @param rangoMax el entero maximo que puede ingresar
* @param c a n t N u m e r o s la cantidad de numeros a pedir
* @return */
public int [] o b t e n e r I n t e n t o( int rangoMax , int c a n t N u m e r o s) {
int [] intento = new int [ c a n t N u m e r o s];
for ( int i = 0; i < c a n t N u m e r o s; i ++) {
int numero ;
do {
numero = Usuario . entero ( " Ingrese el numero " + ( i + 1)
+ " del codigo ( entre 1 y " + rangoMax
+ " , sin repetir ): " );
} while ( numero < 1 || numero > rangoMax || YaEsta ( numero , intento ));
intento [ i ] = numero ;

IIC1103 Captulo 8: Archivos 57


}
return intento ;
}

/* * Revisa si un numero ya esta en un arreglo


* @param num el numero a revisar
* @param intento el arreglo
* @return true si estaba , false si no */
public boolean YaEsta ( int num , int [] intento ) {
for ( int i = 0; i < intento . length ; i ++) {
if ( intento [ i ] == num ) {
return true ;
}
}
return false ;
}

/* * Arma un string con el tablero y lo retorna


* @param t a b l e r o J u e g o el tablero a mostrar ( el juego )
* @param t a b l e r o A y u d a s el tablero con las ayudas
* @return un string con el tablero r e p r e s e n t a d o */
private String g e t S t r i n g T a b l e r o( int [][] tableroJuego , int [][] t a b l e r o A y u d a s) {
// Ponemos borde superior
int l a r g o B o r d e = ( int ) t a b l e r o J u e g o [0]. length * 5 / 2 + 8;
String t a b l e r o M o s t r a d o = " \ n " ;
for ( int i = 0; i < l a r g o B o r d e; i ++) {
t a b l e r o M o s t r a d o += " _ " ;
}
t a b l e r o M o s t r a d o += " \ n " ;
for ( int i = 0; i < t a b l e r o J u e g o [0]. length * 5 + 10; i ++) {
t a b l e r o M o s t r a d o += " " ;
}
t a b l e r o M o s t r a d o += " T F\n";

// Ciclo para todas las filas


for ( int i = 0; i < t a b l e r o J u e g o. length ; i ++) {
// Armamos fila
t a b l e r o M o s t r a d o += " | " ;
for ( int j = 0; j < t a b l e r o J u e g o[ i ]. length ; j ++) {
switch ( t a b l e r o J u e g o[ i ][ j ]) {
case -1: // Caso vacio
t a b l e r o M o s t r a d o += " o";
break ;
default : // Caso normal
t a b l e r o M o s t r a d o += " " + t a b l e r o J u e g o[ i ][ j ];
break ;
}
}

// Armamos ayuda
t a b l e r o M o s t r a d o += " |";
for ( int j = 0; j < t a b l e r o A y u d a s[ i ]. length ; j ++) {
switch ( t a b l e r o A y u d a s[ i ][ j ]) {
case -1:
t a b l e r o M o s t r a d o += " o";
break ;
default : // Caso buen numero y buen lugar
t a b l e r o M o s t r a d o += " " + t a b l e r o A y u d a s[ i ][ j ];
break ;
}
}
t a b l e r o M o s t r a d o += " |\ n " ;
}

// Ponemos borde inferior


for ( int i = 0; i < l a r g o B o r d e; i ++) {
t a b l e r o M o s t r a d o += " _ " ;
}
t a b l e r o M o s t r a d o += " \ n " ;

return t a b l e r o M o s t r a d o;
}
}

import i i c 1 1 0 3 P a c k a g e .*;
import java . io .*;

IIC1103 Captulo 8: Archivos 58


public class P r i n c i p a l {

public static void main ( String [] args ) throws I O E x c e p t i o n {


// Crea el objeto del juego
M a s t e r M i n d juego = new M a s t e r M i n d();
// Cargamos archivo con tablero
String n o m b r e A r c h i v o = Usuario . texto ( " Ingrese el nombre del archivo " , " test . txt " );
if ( juego . C a r g a r T a b l e r o( n o m b r e A r c h i v o) == false ) {
Usuario . mensaje ( " Error leyendo archivo " );
return ;
}
// Comienza el juego
juego . I n i c i a r J u e g o ();
}
}

Criterios de soluci
on
Posible soluci
on
import i i c 1 1 0 3 P a c k a g e .*;

import java . io .*;


import java . util . Scanner ;

public class M a s t e r M i n d {
private int [] codigo ;
private int [][] t a b l e r o J u e g o;
private int [][] t a b l e r o A y u d a s;
private I n t e r f a z G r a f i c a GUI ;
private int n u m I n t e n t o s;
private int rangoMax ;

/* * C o n s t r u c t o r */
public M a s t e r M i n d() {
GUI = new I n t e r f a z G r a f i c a ();
n u m I n t e n t o s = 0;
rangoMax = 0;
}

/* * Lee un archivo con i n f o r m a c i o n del tablero y lo carga en las v a r i a b l e s


* internas
* @param n o m b r e A r c h i v o el nombre del archivo a leer
* @return true si pudo leer el archivo , false si no
* @throws I O E x c e p t i o n */
public boolean C a r g a r T a b l e r o( String n o m b r e A r c h i v o) throws I O E x c e p t i o n {
// Abrimos archivo y r e v i s a m o s si existe
File archivo = new File ( n o m b r e A r c h i v o);
if ( archivo . exists ()) {
// Abrimos lectores
Scanner bLector = new Scanner ( archivo );

// O b t e n e m o s el numero maximo del rango de codigo a usar ( numeros


// estaran entre 1 y rangoMax )
rangoMax = bLector . nextInt ();

// O b t e n e m o s el ancho y alto del tablero


int alto = bLector . nextInt ();
int ancho = bLector . nextInt ();

// Creamos tablero , i n i c i a l i z a d o en -1
t a b l e r o J u e g o = new int [ alto ][ ancho ];
for ( int i = 0; i < alto ; i ++) {
for ( int j = 0; j < ancho ; j ++) {
t a b l e r o J u e g o[ i ][ j ] = -1;
}
}

// Creamos tablero de ayudas , i n i c i a l i z a d o en -1


t a b l e r o A y u d a s = new int [ alto ][2];
for ( int i = 0; i < alto ; i ++) {
for ( int j = 0; j < 2; j ++) {
t a b l e r o A y u d a s[ i ][ j ] = -1;
}

IIC1103 Captulo 8: Archivos 59


}

// Creamos codigo
codigo = new int [ ancho ];

// Leemos codigo
for ( int j = 0; j < ancho ; j ++) {
// O b t e n e m o s valor , g u a r d a m o s y pasamos a sgte
int valor = bLector . nextInt ();
codigo [ j ] = valor ;

// Cerramos
bLector . close ();

return true ;
} else {
return false ;
}
}

/* * Intenta adivinar el codigo


* @param intento un arreglo con el intento de adivinar el codigo
* @return si gano o todavia no */
public boolean Adivinar ( int [] intento ) {
// O b t e n e m o s intento del jugador y lo ponemos en el tablero
for ( int i = 0; i < t a b l e r o J u e g o[ n u m I n t e n t o s]. length ; i ++) {
t a b l e r o J u e g o[ n u m I n t e n t o s][ i ] = intento [ i ];
}

// R e v i s a m o s el intento y armamos las ayudas


t a b l e r o A y u d a s[ n u m I n t e n t o s][0] = 0;
t a b l e r o A y u d a s[ n u m I n t e n t o s][1] = 0;
for ( int i = 0; i < codigo . length ; i ++) {
// R e v i s a m o s si esta el numero correcto en el lugar correcto
if ( codigo [ i ] == t a b l e r o J u e g o[ n u m I n t e n t o s][ i ]) {
t a b l e r o A y u d a s[ n u m I n t e n t o s ][1]++;
// Le achunto al numero , y en el lugar adecuado
} else {
// Si no esta en el lugar correcto , buscamos si al menos esta en
// otro lugar
for ( int j = 0; j < t a b l e r o J u e g o[ n u m I n t e n t o s]. length ; j ++) {
if (( i != j ) && ( t a b l e r o J u e g o[ n u m I n t e n t o s][ i ] == codigo [ j ])) {
t a b l e r o A y u d a s[ n u m I n t e n t o s ][0]++;
// Le achunto al numero , pero no en el lugar adecuado
}
}
}
}

// R e v i s a m o s si gano
boolean gano = false ;
if ( t a b l e r o A y u d a s[ n u m I n t e n t o s ][1] == codigo . length ) {
gano = true ;
}
// A v a n z a m o s y r e t o r n a m o s
n u m I n t e n t o s++;
return gano ;
}

/* * Funcion p r i n c i p a l del juego


* @throws I O E x c e p t i o n */
public void I n i c i a r J u e g o() throws I O E x c e p t i o n {
// Ciclo p r i n c i p a l
boolean salir = false ;
while (! salir ) {
// M o s t r a m o s tablero , o b t e n e m o s opcion y r e v i s a m o s
int opcion = GUI . m o s t r a r E s t a d o J u g a d o r( tableroJuego , tableroAyudas ,
t a b l e r o J u e g o. length - n u m I n t e n t o s);
switch ( opcion ) {
case 1:
// O b t e n e m o s c o o r d e n a d a s y marcamos
int [] intento = GUI . o b t e n e r I n t e n t o( rangoMax ,
t a b l e r o J u e g o [0]. length );
boolean gano = Adivinar ( intento );

IIC1103 Captulo 8: Archivos 60


// Revisa si gano o perdio , si ya marco todas
if ( gano ) {
Usuario . mensaje ( " A d i v i n a s t e! Ganaste el juego . " );
GUI . m o s t r a r C o d i g o( codigo );
return ;
} else if ( n u m I n t e n t o s == t a b l e r o J u e g o. length ) {
Usuario . mensaje ( " Se te acabaron los intentos ! Perdiste el juego . " );
GUI . m o s t r a r C o d i g o( codigo );
return ;
}
break ;
case 2:
GUI . m o s t r a r C o d i g o( codigo );
break ;
case 3:
salir = true ;
break ;
}
}
}
}

IIC1103 Captulo 8: Archivos 61


Problema 15: Laberinto
Enunciado
Debe implementar un programa que simule un juego simplificado de Laberinto.

Se le pide implementar u nicamente la clase Laberinto que simula un juego de laberinto simplificado.
Adem as, existir
an dos clases ya implementadas: InterfazGrafica, que permite mostrar gr
aficamente el
juego, y Principal, que contiene el main del programa.

Laberinto: Esta clase simula un juego de Laberinto cuya estructura no sera conocida por el jugador. El
jugador conocer a el punto de inicio y el de fin del laberinto, y deber a intentar avanzar en distintas direcciones
para llegar al final. A medida que avanza, se le ir a mostrando la estructura del laberinto. El jugador tiene
una cantidad limitada de turnos, por lo que ganar a si llega al final antes de que se le acaben los turnos, o
perdera si se le acaban los turnos sin haber llegado al final.

Esta clase debe tener los siguientes atributos:

Tablero de juego: Es una matriz que almacena el estado del laberinto mientras se juega. Cada casillero
en la matriz tendr
a los siguientes valores posibles:
-1 = casillero oculto, jugador no sabe su contenido
-2 = casillero descubierto, se mostrar
a el contenido del laberinto en ese lugar
-3 = casillero donde est
a el jugador
Tablero del laberinto: Es una matriz que almacena la estructura del laberinto. Cada casillero en la
matriz tendr
a los siguientes valores posibles:
0 = existe un camino despejado
1= existe una muralla
2 = la entrada del laberinto
3 = la salida del laberinto
Un entero para almacenar la cantidad m
axima de turnos disponibles para el jugador.
Un entero para almacenar la cantidad de turnos ya usados por el jugador.
Un entero para almacenar la fila actual donde est
a el jugador en cada momento.
Un entero para almacenar la columna actual donde est
a el jugador en cada momento.
Un objeto de tipo InterfazGrafica para mostrar los tableros.

Adem
as, esta clase debe tener los siguientes metodos:

public Laberinto(): El constructor crea un nuevo Laberinto, inicializando el atributo de tipo InterfazGrafica
y poniendo en cero los atributos enteros.
public boolean CargarTablero(String nombreArchivo) throws IOException: metodo que lee un
archivo con la informacion del juego y la estructura del laberinto. El nombre del archivo a abrir se
recibe como parametro en nombreArchivo. Debe retornar false si el archivo no existe y si existe, debe
leerlo y almacenar los valores ledos en los atributos correspondientes de la clase: cantidad de turnos,
tama no del tablero, y matriz con la estructura del laberinto. El siguiente es el formato del archivo:

IIC1103 Captulo 8: Archivos 62


12
5
1 1 0 1 1
2 0 0 0 1
1 1 0 1 1
1 0 0 0 3
1 1 1 1 1

Cada lnea contiene lo siguiente:


Primera lnea: contiene un entero, que es la cantidad de turnos disponibles para el usuario (es
decir, si no llega al final en esta cantidad de acciones o menos, pierde).
Segunda lnea: contiene un entero, con el tama
no del laberinto (es decir, la cantidad de filas y
columnas, es una matriz cuadrada)
Siguientes lneas: contienen la estructura del laberinto. Cada lnea tiene una serie de enteros sepa-
rados por un espacio. Los valores posibles fueron indicados previamente (0 = camino despejado,
1= muralla, 2 = entrada y 3 = salida).
Este metodo debe adem as crear e inicializar el tablero de juego con todos los valores en -1 (ocultos),
marcar la entrada del laberinto en el tablero de juego con -3 (para indicar que el jugador empieza el
juego en la entrada del laberinto), y marcar la salida con -2 (para indicar que sea mostrada al comenzar
el juego). Adem as, debe almacenar en los atributos internos la columna y fila inicial del jugador.
public boolean Avanzar(int direccion): metodo que recibe una direccion de avance, e intenta
avanzar en esa direcci on. Siempre recibir a una direccion v
alida, pues esto se valida antes. V alida
quiere decir que no trata de salirse de los bordes del laberinto; por ejemplo, si est a en la primera
fila, nunca recibir
a como direccion arriba. Los valores posibles de la direccion son: 1 = arriba, 2 =
derecha, 3 = abajo, 4 = izquierda. Este metodo debe calcular la nueva posici on segun la direccion y
la posicion actual, y marcar como descubierta esa nueva posici on (marcando con -2 en la matriz
del tablero de juego). Adem as, y solamente si esa nueva posici on no es una muralla en la matriz del
laberinto, debe mover el jugador a esa posici on, actualizando su posicion actual, y marc andolo en el
tablero de juego (y dejando la antigua posici on del jugador visible). Por u
ltimo, debe revisar si llego al
final del laberinto, y retornar true si lo hizo, false si no.
public void IniciarJuego() throws IOException: el metodo principal del juego debe tener un
ciclo constante en el que se obtiene la opci
on del usuario a traves del objeto de InterfazGrafica (que
adem as muestra el tablero al mismo tiempo), y realiza la accion indicada por el usuario. Las opciones
son las siguientes:
(1) Avanzar: obtiene la direccion del usuario desde el objeto InterfazGrafica, usa el metodo
Avanzar() de esta clase (Laberinto) para realizar el movimiento, y revisar si lleg o al final o no.
Si lleg
o, muestra el mensaje Llegaste al final! Ganaste el juego.; si no, revisa si se le acabaron
la cantidad de turnos posibles; de ser as, muestra el mensaje Se te acabaron los turnos! Perdiste
el juego.. En ambos casos, luego muestra el laberinto completo, y termina el programa. Si le
quedan turnos posibles, solamente sigue el programa.
(2) Ver laberinto (trampa!): usa el objeto InterfazGrafica para mostrar el laberinto completo.
para revisar consistencia del juego.
Util
(3) Salir: termina el programa.

InterfazGrafica: Ya esta creada por lo que usted NO DEBE IMPLEMENTARLA. Tiene los siguientes
metodos que usted puede utilizar:

IIC1103 Captulo 8: Archivos 63


public int mostrarEstadoJugador(int[][] tableroJugador, int[][] laberinto, int turnosFaltantes):
muestra graficamente el tablero del juego, indicando cu antos turnos le quedan al jugador. Adem as, in-
dica al usuario un men u de opciones. Recibe como par ametros el tablero de juego, la matriz con
el laberinto y el total de turnos que quedan disponibles. Retorna 1 si quiere avanzar, 2 para ver el
laberinto, y 3 para salir. La interfaz gr
afica muestra smbolos en el tablero; la leyenda es la siguiente:
? = casillero oculto
J = la posici
on del jugador
E = la entrada del laberinto
S = la salida del laberinto
0 = camino despejado
1 = muralla
public void mostrarLaberinto(int[][] tablero): muestra el laberinto, usando la misma leyenda
gr
afica que el metodo anterior (aunque sin mostrar el jugador ni nada oculto). Recibe como par
ametro
la matriz con el laberinto.
public int obtenerDireccion(int posFila, int posCol, int[][] laberinto): pide al usuario
una direccion v
alida. Recibe como par ametro la posici
on (fila y columna) actual del usuario, y la matriz
con el laberinto. Los valores posibles de ingreso son: 1 = arriba, 2 = derecha, 3 = abajo, 4 = izquierda.
Valida que la direccion indicada no lleve al jugador fuera de la matriz; de ser as, sigue pidiendo hasta
que se ingrese una direccion v
alida.

La clase Principal, que contiene el main del programa, viene creada por lo que NO DEBE IMPLEMEN-
TARLA. A modo de explicaci on, se indican las acciones realizadas:

Crea un objeto Laberinto.


Pide al usuario el nombre del archivo a usar (por defecto viene con el nombre test.txt).
Carga el archivo.
Inicia el juego

A continuaci
on se muestran las dos clases implementadas:

import i i c 1 1 0 3 P a c k a g e .*;

/* * Clase que sirve como interfaz grafica simple del juego B u s c a M i n a s */


public class I n t e r f a z G r a f i c a {
/* * Muestra el estado de un jugador y un menu de opciones
* @param t a b l e r o J u g a d o r el tablero del jugador
* @param l a b e r i n t o el l a b e r i n t o
* @param m i n a s F a l t a n t e s la cantidad de bombas f a l t a n t e s por marcar
* @return */
public int m o s t r a r E s t a d o J u g a d o r( int [][] tableroJugador , int [][] laberinto ,
int t u r n o s F a l t a n t e s) {
// Arma el mensaje a mostrar
String mensaje = " " ;
mensaje += g e t S t r i n g T a b l e r o( tableroJugador , l a b e r i n t o);
mensaje += " \ nQuedan " + t u r n o s F a l t a n t e s + " turnos .\ n " ;
mensaje += " \ nElija una opcion :\ n (1) Mover \ n (2) Ver l a b e r i n t o ( trampa !)\ n (3) Salir \ n " ;

// Obtiene la opcion del usuario , m o s t r a n d o l e todo


int opcion = Usuario . entero ( mensaje );
return opcion ;
}

/* * Funcion que muestra en pantalla el l a b e r i n t o mismo


* @param tablero el tablero */
public void m o s t r a r L a b e r i n t o( int [][] tablero ) {

IIC1103 Captulo 8: Archivos 64


String mensaje = " L a b e r i n t o: " ;
mensaje += g e t S t r i n g T a b l e r o( tablero , tablero );
Usuario . mensaje ( mensaje );
}

/* * Pide al usuario una d i r e c c i o n valida


* @param posFila el lugar en que esta ( fila )
* @param posCol el lugar en que esta ( columna )
* @param l a b e r i n t o la matriz con el l a b e r i n t o
* @return un entero con una d i r e c c i o n (1 , 2 , 3 o 4) */
public int o b t e n e r D i r e c c i o n( int posFila , int posCol , int [][] l a b e r i n t o) {
int d i r e c c i o n;
do {
d i r e c c i o n = Usuario . entero ( " Ingrese una d i r e c c i o n valida (1 arriba , 2 derecha , " +
" 3 abajo , 4 i z q u i e r d a): " );
} while (! E s D i r e c c i o n V a l i d a( direccion , posFila , posCol , l a b e r i n t o));
return d i r e c c i o n;
}

/* * Revisa si se sale del borde del l a b e r i n t o por la direcion dada


* @param d i r e c c i o n la d i r e c c i o n dada ( entre 1 y 4)
* @param posFila el lugar en que esta ( fila )
* @param posCol el lugar en que esta ( columna )
* @param l a b e r i n t o la matriz con el l a b e r i n t o
* @return true si es valida , false si no */
private boolean E s D i r e c c i o n V a l i d a( int direccion , int posFila , int posCol ,
int [][] l a b e r i n t o) {
if ( d i r e c c i o n < 1 || d i r e c c i o n > 4) {
return false ;
}
switch ( d i r e c c i o n) {
case 1:
if ( posFila == 0) {
return false ;
}
break ;
case 2:
if ( posCol == l a b e r i n t o. length - 1) {
return false ;
}
break ;
case 3:
if ( posFila == l a b e r i n t o. length - 1) {
return false ;
}
break ;
case 4:
if ( posCol == 0) {
return false ;
}
break ;
}
return true ;
}

/* * Arma un string con el tablero y lo retorna


* @param tablero el tablero a mostrar ( puede ser el de jugador o el l a b e r i n t o)
* @param t a b l e r o L a b e r i n t o el tablero con las minas
* @return un string con el tablero r e p r e s e n t a d o */
private String g e t S t r i n g T a b l e r o( int [][] tableroJugador ,
int [][] t a b l e r o L a b e r i n t o) {
// Ponemos borde superior
int l a r g o B o r d e = ( int ) t a b l e r o J u g a d o r. length * 5 / 2 + 2;
String t a b l e r o M o s t r a d o = " \ n " ;
for ( int i = 0; i < l a r g o B o r d e; i ++) {
t a b l e r o M o s t r a d o += " _ " ;
}
t a b l e r o M o s t r a d o += " \ n " ;

// Ciclo para todas las filas


for ( int i = 0; i < t a b l e r o J u g a d o r. length ; i ++) {
// Armamos fila
t a b l e r o M o s t r a d o += " | " ;
for ( int j = 0; j < t a b l e r o J u g a d o r. length ; j ++) {
t a b l e r o M o s t r a d o += " "
+ g e t C a r a c t e r(i , j , tableroJugador , t a b l e r o L a b e r i n t o);
}

IIC1103 Captulo 8: Archivos 65


t a b l e r o M o s t r a d o += " |\ n " ;
}

// Ponemos borde inferior


for ( int i = 0; i < l a r g o B o r d e; i ++) {
t a b l e r o M o s t r a d o += " _ " ;
}
t a b l e r o M o s t r a d o += " \ n " ;

return t a b l e r o M o s t r a d o;
}

/* * Retorna el caracter indicado para mostrar g r a f i c a m e n t e


* @param i la fila
* @param j la columna
* @param tablero la matriz a mostrar
* @param t a b l e r o L a b e r i n t o el l a b e r i n t o
* @return */
private String g e t C a r a c t e r( int i , int j , int [][] tableroJuego ,
int [][] t a b l e r o L a b e r i n t o) {
switch ( t a b l e r o J u e g o[ i ][ j ]) {
case -1: // Caso oculto
return " ? " ;
case -2: // Caso d e s c u b i e r t o ( muestra lo que haya en el l a b e r i n t o)
return " " + g e t C a r a c t e r(i , j , tableroLaberinto , t a b l e r o L a b e r i n t o );
case -3: // Caso jugador
return " J " ;
case 2: // Caso inicio
return " E " ;
case 3: // Caso fin
return " S " ;
default : // Caso normal
return " " + t a b l e r o J u e g o[ i ][ j ];
}
}
}

import i i c 1 1 0 3 P a c k a g e .*;
import java . io .*;

public class P r i n c i p a l {

public static void main ( String [] args ) throws I O E x c e p t i o n {


// Crea el objeto del juego
L a b e r i n t o juego = new L a b e r i n t o();

// Cargamos archivo con tablero


String n o m b r e A r c h i v o = Usuario . texto ( " Ingrese el nombre del archivo " , " test . txt " );
if ( juego . C a r g a r T a b l e r o( n o m b r e A r c h i v o) == false ) {
Usuario . mensaje ( " Error leyendo archivo " );
return ;
}
// Comienza el juego
juego . I n i c i a r J u e g o ();
}
}

Criterios de soluci
on
Posible soluci
on
import i i c 1 1 0 3 P a c k a g e .*;

import java . io .*;


import java . util . Scanner ;

public class L a b e r i n t o {
private int [][] t a b l e r o J u g a d o r;
private int [][] t a b l e r o L a b e r i n t o;
private I n t e r f a z G r a f i c a GUI ;
private int t u r n o s D i s p o n i b l e s;
private int posFila ;
private int posCol ;

IIC1103 Captulo 8: Archivos 66


/* * C o n s t r u c t o r */
public L a b e r i n t o() {
GUI = new I n t e r f a z G r a f i c a ();
t u r n o s D i s p o n i b l e s = 0;
}

/* * Lee un archivo con i n f o r m a c i o n del tablero y lo carga en las v a r i a b l e s


* internas
* @param n o m b r e A r c h i v o el nombre del archivo a leer
* @return true si pudo leer el archivo , false si no
* @throws I O E x c e p t i o n */
public boolean C a r g a r T a b l e r o( String n o m b r e A r c h i v o) throws I O E x c e p t i o n {
// Abrimos archivo y r e v i s a m o s si existe
File archivo = new File ( n o m b r e A r c h i v o);
if ( archivo . exists ()) {
// Abrimos lectores
Scanner bLector = new Scanner ( archivo );

// O b t e n e m o s cantidad de turnos
t u r n o s D i s p o n i b l e s = bLector . nextInt ();

// O b t e n e m o s d i m e n s i o n del tablero y lo creamos


int tamano = bLector . nextInt ();
t a b l e r o L a b e r i n t o = new int [ tamano ][ tamano ];

// Creamos tablero jugador y llenamos con todo oculto ( -1)


t a b l e r o J u g a d o r = new int [ tamano ][ tamano ];
for ( int i = 0; i < tamano ; i ++) {
for ( int j = 0; j < tamano ; j ++) {
t a b l e r o J u g a d o r[ i ][ j ] = -1;
}
}

// Llenamos tablero
for ( int i = 0; i < tamano ; i ++) {
for ( int j = 0; j < tamano ; j ++) {
// O b t e n e m o s valor
int valor = bLector . nextInt ();
t a b l e r o L a b e r i n t o[ i ][ j ] = valor ;

// Vemos si e n c o n t r a m o s inicio
if ( valor == 2) {
posFila = i ;
posCol = j ;
t a b l e r o J u g a d o r[ posFila ][ posCol ] = -3;
} else if ( valor == 3) {
t a b l e r o J u g a d o r[ i ][ j ] = -2; // Dejamos salida d e s c u b i e r t a
}
}
}

bLector . close ();

return true ;
} else {
return false ;
}
}

/* * Avanza en una d i r e c c i o n dada


* @param d i r e c c i o n la direcion (1 arriba , 2 derecha , 3 abajo , 4 i z q u i e r d a)
* @return si encontro el final o no */
public boolean Mover ( int d i r e c c i o n) {
// A v a n z a m o s en la d i r e c c i o n indicada
t u r n o s D i s p on ibl es - -;
int n u e v a P o s F i l a = posFila ;
int n u e v a P o s C o l = posCol ;
switch ( d i r e c c i o n) {
case 1: // Arriba
nuevaPosFila - -;
break ;
case 2: // Derecha
n u e v a P o s C o l++;
break ;
case 3: // Abajo
n u e v a P o s F i l a ++;
break ;

IIC1103 Captulo 8: Archivos 67


case 4: // I z q u i e r d a
nuevaPosCol - -;
break ;
}
t a b l e r o J u g a d o r[ n u e v a P o s F i l a][ n u e v a P o s C o l] = -2; // Indica que se muestre

// A v a n z a m o s solo si no es muralla
if ( t a b l e r o L a b e r i n t o[ n u e v a P o s F i l a][ n u e v a P o s C o l] != 1) {
t a b l e r o J u g a d o r[ posFila ][ posCol ] = -2; // Lo deja como d e s c u b i e r t o
posFila = n u e v a P o s F i l a;
posCol = n u e v a P o s C o l;
t a b l e r o J u g a d o r[ n u e v a P o s F i l a][ n u e v a P o s C o l] = -3; // Indica el jugador
}

// Revisa si llego al final


if ( t a b l e r o L a b e r i n t o[ n u e v a P o s F i l a][ n u e v a P o s C o l] == 3) {
return true ;
} else {
return false ;
}
}

/* * Funcion p r i n c i p a l del juego


* @throws I O E x c e p t i o n */
public void I n i c i a r J u e g o() throws I O E x c e p t i o n {
// Ciclo p r i n c i p a l
boolean salir = false ;
while (! salir ) {
// M o s t r a m o s tablero , o b t e n e m o s opcion y r e v i s a m o s
int opcion = GUI . m o s t r a r E s t a d o J u g a d o r( tableroJugador ,
tableroLaberinto , t u r n o s D i s p o n i b l e s);
switch ( opcion ) {
case 1:
// O b t e n e m o s c o o r d e n a d a s y marcamos
int d i r e c c i o n = GUI . o b t e n e r D i r e c c i o n( posFila , posCol ,
t a b l e r o L a b e r i n t o );
boolean gano = Mover ( d i r e c c i o n);

// Revisa si gano o perdio , si ya marco todas


if ( gano ) {
Usuario . mensaje ( " Llegaste al final ! Ganaste el juego . " );
GUI . m o s t r a r L a b e r i n t o( t a b l e r o L a b e r i n t o);
return ;
} else if ( t u r n o s D i s p o n i b l e s == 0) {
Usuario . mensaje ( " Se te acabaron los turnos ! Perdiste el juego . " );
GUI . m o s t r a r L a b e r i n t o( t a b l e r o L a b e r i n t o);
return ;
}
break ;
case 2:
GUI . m o s t r a r L a b e r i n t o( t a b l e r o L a b e r i n t o);
break ;
case 3:
salir = true ;
break ;
}
}
}
}

IIC1103 Captulo 8: Archivos 68


Problema 16: Editor de texto
Enunciado
Debe implementar un programa que consista en un editor de texto.

Se le pide implementar un programa que pueda servir como un editor de texto. Debe ser capaz de abrir
un archivo existente, hacer diversas modificaciones, y guardar el archivo. En particular, se le pide implemen-
tar la clase EditorTexto, que se encargara de organizar la edici
on, y el metodo main de la clase Principal.
Adem as, tendr
a a su disposici
on dos clases ya creadas: InterfazUsuario, para las funcionalidades m as co-
munes de interacci on con el usuario, y Documento, con informaci on y operaciones de un documento.

El formato de los archivos utilizados ser


a el siguiente:

En la primera lnea esta la fecha de u


ltima vez que se almacen
o; no es parte del contenido.
En el resto de las lneas esta el contenido.

Clase Documento: la siguiente clase ya viene definida e implementada, por lo que usted NO DEBE IM-
PLEMENTARLA. Esta clase encapsula la informaci on necesaria sobre documento en edicion. A continuaci
on
se describen sus metodos p
ublicos para que usted pueda utilizarlos:

public Documento(String nuevoNombre, String nuevaFechaAct): constructor de la clase, recibe


una serie de par
ametros y los almacena internamente (adem
as de dejar el cursor al inicio del documen-
to):
nuevoNombre: el nombre del archivo en edici
on.
nuevaFechaAct: la u
ltima fecha de edici
on del archivo.
public void cargarTexto(String nuevoTexto): permite almacenar el contenido de un documento
indicado por nuevoTexto en el objeto.
public String getNombre(): retorna el nombre del archivo correspondiente al documento.
public String getFecha(): retorna la fecha de u
ltimo almacenamiento del documento.
public int getCursor(): retorna la posici on del cursor en el documento, entre 0 (antes de todas las
letras) hasta el largo del documento (despues de la u
ltima letra).
public void moverCursor(int cuanto): mueve el cursor la cantidad de espacios indicados. El par ame-
tro cuanto puede ser positivo o negativo; si es negativo, el cursor retrocede. No puede moverse antes
del inicio del documento ni mas all
a del fin.
public void insertarTexto(String nuevoTexto): inserta el String indicado por nuevoTexto en
la posicion del cursor, moviendo lo que haba en ese lugar a la derecha.
public void eliminarTexto(int numCaracteres): elimina a lo mas la cantidad de caracteres dada
por numCaracteres hacia atr
as del lugar actual del cursor.

Clase InterfazUsuario: la siguiente clase ya viene definida e implementada, por lo que usted NO DEBE
IMPLEMENTARLA. Esta clase tiene metodos para pedir y mostrar la informaci on necesaria al usuario. A
continuacion se describen sus metodos p
ublicos para que usted pueda utilizarlos:

public int ContenidoYMenu(String contenidoArchivo): muestra el contenido del documento abier-


to, seguido por un men
u con opciones al usuario, y retorna la opci
on elegida. No realiza ninguna acci
on
asociada; solamente retorna el n
umero de la opcion indicada por el usuario. Las opciones que presenta
son (retornando el n
umero en parentesis):

IIC1103 Captulo 8: Archivos 69


(1) Elegir archivo a abrir
(2) Mover cursor
(3) Insertar texto
(4) Eliminar texto
(5) Juntar con otro archivo
(6) Guardar archivo
(7) Salir
public String ElegirDocumentoAbrir(String[] lista): recibe una lista de Strings con nombres
de archivos, la muestra al usuario, y le permite elegir el n
umero del archivo mostrado de esa lista,
retornando el nombre de ese archivo.
public int ObtenerMovimientoCursor(): pide un n umero distinto de cero al usuario para mover esa
cantidad positiva o negativa el cursor, y lo retorna.
public String ObtenerPalabra(): pide una palabra v
alida al usuario para insertar, y la retorna.
public int ObtenerCantidadEliminar(): pide un n
umero positivo al usuario para eliminar esa can-
tidad de caracteres, y la retorna.
public String GetFechaActual(): retorna un String con la fecha actual en formato yyyy/MM/dd
HH:mm:ss (ejemplo: 2007/06/01 18:04:00).

Clase EditorTexto: la siguiente clase debe ser implementada por usted. Esta clase es la encargada de
buscar una palabra en archivos, y formatear y exportar los resultados. Puede tener todos los atributos y
metodos privados que usted considere necesarios. Debe tener los siguientes metodos p
ublicos:

public String[] getListaDocumentos() throws IOException: Este metodo busca en la carpeta


de trabajo, todos los archivos con extensi on txt y cuyo nombre sea de la forma archivo seguido
de un n umero (ej: archivo1.txt, archivo20.txt). Sin embargo, basta que los busque secuencialmente; es
decir, debe buscar si esta archivo1.txt, luego archivo2.txt, etc, hasta que no encuentre el siguiente, y
no debe seguir buscando. Retorna un arreglo de strings con los nombres de los archivos secuenciales
que s existan.
public Documento abrirDocumento(String nombreDocumento) throws IOException: Este meto-
do debe recibir como par
ametro el nombre de un archivo, y debe crear un objeto de tipo Documento
con toda la informaci
on necesaria en base a abrir y leer ese archivo. Retorna el objeto Documento
creado.
public void guardarDocumento(Documento doc, String fecha) throws IOException: Este meto-
do debe recibir como par
ametro un objeto Documento y una fecha, y debe almacenar en disco ese mismo
Documento, dejando en la primera lnea la fecha indicada, y a continuaci
on su contenido.
public Documento juntarDocumentos(Documento doc1, Documento doc2): Este metodo debe reci-
bir como par
ametro dos Documentos, y retornar un documento con los contenidos de ambos documentos
pegados (el contenido del primero seguido del contenido del segundo), separados por un salto de lnea.
public String getTextoConCursor(Documento doc): retorna un String con el contenido de un do-
cumento, indicando con un gui
on el cursor en el lugar que le corresponde.

Clase Principal: el metodo main de esta clase debe ser implementado por usted. Debe consistir en el
funcionamiento principal del programa, que debe realizar las siguientes funciones:

Tener el ciclo principal para el men


u del programa.

IIC1103 Captulo 8: Archivos 70


Realizar cada una de las opciones que ingrese el usuario, utilizando las clases anteriormente definidas.
Para las opciones 2 a 6, debe antes revisar si no se ha abierto un documento; de ser as, debe indicarlo
con un mensaje, y no realizar la acci
on. En particular, dependiendo de la elecci
on, si eligi
o lo siguiente,
debe hacer lo indicado:
(1) Elegir archivo a abrir: muestra una lista de los archivos disponibles al usuario, y abre el
documento elegido; este queda como documento actual.
(2) Mover cursor: pide al usuario cu
anto moverlo, y mueve el cursor esa cantidad de espacios en
el documento actual.
(3) Insertar texto: pide al usuario un texto, y lo inserta en el documento actual.
(4) Eliminar texto: pide al usuario cu
antos caracteres eliminar, y los elimina del documento actual.
(5) Juntar con otro archivo: pide al usuario que elija de la lista un segundo documento, y lo
adjunta al documento actual, mostrando un mensaje de exito.
(6) Guardar archivo: guarda el documento actual a disco, y muestra un mensaje indicando que lo
guard
o.
(7) Salir: termina el programa.

A continuaci
on se muestra el c
odigo de las clases ya implementadas

public class D o c u m e n t o {
// A t r i b u t o s
private String nombre ;
private String fechaAct ;
private String texto ;
private int cursor ;

// C o n s t r u c t o r
public D o c u m e n t o( String nuevoNombre , String n u e v a F e c h a A c t) {
nombre = n u e v o N o m b r e;
fechaAct = n u e v a F e c h a A c t;
cursor = 0;
}

// Carga un texto en el d o c u m e n t o
public void c a r g a r T e x t o( String n u e v o T e x t o) {
texto = n u e v o T e x t o;
}

// Retorna el texto del d o c u m e n t o


public String g e t N o m b r e() {
return nombre ;
}

// Retorna el texto del d o c u m e n t o


public String getTexto () {
return texto ;
}

// Retorna la fecha
public String getFecha () {
return fechaAct ;
}

// Retorna el cursor
public int g e t C u r s o r() {
return cursor ;
}

// Mjueve el cursor una cierta cantidad de espacios indicada


public void m o v e r C u r s o r( int cuanto ) {
if ( cursor + cuanto > texto . length ()) {
cursor = texto . length ();
} else if ( cursor + cuanto < 0) {
cursor = 0;
} else {

IIC1103 Captulo 8: Archivos 71


cursor += cuanto ;
}
}

// Inserta el texto indicado en la posicion del cursor


public void i n s e r t a r T e x t o( String n u e v o T e x t o) {
texto = texto . s u b s t r i n g(0 , cursor ) + n u e v o T e x t o
+ texto . s u b s t r i n g( cursor , texto . length ());
cursor += n u e v o T e x t o. length ();
}

// Elimina la cantidad de c a r a c t e r e s i n d i c a d a s a partir del cursor


public void e l i m i n a r T e x t o( int n u m C a r a c t e r e s) {
int posFinal = cursor - n u m C a r a c t e r e s;
if ( posFinal < 0) {
posFinal = 0;
}
texto = texto . s u b s t r i n g(0 , posFinal )
+ texto . s u b s t r i n g( cursor , texto . length ());
cursor = posFinal ;
}
}

import i i c 1 1 0 3 P a c k a g e .*;
public class I n t e r f a z U s u a r i o {
/* * Muestra el d o c u m e n t o y un menu de opciones , y retorna la opcion elegida
* @param un string con el c o n t e n i d o del archivo , i n c l u y e n d o posicion del cursor
* @return un numero con la opcion elegida */
public int C o n t e n i d o Y M e n u( String c o n t e n i d o A r c h i v o) {
int opcion ;
do {
opcion = Usuario . entero (" Archivo :\ n \ n "
+ contenidoArchivo
+ " \ n \ nElija una opcion :\ n (1) Elegir archivo a abrir \ n (2) Mover cursor \ n " +
" (3) Insertar texto \ n (4) Eliminar texto \ n (5) Juntar con otro archivo \ n " +
" (6) Guardar archivo \ n (7) Salir " );
} while ( opcion < 1 || opcion > 73);
return opcion ;
}

/* * Pide un archivo al usuario para abrir


* @param lista una lista con nombres de archivos
* @return */
public String E l e g i r D o c u m e n t o A b r i r( String [] lista ) {
// Armamos mensaje
String mensaje = " Elija d o c u m e n t o de la lista ordenada por fecha :\ n " ;
for ( int i = 0; i < lista . length ; i ++) {
mensaje += " \ n " + ( i + 1) + " ) " + lista [ i ];
}
// Elegimos archivo
int opcion ;
do {
opcion = Usuario . entero ( mensaje + " \ n \ nElija el numero del archivo a abrir : " );
} while ( opcion < 1 && opcion > lista . length - 1);
return lista [ opcion - 1];
}

/* * Pide cantidad de espacios a mover cursor


* @return */
public int O b t e n e r M o v i m i e n t o C u r s o r() {
int cant ;
do {
cant = Usuario . entero ( " Indique cuantos espacios mover el cursor : " );
} while ( cant == 0);
return cant ;
}

/* * Pide la palabra a insertar


* @return */
public String O b t e n e r P a l a b r a() {
String palabra ;
do {
palabra = Usuario . texto (" Ingrese una palabra a insertar : " );
} while ( palabra == null || palabra == " " );
return palabra ;
}

IIC1103 Captulo 8: Archivos 72


/* * Obtiene la cantiad de c a r a c t e r e s a eliminar
* @return */
public int O b t e n e r C a n t i d a d E l i m i n a r() {
int cant ;
do {
cant = Usuario . entero ( " Ingrese la cantidad de c a r a c t e r e s a eliminar : " );
} while ( cant < 1);
return cant ;
}

/* * Retorna un String con la fecha actual


* @return un String con la fecha actual */
public String G e t F e c h a A c t u a l() {
return new java . text . S i m p l e D a t e F o r m a t( " yyyy / MM / dd HH : mm : ss " )
. format ( new java . util . Date ());
}
}

Criterios de soluci
on
Posible soluci
on

import java . io .*;


import java . util . Scanner ;

public class E d i t o r T e x t o {
/* * Arma un arreglo de strings con los nombres de los archivos e x i s t e n t e s
* @return un arreglo de strings con los nombres de archivos e x i s t e n t e s
* @throws I O E x c e p t i o n */
public String [] g e t L i s t a D o c u m e n t o s() throws I O E x c e p t i o n {
// Cuenta cuantos archivos hay
boolean fin = false ;
int i = 1;
int t o t a l A r c h i v o s = 0;
do {
// Abre archivo s i g u i e n t e y revisa
File a r c h i v o A c t u a l = new File ( " archivo " + i ++ + " . txt " );
if ( a r c h i v o A c t u a l. exists ()) {
t o t a l A r c h i v o s ++;
} else {
fin = true ;
}
} while (! fin );

// Arma arreglo
String [] docs = new String [ t o t a l A r c h i v o s];
for ( i = 0; i < t o t a l A r c h i v o s; i ++) {
docs [ i ] = " archivo " + ( i + 1) + " . txt " ;
}
return docs ;
}

/* * Abre un d o c u m e n t o y lo retorna ; si no existe , retorna null


* @param n o m b r e D o c u m e n t o el nombre del d o c u m e n t o a abrir
* @return un objeto D o c u m e n t o si existia , o null si no existia
* @throws I O E x c e p t i o n */
public D o c u m e n t o a b r i r D o c u m e n t o( String n o m b r e D o c u m e n t o) throws I O E x c e p t i o n {
// Abrimos archivo y r e v i s a m o s si existe
File archivo = new File ( n o m b r e D o c u m e n t o);
if ( archivo . exists ()) {
// Abrimos lectores
Scanner bLector = new Scanner ( archivo );

// Leemos fecha
String fecha = bLector . nextLine ();

// Leemos c o n t e n i d o
String texto = " " ;
while ( bLector . h a s N e x t L i n e()) {
texto += bLector . nextLine () + " \ n " ;
}
// Cerramos archivos
bLector . close ();

IIC1103 Captulo 8: Archivos 73


// Armamos r e s u l t a d o
D o c u m e n t o doc = new D o c u m e n t o( nombreDocumento , fecha );
doc . c a r g a r T e x t o( texto );
return doc ;
} else {
return null ;
}
}

/* * Guarda un d o c u m e n t o
* @param doc el d o c u m e n t o a guardar
* @throws I O E x c e p t i o n
*/
public void g u a r d a r D o c u m e n t o( D o c u m e n t o doc , String fecha )
throws I O E x c e p t i o n {
// Abrimos archivo a escribir
File archivo = new File ( doc . g e t N o m b r e ());
F i l e W r i t e r escritor = new F i l e W r i t e r( archivo );
P r i n t W r i t e r p E s c r i t o r = new P r i n t W r i t e r( escritor );

// Escribe fecha y texto


p E s c r i t o r. write ( fecha + " \ n " );
p E s c r i t o r. write ( doc . getTexto ());

p E s c r i t o r. close ();
escritor . close ();
}

/* * Agrega el c o n t e n i d o de un d o c u m e n t o a otro
* @param doc1 el d o c u m e n t o base
* @param doc2 el d o c u m e n t o agregado
* @return */
public D o c u m e n t o j u n t a r D o c u m e n t o s( D o c u m e n t o doc1 , D o c u m e n t o doc2 ) {
doc1 . c a r g a r T e x t o( doc1 . getTexto () + " \ n " + doc2 . getTexto ());
return doc1 ;
}

/* * Retorna un texto con cursor incluido


* @param doc el d o c u m e n t o
* @return un string con c o n t e n i d o y cursor */
public String g e t T e x t o C o n C u r s o r( D o c u m e n t o doc ) {
String texto = doc . getTexto ();
String t e x t o C o n C u r s o r = texto . s u b s t r i n g(0 , doc . g e t C u r s o r ()) + " _ "
+ texto . s u b s t r i n g( doc . g e t C u r s o r() , texto . length ());
return t e x t o C o n C u r s o r;
}
}

import i i c 1 1 0 3 P a c k a g e .*;
import java . io .*;

public class P r i n c i p a l {
// Main del programa
public static void main ( String [] args ) throws I O E x c e p t i o n {
// V a r i a b l e s internas
I n t e r f a z U s u a r i o GUI = new I n t e r f a z U s u a r i o ();
E d i t o r T e x t o editor = new E d i t o r T e x t o ();
String c o n t e n i d o = " No hay d o c u m e n t o abierto " ;
D o c u m e n t o d o c A c t u a l = null ;

// Ciclo p r i n c i p a l
boolean salir = false ;
while (! salir ) {
int opcion = GUI . C o n t e n i d o Y M e n u( c o n t e n i d o);
switch ( opcion ) {
case 1: // Elegir d o c u m e n t o para abrir
String [] lista = editor . g e t L i s t a D o c u m e n t o s ();
String a r c h i v o A b r i r = GUI . E l e g i r D o c u m e n t o A b r i r( lista );
d o c A c t u a l = editor . a b r i r D o c u m e n t o( a r c h i v o A b r i r);
Usuario . mensaje ( " D o c u m e n t o " + d o c A c t u a l. g e t N o m b r e()
+ " abierto . " );
break ;
case 2: // Mover cursor
if ( d o c A c t u a l != null )

IIC1103 Captulo 8: Archivos 74


d o c A c t u a l. m o v e r C u r s o r( GUI . O b t e n e r M o v i m i e n t o C u r s o r ());
else
Usuario . mensaje ( " No se ha cargado un d o c u m e n t o" );
break ;
case 3: // Insertar texto
if ( d o c A c t u a l != null ) {
String inserto = GUI . O b t e n e r P a l a b r a ();
d o c A c t u a l. i n s e r t a r T e x t o( inserto );
} else {
Usuario . mensaje ( " No se ha cargado un d o c u m e n t o" );
}
break ;
case 4: // Eliminar texto
if ( d o c A c t u a l != null ) {
int cant = GUI . O b t e n e r C a n t i d a d E l i m i n a r ();
d o c A c t u a l. e l i m i n a r T e x t o( cant );
} else {
Usuario . mensaje ( " No se ha cargado un d o c u m e n t o" );
}
break ;
case 5: // Juntar
if ( d o c A c t u a l != null ) {
String n o m b r e D o c 2 = GUI . E l e g i r D o c u m e n t o A b r i r( editor
. g e t L i s t a D o c u m e n t o s ());
D o c u m e n t o doc2 = editor . a b r i r D o c u m e n t o( n o m b r e D o c 2);
d o c A c t u a l = editor . j u n t a r D o c u m e n t o s( docActual , doc2 );
Usuario . mensaje ( " Archivos juntados . " );
} else {
Usuario . mensaje ( " No se ha cargado un d o c u m e n t o" );
}
break ;
case 6: // Guarda el d o c u m e n t o
if ( d o c A c t u a l != null ) {
editor . g u a r d a r D o c u m e n t o( docActual , GUI . G e t F e c h a A c t u a l ());
Usuario . mensaje ( " D o c u m e n t o a l m a c e n a d o" );
} else {
Usuario . mensaje ( " No se ha cargado un d o c u m e n t o" );
}
break ;
case 7:
salir = true ;
break ;
}

// Cargamos c o n t e n i d o a mostrar
if ( d o c A c t u a l != null ) {
c o n t e n i d o = editor . g e t T e x t o C o n C u r s o r( d o c A c t u a l);
}
}
}
}

IIC1103 Captulo 8: Archivos 75


Problema 17: Buscador de Palabras
Enunciado
Debe implementar un programa que consista en un buscador de palabras.

Se le pide implementar un programa que pueda buscar palabras dadas por el usuario en una serie de archivos
de texto plano, y retornar resultados ordenados, los que podr an ser exportados a un archivo. En particular,
se le pide implementar la clase Buscador, que se encargara de hacer la busqueda de la palabra, y el metodo
main de la clase Principal. Adem as, tendr
a a su disposici
on dos clases ya creadas: InterfazUsuario, para
las funcionalidades mas comunes de interaccion con el usuario, y Resultado, con informacion de resultados
de la busqueda.

Clase Resultado: la siguiente clase ya viene definida e implementada, por lo que usted NO DEBE IM-
PLEMENTARLA. Esta clase encapsula la informaci on necesaria sobre un resultado de una b
usqueda. A
continuacion se describen sus metodos p
ublicos para que usted pueda utilizarlos:

public Resultado(String archivo, int nVeces, String nuevoExtracto): constructor de la cla-


se, recibe una serie de par
ametros y los almacena internamente:
archivo: el nombre del archivo en que se busc
o la palabra.
nVeces: la cantidad de veces que se encontr
o la palabra en ese archivo
nuevoExtracto: un pedazo del archivo, que contiene una frase con a lo m as 15 caracteres antes
(contando desde el inicio de la palabra) y despues (contando del final de la palabra) del primer
lugar donde se encontr o la palabra, y la palabra misma. Por ejemplo, si se buscaba la palabra
todos en un archivo cuyo contenido es Hola a todos, como les va, saludos a todos, el extracto
sera Hola a todos, como les. Esto sirve para tener un contexto de donde se encontr
o la palabra.
public String getNombreArchivo(): retorna el nombre del archivo donde se busc
o.
public int getNumVeces(): retorna la cantidad de veces que se encontro la palabra.
public String getExtracto(): retorna el extracto con la palabra (ver definicion m
as arriba).

Clase InterfazUsuario: la siguiente clase ya viene definida e implementada, por lo que usted NO DEBE
IMPLEMENTARLA. Esta clase tiene metodos para pedir y mostrar la informaci on necesaria al usuario. A
continuacion se describen sus metodos p
ublicos para que usted pueda utilizarlos:

public int MenuOpciones(): muestra un men u con opciones al usuario, y retorna la opci
on elegida.
No realiza ninguna acci
on asociada; solamente retorna el n
umero de la opcion indicada por el usuario.
Las opciones que presenta son:
(1) Indicar archivos: para elegir en que archivos buscar; si es elegida, retorna 1.
(2) Buscar en archivos: para buscar una palabra en archivos; si es elegida, retorna 2.
(3) Salir: para terminar el programa; si es elegida, retorna 3.
public String[] ObtenerNombreArchivos(): pide al usuario indicar en cu antos archivos quiere bus-
car, y le pide el nombre de cada uno. Luego retorna un arreglo con todos esos nombres.
public String ObtenerPalabra(): pide una palabra v
alida al usuario para buscar, y la retorna.
public boolean MostrarYExportar(String resultados): recibe un string con los resultados for-
mateados y listos para mostrar, los muestra en pantalla, y pregunta si quiere exportarlos a archivo.
Retorna 1 si se quiere exportar, 2 si no.

IIC1103 Captulo 8: Archivos 76


Clase Buscador: la siguiente clase debe ser implementada por usted. Esta clase es la encargada de buscar
una palabra en archivos, y formatear y exportar los resultados. Puede tener todos los atributos y m
etodos
privados que usted considere necesarios. Debe tener los siguientes metodos p
ublicos:

public Resultado[] Buscar(String busqueda, String[] nombreArchivos) throws IOException:


Este metodo debe recibir como par ametro una palabra (busqueda) y un arreglo de archivos (nom-
breArchivos), y buscar secuencialmente en cada uno de los archivos del arreglo cuantas veces aparece
la palabra indicada. Por cada uno de los archivos en los que s se encontr
o la palabra debe crear un
objeto de tipo Resultado, y llenarlo con la informacion necesaria (ver definici
on de clase Resultado
para detalles). Para el caso del extracto, debe reemplazar todos los caracteres de salto de lnea que
contenga por espacios, para que al mostrarlo despues no haya problemas de despliegue. Finalmente,
debe retornar un arreglo con los resultados obtenidos (solamente para los archivos en los que s se
encontr
o la palabra; si no se encontr
o en ning
un archivo, no vendra ning
un resultado en el arreglo).
public Resultado[] OrdenarResultados(Resultado[] resultados): Este metodo debe recibir co-
mo parametro un arreglo de objetos de tipo Resultado, y ordenarlos de mayor a menor seg un la
cantidad de veces que se encontr
o la palabra en cada uno. Debe retorna un arreglo con los mismos
objetos ordenados.
public String FormatearResultados(Resultado[] resultados, String palabra): Este metodo
debe recibir como parametro un arreglo de objetos de tipo Resultado, y generar un String con la
informaci
on de los resultados para poder ser mostrada. El formato debe ser el siguiente, reemplazan-
do NombreArchivoN, palabra, la cantidad de veces y lo que est a en cada extracto por lo que
corresponda:

Resultados para b
usqueda de palabra:
1) NombreArchivo1 { 10 veces { extracto: ...blabla palabra bla...
2) NombreArchivo2 { 8 veces { extracto: ...blablo palabra ble...

public void ExportarResultados(Resultado[] resultados, String nombreArchivo) throws IOException:


Este metodo debe recibir como par
ametro un arreglo de objetos de tipo Resultado, y un String con el
nombre de un archivo. Debe tomar los resultados, y escribirlos en el formato especificado en el metodo
anterior en un archivo con el nombre indicado (si no existe el archivo, debe crearlo).

Clase Principal: el metodo main de esta clase debe ser implementado por usted. Debe consistir en el
funcionamiento principal del programa, que debe realizar las siguientes funciones:

Tener el ciclo principal para el men


u del programa.
Realizar cada una de las opciones que ingrese el usuario, utilizando las clases anteriormente definidas.
En particular, dependiendo de la elecci
on, si eligi
o lo siguiente, debe hacer lo indicado:
(1) Indicar archivos: obtener del usuario los nombres de los archivos de entradas, y almacenarlos
internamente.
(2) Buscar en archivos: primero debe revisar si ya se ingresaron los archivos de entrada; si no,
avisa con un mensaje que primero deben ingresarse, y no permite la b usqueda. Si ya se haban
ingresado, debe realizar la b
usqueda y mostrar los resultados ordenados en pantalla. Si el usuario
quiere exportar los resultados, debe pedirle el nombre del archivo de salida, exportarlos, y avisar
con un mensaje la finalizacion de la exportaci
on.
(3) Salir: para terminar el programa.

A continuaci
on se muestra el c
odigo de las clases ya implementadas:

IIC1103 Captulo 8: Archivos 77


public class R e s u l t a d o {
// A t r i b u t o s internos
private String n o m b r e A r c h i v o; // El archivo donde se encontro
private int numVeces ; // La cantidad de veces e n c o n t r a d a en este texto
private String extracto ; // Un extracto de un lugar donde se encontro

// C o n s t r u c t o r
public R e s u l t a d o( String archivo , int nVeces , String n u e v o E x t r a c t o) {
n o m b r e A r c h i v o = archivo ;
numVeces = nVeces ;
extracto = n u e v o E x t r a c t o;
}

// Retorna el nombre del archivo


public String g e t N o m b r e A r c h i v o() {
return n o m b r e A r c h i v o;
}

// Retorna la cantidad de veces e n c o n t r a d o el r e s u l t a d o


public int g e t N u m V e c e s() {
return numVeces ;
}

// Retorna el extracto
public String g e t E x t r a c t o() {
return extracto ;
}

import i i c 1 1 0 3 P a c k a g e .*;
public class I n t e r f a z U s u a r i o {
/* * Muestra un menu de opciones , y retorna la opcion elegida
* @return un numero con la opcion elegida */
public int M e n u O p c i o n e s() {
int opcion ;
do {
opcion = Usuario . entero (" Elija una opcion :\ n (1) Indicar archivos \ n " +
" (2) Buscar en archivos \ n (3) Salir " );
} while ( opcion < 1 || opcion > 3);
return opcion ;
}

/* * @return un arreglo con los nombres de los archivos */


public String [] O b t e n e r N o m b r e A r c h i v o s() {
// Pide la cantidad de archivos a ingresar
int c a n t A r c h i v o s;
do {
c a n t A r c h i v o s = Usuario . entero ( " Ingrese cuantos archivos va a usar : " );
} while ( c a n t A r c h i v o s < 1);

// O b t e n e m o s nombres de los archivos


String [] archivos = new String [ c a n t A r c h i v o s];
for ( int i = 0; i < c a n t A r c h i v o s; i ++) {
do {
archivos [ i ] = Usuario . texto ( " Ingrese el nombre del archivo " + ( i + 1)+ " : " );
} while ( archivos [ i ] == null || archivos [ i ]. equals ( " " ));
}

return archivos ;
}

/* * Pide la palabra a buscar


* @return */
public String O b t e n e r P a l a b r a() {
String palabra ;
do {
palabra = Usuario . texto (" Ingrese una palabra a buscar : " );
} while ( palabra == null || palabra . equals ( " " ));
return palabra ;
}

/* * Muestra los resultados , y pregunta si quiere exportar


* @param r e s u l t a d o s un String con los r e s u l t a d o s ya f o r m a t e a d o s
* @return true si quiere exportarlos , false si no */

IIC1103 Captulo 8: Archivos 78


public boolean M o s t r a r Y E x p o r t a r( String r e s u l t a d o s) {
int opcion ;
do {
opcion = Usuario . entero ( r e s u l t a d o s + " \ n \ nDesea exportar los r e s u l t a d o s? " +
" (1 para exportar , 2 para no exportar ): " );
} while ( opcion < 1 || opcion > 2);

if ( opcion == 1) {
return true ;
} else {
return false ;
}
}
}

Criterios de soluci
on
Posible soluci
on

import java . io .*;


import java . util . Scanner ;

public class Buscador {


// La palabra buscada
private String p a l a b r a B u s c a d a;

/* * Busca una palabra en m u l t i p l e s archivos , y retorna un arreglo con r e s u l t a d o s


* @param busqueda la palabra a buscar
* @param n o m b r e A r c h i v o s los archivos donde buscar
* @return un arreglo con los r e s u l t a d o s */
public R e s u l t a d o[] Buscar ( String busqueda , String [] n o m b r e A r c h i v o s)
throws I O E x c e p t i o n {
// Ciclo para todos los archivos
p a l a b r a B u s c a d a = busqueda ;
R e s u l t a d o[] r e s u l t a d o s = new R e s u l t a d o[ n o m b r e A r c h i v o s. length ];
int p o s A c t u a l = 0;
for ( int i = 0; i < n o m b r e A r c h i v o s. length ; i ++) {
// Abrimos archivo y r e v i s a m o s si existe
File archivo = new File ( n o m b r e A r c h i v o s[ i ]);
if ( archivo . exists ()) {
// Abrimos lectores
Scanner bLector = new Scanner ( archivo );

// Leemos c o n t e n i d o

String texto = " " ;


while ( bLector . h a s N e x t L i n e()) {
texto += bLector . nextLine () + " \ n " ;
}
// Cerramos archivos
bLector . close ();

// Busca la palabra
int numVeces = B u s c a r C a n t i d a d( busqueda , texto );
String extracto = " " ;
int t a m a n o E x t r a c t o = 15;
if ( numVeces > 0) {
// Busca extracto , buscando a lo mas 10 c a r a c t e r e s antes y
// despues
int pos = texto . indexOf ( busqueda , 0);
int inicio = pos - t a m a n o E x t r a c t o;
if ( inicio < 0) {
inicio = 0;
}
int fin = pos + busqueda . length () + t a m a n o E x t r a c t o;
if ( fin > texto . length () - 1) {
fin = texto . length () - 1;
}
extracto = texto . s u b s t r i n g( inicio , fin );
extracto = extracto . replace ( " \ n " , " " );

// Armamos r e s u l t a d o
R e s u l t a d o res = new R e s u l t a d o( n o m b r e A r c h i v o s[ i ] , numVeces , extracto );

IIC1103 Captulo 8: Archivos 79


r e s u l t a d o s[ i ] = res ;
} else {
r e s u l t a d o s[ p o s A c t u a l] = null ;
}
} else {
r e s u l t a d o s[ p o s A c t u a l] = null ;
}
p o s A c t u a l++;
}
return r e s u l t a d o s;
}

/* * Busca cuantas veces aparece una palabra en un texto


* @param palabra la palabra a buscar
* @param t e x t o A U s a r el texto a usar
* @return la cantidad de veces que aparece la palabra */
private int B u s c a r C a n t i d a d( String palabra , String t e x t o A U s a r) {
// Contamos cuantas veces esta la palabra
int veces = 0;
int pos = 0;
while ( pos != -1) {
// Buscamos string y contamos
pos = t e x t o A U s a r. indexOf ( palabra , pos + 1);
if ( pos != -1) {
veces ++;
}
}
return veces ;
}

/* * Toma un arreglo de resultados , y los ordena segun cantidad de veces


* e n c o n t r a d a la palabra
* @param r e s u l t a d o s un arreglo de r e s u l t a d o s
* @return el arreglo de r e s u l t a d o s ordenado */
public R e s u l t a d o[] O r d e n a r R e s u l t a d o s( R e s u l t a d o[] r e s u l t a d o s) {
// Usamos s e l e c t i o n sort para el orden
for ( int i = 0; i < r e s u l t a d o s. length - 1; i ++) {
int max = i ;
for ( int j = i + 1; j < r e s u l t a d o s. length ; j ++) {
if (( r e s u l t a d o s[ j ] != null ) && ( r e s u l t a d o s[ max ] != null )) {
if ( r e s u l t a d o s[ j ]. g e t N u m V e c e s() > r e s u l t a d o s[ max ]
. g e t N u m V e c e s ()) {
max = j ;
}
}
}
// Hacemos swap
R e s u l t a d o temp = r e s u l t a d o s[ i ];
r e s u l t a d o s[ i ] = r e s u l t a d o s[ max ];
r e s u l t a d o s[ max ] = temp ;
}
return r e s u l t a d o s;
}

/* * Formatea los r e s u l t a d o s para generar un string con la lista de r e s u l t a d o s


* a mostrar
* @param r e s u l t a d o s un arreglo con los r e s u l t a d o s
* @return un string con la i n f o r m a c i o n de los r e s u l t a d o s */
public String F o r m a t e a r R e s u l t a d o s( R e s u l t a d o[] r e s u l t a d o s) {
// Armamos string con r e s u l t a d o
String r e s u l t a d o = " R e s u l t a d o s para busqueda de " + p a l a b r a B u s c a d a + " : " ;
int n u m R e s u l t a d o = 1;
for ( int i = 0; i < r e s u l t a d o s. length ; i ++) {
if ( r e s u l t a d o s[ i ] != null ) {
r e s u l t a d o += " \ n " + ( n u m R e s u l t a d o ++) + " ) "
+ r e s u l t a d o s[ i ]. g e t N o m b r e A r c h i v o() + " - "
+ r e s u l t a d o s[ i ]. g e t N u m V e c e s()
+ " veces - extracto : ... "
+ r e s u l t a d o s[ i ]. g e t E x t r a c t o() + " ... " ;
}
}
return r e s u l t a d o;
}

/* * Exporta los r e s u l t a d o s a un archivo


* @param r e s u l t a d o s un arreglo con los r e s u l t a d o s
* @param n o m b r e A r c h i v o el nombre del archivo donde se e x p o r t a r a

IIC1103 Captulo 8: Archivos 80


*/
public void E x p o r t a r R e s u l t a d o s( R e s u l t a d o[] resultados , String n o m b r e A r c h i v o)
throws I O E x c e p t i o n {
// Abrimos archivo a escribir
File archivo = new File ( n o m b r e A r c h i v o);
F i l e W r i t e r escritor = new F i l e W r i t e r( archivo );
P r i n t W r i t e r p E s c r i t o r = new P r i n t W r i t e r( escritor );

// Escribe r e s u l t a d o
p E s c r i t o r. write ( F o r m a t e a r R e s u l t a d o s( r e s u l t a d o s));

p E s c r i t o r. close ();
escritor . close ();
}
}

import i i c 1 1 0 3 P a c k a g e .*;
import java . io .*;

public class P r i n c i p a l {
// Main del programa
public static void main ( String [] args ) throws I O E x c e p t i o n {
boolean salir = false ;
I n t e r f a z U s u a r i o GUI = new I n t e r f a z U s u a r i o ();
Buscador busca = new Buscador ();
String [] n o m b r e A r c h i v o s = null ;
while (! salir ) {
int opcion = GUI . M e n u O p c i o n e s();
switch ( opcion ) {
case 1:
n o m b r e A r c h i v o s = GUI . O b t e n e r N o m b r e A r c h i v o s ();
break ;
case 2:
if ( n o m b r e A r c h i v o s == null ) {
Usuario . mensaje ( " Debe ingresar los nombres de archivos antes de " +
" buscar una palabra . " );
} else {
// O b t e n e m o s palabra y buscamos
String palabra = GUI . O b t e n e r P a l a b r a ();
R e s u l t a d o[] res = busca . Buscar ( palabra , n o m b r e A r c h i v o s);
res = busca . O r d e n a r R e s u l t a d o s( res );

// M o s t r a m o s r e s u l t a d o s y e x p o r t a m o s de ser n e c e s a r i o
boolean exportar = GUI . M o s t r a r Y E x p o r t a r( busca
. F o r m a t e a r R e s u l t a d o s( res ));
if ( exportar ) {
String n o m b r e A r c h i v o = Usuario . texto (
" Ingrese el nombre del archivo de salida " ,
" salida . txt " );
busca . E x p o r t a r R e s u l t a d o s( res , n o m b r e A r c h i v o);
Usuario . mensaje ( " R e s u l t a d o s e x p o r t a d o s. " );
}
}
break ;
case 3:
salir = true ;
break ;
}
}
}
}

IIC1103 Captulo 8: Archivos 81


Problema 18: Corrector Ortogr
afico
Enunciado
Debe implementar un programa que consista en un corrector ortografico.

Se le pide implementar un programa que pueda corregir un texto en un archivo en base a un dicciona-
rio provisto en otro archivo. En particular, se le pide implementar la clase Corrector, que se encargara de
hacer la correccion de las palabras, y el metodo main de la clase Principal. Ademas, tendra a su disposici
on
dos clases ya creadas: InterfazUsuario, para las funcionalidades m as comunes de interacci
on con el usuario,
y Diccionario, con informaci on de un diccionario.

Clase Diccionario: la siguiente clase ya viene definida e implementada, por lo que usted NO DEBE IM-
PLEMENTARLA. Esta clase encapsula la informaci on necesaria sobre un diccionario para correcci
on. A
continuacion se describen sus metodos p
ublicos para que usted pueda utilizarlos:

public Diccionario(): constructor de la clase, crea el diccionario e inicializa sus atributos internos.
Un diccionario puede almacenar a lo m
as 100 palabras.
public boolean agregarPalabra(String nuevaPalabra): agrega una palabra al diccionario; retor-
na true si pudo, false si estaba lleno y no pudo.
public void iniciarRecorrido(): prepara el objeto diccionario para recorrer todas sus palabras.
Debe ser llamado 1 vez antes de avanzar usando el metodo getSiguiente().
public String getSiguiente(): retorna la siguiente palabra del diccionario para recorrerlas todas.
Cada vez que se llame, entregar
a una palabra distinta, secuencialmente, del diccionario. Debe llamarse
una vez a iniciarRecorrido previamente. Retorna null despues de entregar la u ltima palabra.
public int getDiferencia(String palabra1, String palabra2): compara las dos palabras da-
das, y retorna un entero indicando la diferencia. Si retorna 0, quiere decir que son iguales; si retorna 1,
quiere decir que tiene una letra diferente (por ejemplo, casa con cosa), o que son iguales pero una
tiene 1 letra mas que la otra al final (por ejemplo, casa con casas). Si retorna un numero mayor,
indica cuantas letras distintas tienen, o cu
antas letras m
as tiene una que la otra.
public String getPalabraEnTexto(String texto, int inicio): busca en el texto dado, desde la
posici
on inicio, la siguiente palabra hasta un espacio ( ) o hasta el fin del texto, y la retorna.

Clase InterfazUsuario: la siguiente clase ya viene definida e implementada, por lo que usted NO DEBE
IMPLEMENTARLA. Esta clase tiene metodos para pedir y mostrar la informaci on necesaria al usuario. A
continuacion se describen sus metodos p
ublicos para que usted pueda utilizarlos:

public int MostrarMenu(): muestra un men u con opciones al usuario, y retorna la opci
on elegida.
No realiza ninguna acci
on asociada; solamente retorna el n
umero de la opci
on indicada por el usuario.
Las opciones que presenta son:
(1) Cargar diccionario: retorna 1.
(2) Corregir archivo: retorna 2.
(3) Guardar archivo corregido: retorna 3.
(4) Salir: retorna 4.
public int GetCorrecion(String[] opciones, int cantOpciones, String aCorregir): muestra
al usuario una lista de opciones (para cuando una palabra se puede corregir con varias opciones), y le
pide que ingrese el n
umero de una. Retorna ese entero (entre 1 y la cantidad de opciones).

IIC1103 Captulo 8: Archivos 82


public String PedirNombreArchivo(): pide un nombre de archivo al usuario, y lo retorna.
public void AvisarCorreccion(String pOriginal, String pFinal): muestra un mensaje avisan-
do que una palabra se corrigi
o, y por cu
al otra.

Clase Corrector: la siguiente clase debe ser implementada por usted. Esta clase es la encargada de corregir
el contenido de un archivo en base al diccionario, y guardarlo. Puede tener todos los atributos y metodos
privados que usted considere necesarios. Debe tener los siguientes metodos p
ublicos:

public Diccionario cargarPalabras(String nombreArchivo) throws IOException: Este meto-


do debe recibir como par ametro el nombre de un archivo con un diccionario. El formato de un archivo
de diccionario consiste en una palabra por lnea, cada palabra siendo una palabra correcta para ese
diccionario. Este metodo debe abrir el archivo indicado, crear un objeto Diccionario y cargarle las
palabras, y retornarlo. Si no exista el archivo, debe retornar null.
public String getContenido(String nombreArchivo) throws IOException: Este metodo debe re-
cibir como par
ametro el nombre de un archivo a corregir; debe leer su contenido, y retornar un string
con todo el contenido del texto, incluyendo los saltos de lnea.
public String corregir(String texto, Diccionario dic, InterfazUsuario GUI): Este meto-
do debe recibir como parametro un texto a corregir, un objeto Diccionario, y un objeto InterfazUsuario.
Debe utilizar el Diccionario para corregir el texto. Debe revisar cada palabra del texto (se toma sola-
mente el espacio ( ) como separador de palabras), y si encuentra una palabra con una diferencia en
el diccionario, cambiarla por esa y avisar con un mensaje al usuario. Si encuentra m as de una palabra
con una diferencia en el diccionario, debe mostrar al usuario la lista para que elija por cu
al cambiarla.
Si la encuentra en el diccionario, o solamente encuentra palabras con m as diferencia, deja la misma
palabra. Retorna el texto corregido.
public void guardarCorregido(String textoCorregido, String archivoCorregido) throws IOException:
Este metodo debe recibir como par ametro un texto corregido, y el nombre de un nuevo archivo. Debe
crear ese archivo (o sobrescribirlo si exista), y escribir el texto corregido en el.

Clase Principal: el metodo main de esta clase debe ser implementado por usted. Debe consistir en el
funcionamiento principal del programa, que debe realizar las siguientes funciones:

Tener el ciclo principal para el men


u del programa.

Realizar cada una de las opciones que ingrese el usuario, utilizando las clases anteriormente definidas.
En particular, dependiendo de la elecci
on, si eligi
o lo siguiente, debe hacer lo indicado:
(1) Cargar diccionario: obtener del usuario el nombre del diccionario, y cargarlo internamente,
avisando con un mensaje si pudo o no.
(2) Corregir archivo: si no se ha cargado un diccionario, avisa y no hace nada. Si se ha cargado,
debe pedirle al usuario un archivo, corregirlo, guardar internamente el texto corregido, y avisar
cuando finalice la correccion. Si el archivo no existe, debe avisar.
(3) Guardar archivo corregido: si no hay texto corregido, avisa y no hace nada. Si hay, debe
pedirle al usuario el nombre del archivo de salida, y guardar el texto corregido ah, avisando
cuando finalice. Si el archivo no existe, debe avisar.
(4) Salir: para terminar el programa.

A continuaci
on se muestra el c
odigo de las clases ya implementadas:

IIC1103 Captulo 8: Archivos 83


// Clase que i m p l e m e n t a un d i c c i o n a r i o
public class D i c c i o n a r i o {
// Lista de palabras , maximo de 100 palabras
private String [] palabras ;
private int c a n t P a l a b r a s;
private int l u g a r R e c o r r i d o;

/* * C o n s t r u c t o r */
public D i c c i o n a r i o() {
palabras = new String [100];
c a n t P a l a b r a s = 0;
l u g a r R e c o r r i d o = 0;
}

/* * Agrega una palabra al d i c c i o n a r i o


* @param n u e v a P a l a b r a la palabra a agregar
* @return true si agrego , false si no pudo por c a p a c i d a d llena */
public boolean a g r e g a r P a l a b r a( String n u e v a P a l a b r a) {
if ( c a n t P a l a b r a s < palabras . length ) {
palabras [ c a n t P a l a b r a s ++] = n u e v a P a l a b r a;
return true ;
} else {
return false ;
}
}

/* * I n i c i a l i z a la clase para recorrer el d i c c i o n a r i o */


public void i n i c i a r R e c o r r i d o() {
l u g a r R e c o r r i d o = 0;
}

/* * Obtiene la s i g u i e n t e palabra cuando se esta r e c o r r i e n d o el d i c c i o n a r i o


* @return la palabra siguiente , o null si llego al final */
public String g e t S i g u i e n t e () {
if ( l u g a r R e c o r r i d o < c a n t P a l a b r a s) {
return palabras [ l u g a r R e c o r r i d o ++];
} else {
return null ;
}
}

/* * Revisa las d i f e r e n c i a s entre dos palabras .


* @param palabra1 la primera palabra
* @param palabra2 la segunda palabra
* @return 0 si son iguales , 1 si tienen 1 letra de d i f e r e n c i a o de mas al
* inicio o al final , otro numero si tienen mas d i f e r e n c i a s */
public int g e t D i f e r e n c i a( String palabra1 , String palabra2 ) {
// O r d e n a m o s las palabras para c o m p a r a c i o n
int d i f e r e n c i a s = 0;
String p a l a b r a M a y o r = palabra1 ;
String p a l a b r a M e n o r = palabra2 ;
if ( palabra2 . length () > palabra1 . length ()) {
p a l a b r a M a y o r = palabra2 ;
p a l a b r a M e n o r = palabra1 ;
}

// R e v i s a m o s las dos palabras del inicio


for ( int i = 0; i < p a l a b r a M e n o r. length (); i ++) {
if ( p a l a b r a M e n o r. charAt ( i ) != p a l a b r a M a y o r. charAt ( i )) {
d i f e r e n c i a s ++;
}
}

// Le sumamos las letras de mas


d i f e r e n c i a s += p a l a b r a M a y o r. length () - p a l a b r a M e n o r. length ();
return d i f e r e n c i a s;
}

/* * Retorna una palabra en el texto , desde la posicion dada , hasta un espacio


* @param texto el texto
* @param inicio la posicion desde donde buscar
* @return la palabra hasta el espacio , o null si no es valido */
public String g e t P a l a b r a E n T e x t o( String texto , int inicio ) {
String palabra = null ;
if ( inicio < texto . length () && inicio >= 0) {

IIC1103 Captulo 8: Archivos 84


int nuevaPos = texto . indexOf ( " " , inicio );
if ( nuevaPos == -1) {
nuevaPos = texto . length ();
}
palabra = texto . s u b s t r i n g( inicio , nuevaPos );
}
return palabra ;
}
}

import i i c 1 1 0 3 P a c k a g e .*;
public class I n t e r f a z U s u a r i o {
/* * Muestra un menu de opciones , y retorna la opcion elegida
* @return un numero con la opcion elegida */
public int M o s t r a r M e n u() {
int opcion ;
do {
opcion = Usuario . entero (" Elija una opcion :\ n (1) Cargar d i c c i o n a r i o \ n " +
" (2) Corregir archivo \ n (3) Guardar archivo c o r r e g i d o \ n (4) Salir " );
} while ( opcion < 1 || opcion > 73);
return opcion ;
}

/* * Permite elegir entre una serie de opciones


* @param opciones las opciones
* @param a C o r r e g i r la palabra estando en c o r r e c c i o n
* @return el lugar de la palabra elegida */
public int G e t C o r r e c i o n( String [] opciones , int cantOpciones ,
String a C o r r e g i r) {
// Armamos mensaje
String mensaje = " Hay mas de una opcion para corregir la palabra "
+ a C o r r e g i r + " . Elija una de las s i g u i e n t e s opciones :\ n " ;
mensaje += " \ n0 ) No corregir palabra " ;
for ( int i = 0; i < c a n t O p c i o n e s; i ++) {
mensaje += " \ n " + ( i + 1) + " ) " + opciones [ i ];
}
// Pide opcion
int opcion ;
do {
opcion = Usuario . entero ( mensaje );
} while ( opcion < 0 || opcion > opciones . length );
return opcion ;
}

/* * Entrega el nombre de un archivo


* @return el nombre del archivo dado por el usuario */
public String P e d i r N o m b r e A r c h i v o() {
String nombre ;
do {
nombre = Usuario . texto ( " Ingrese el nombre del archivo : " );
} while ( nombre == null || nombre . equals ( " " ));
return nombre ;
}

/* * Avisa una c o r r e c i o n
* @param p O r i g i n a l la palabra original
* @param pFinal la c o r r e g i d a */
public void A v i s a r C o r r e c c i o n( String pOriginal , String pFinal ) {
Usuario . mensaje ( " Palabra " + p O r i g i n a l + " c o r r e g i d a a "
+ pFinal + " . " );
}
}

Criterios de soluci
on
Posible soluci
on

import java . io .*;


import java . util . Scanner ;

public class C o r r e c t o r {
/* * Carga las palabras de un archivo en un D i c c i o n a r i o
* @param n o m b r e A r c h i v o El nombre del archivo a revisar

IIC1103 Captulo 8: Archivos 85


* @return un objeto Diccionario , o null si no existia el archivo */
public D i c c i o n a r i o c a r g a r P a l a b r a s( String n o m b r e A r c h i v o) throws I O E x c e p t i o n {
// Abrimos archivo y r e v i s a m o s si existe
File archivo = new File ( n o m b r e A r c h i v o);
if ( archivo . exists ()) {
// Abrimos lectores
Scanner bLector = new Scanner ( archivo );

// Creamos d i c c i o n a r i o
D i c c i o n a r i o dic = new D i c c i o n a r i o ();

// Leemos cada palabra


while ( bLector . h a s N e x t L i n e()) {
dic . a g r e g a r P a l a b r a( bLector . nextLine ());
}

// Cerramos archivos
bLector . close ();
return dic ;
} else {
return null ;
}
}

/* * Abre un archivo y retorna su c o n t e n i d o


* @param n o m b r e A r c h i v o
* @return un string con el c o n t e n i d o */
public String g e t C o n t e n i d o( String n o m b r e A r c h i v o) throws I O E x c e p t i o n {
// Abrimos archivo y r e v i s a m o s si existe
File archivo = new File ( n o m b r e A r c h i v o);
if ( archivo . exists ()) {
// Abrimos lectores
Scanner bLector = new Scanner ( archivo );

// Leemos cada palabra

String texto = " " ;


while ( bLector . h a s N e x t L i n e()) {
texto += bLector . nextLine () + " \ n " ;
}

// Cerramos archivos
bLector . close ();
return texto ;
} else {
return null ;
}
}

/* * Corrige un texto y lo retorna


* @param texto
* @param dic
* @return */
public String corregir ( String texto , D i c c i o n a r i o dic , I n t e r f a z U s u a r i o GUI ) {
String c o r r e g i d o = " " ;

// A v a n z a m o s palabra por palabra


int inicio = 0;
String a C o r r e g i r = dic . g e t P a l a b r a E n T e x t o( texto , inicio );
while ( a C o r r e g i r != null ) {
// Donde se a l m a c e n a r a n las opciones
String [] opciones = new String [100];
int c a n t O p c i o n e s = 0;

// R e c o r r e m o s todas las palabras del d i c c i o n a r i o


dic . i n i c i a r R e c o r r i d o ();
String correcta = dic . g e t S i g u i e n t e ();
while ( correcta != null ) {
// C o m p a r a m o s
int difs = dic . g e t D i f e r e n c i a( aCorregir , correcta );

// R e a l i z a m o s accion
if ( difs == 1) {
opciones [ c a n t O p c i o n e s++] = correcta ;
}

// Pasamos a s i g u i e n t e

IIC1103 Captulo 8: Archivos 86


correcta = dic . g e t S i g u i e n t e();
}

// R e v i s a m o s las opciones
String c o r r e c c i o n = a C o r r e g i r;
if ( c a n t O p c i o n e s == 1) {
c o r r e c c i o n = opciones [0];
GUI . A v i s a r C o r r e c c i o n( aCorregir , c o r r e c c i o n);
} else if ( c a n t O p c i o n e s > 1) {
// Si hay muchas opciones , debe elegir
// O b t e n e m o s correcion , y si eligio corregirla , la c a m b i a m o s por
// esa palabra
int opcion = GUI . G e t C o r r e c i o n( opciones , cantOpciones , a C o r r e g i r);
if ( opcion != 0) {
c o r r e c c i o n = opciones [ opcion - 1];
}
}

// Vamos armando c o r r e g i d o
c o r r e g i d o += c o r r e c c i o n + " " ;

// A v a n z a m o s
inicio += a C o r r e g i r. length () + 1;
a C o r r e g i r = dic . g e t P a l a b r a E n T e x t o( texto , inicio );
}

// Sacamos espacio final y r e t o r n a m o s


c o r r e g i d o = c o r r e g i d o. s u b s t r i n g(0 , c o r r e g i d o. length () - 1);
return c o r r e g i d o;
}

/* * Guarda el archivo c o r r e g i d o
* @param t e x t o C o r r e g i d o el texto c o r r e g i d o
* @param a r c h i v o C o r r e g i d o el nombre del archivo donde guardar el texto c o r r e g i d o
* @throws I O E x c e p t i o n */
public void g u a r d a r C o r r e g i d o( String textoCorregido , String a r c h i v o C o r r e g i d o)
throws I O E x c e p t i o n {
// Abrimos archivo a escribir
File archivo = new File ( a r c h i v o C o r r e g i d o);
F i l e W r i t e r escritor = new F i l e W r i t e r( archivo );
P r i n t W r i t e r p E s c r i t o r = new P r i n t W r i t e r( escritor );

// Escribe texto
p E s c r i t o r. write ( t e x t o C o r r e g i d o);

p E s c r i t o r. close ();
escritor . close ();
}
}

import i i c 1 1 0 3 P a c k a g e .*;
import java . io .*;

public class P r i n c i p a l {
// Main del programa
public static void main ( String [] args ) throws I O E x c e p t i o n {
// V a r i a b l e s internas
I n t e r f a z U s u a r i o GUI = new I n t e r f a z U s u a r i o ();
C o r r e c t o r corrige = new C o r r e c t o r();
String c o r r e g i d o = null ;
D i c c i o n a r i o dic = null ;

// Ciclo p r i n c i p a l
boolean salir = false ;
while (! salir ) {
int opcion = GUI . M o s t r a r M e n u();
switch ( opcion ) {
case 1: // Cargar d i c c i o n a r i o
String archivo = GUI . P e d i r N o m b r e A r c h i v o ();
dic = corrige . c a r g a r P a l a b r a s( archivo );
if ( dic != null ) {
Usuario . mensaje ( " D i c c i o n a r i o cargado " );
} else {
Usuario . mensaje ( " D i c c i o n a r i o no e x i s t e n t e" );
}
break ;

IIC1103 Captulo 8: Archivos 87


case 2: // Corregir archivo
if ( dic != null ) {
String a r c h i v o A C o r r e g i r = GUI . P e d i r N o m b r e A r c h i v o();
String c o n t e n i d o = corrige . g e t C o n t e n i d o( a r c h i v o A C o r r e g i r);
if ( c o n t e n i d o != null ) {
c o r r e g i d o = corrige . corregir ( contenido , dic , GUI );
Usuario . mensaje ( " Texto c o r r e g i d o" );
} else {
Usuario . mensaje ( " Archivo a corregir no e x i s t e n t e" );
}
} else {
Usuario . mensaje ( " No se ha cargado un d i c c i o n a r i o" );
}
break ;
case 3: // Guardar texto
if ( c o r r e g i d o != null ) {
String a r c h i v o C o r r e g i d o = GUI . P e d i r N o m b r e A r c h i v o();
corrige . g u a r d a r C o r r e g i d o( corregido , a r c h i v o C o r r e g i d o);
Usuario . mensaje ( " Archivo c o r r e g i d o guardado " );
} else {
Usuario . mensaje ( " No se ha c o r r e g i d o un archivo " );
}
break ;
case 4:
salir = true ;
break ;
}
}
}
}

IIC1103 Captulo 8: Archivos 88


Problema 19: Traductor
Enunciado
Debe implementar un programa que consista en un traductor de espa
nol a ingles.

Se le pide implementar un programa que pueda traducir un texto en un archivo en base a un dicciona-
rio provisto en dos archivos con palabras en dos idiomas. En particular, se le pide implementar la clase
Traductor, que se encargara de hacer la traduccion de las palabras, y el metodo main de la clase Principal.
Adem as, tendr
a a su disposici
on dos clases ya creadas: InterfazUsuario, para las funcionalidades m as co-
munes de interaccion con el usuario, y Diccionario, con informaci on de un diccionario espa nol-ingles.

Clase Diccionario: la siguiente clase ya viene definida e implementada, por lo que usted NO DEBE IM-
PLEMENTARLA. Esta clase encapsula la informaci on necesaria sobre un diccionario para traducci
on. A
continuacion se describen sus metodos p
ublicos para que usted pueda utilizarlos:

public Diccionario(int cantMax): constructor de la clase, crea el diccionario e inicializa sus atri-
butos internos. Puede almacenar a lo m
as cantMax palabras.
public boolean agregarPalabra(String nuevaPalabra, String traduccion): agrega una pala-
bra y su traducci
on al diccionario; retorna true si pudo, false si estaba lleno y no pudo.
public int getCantPalabras(): retorna la cantidad de palabras almacenadas.
public String getPalabra(int lugar): retorna una palabra del diccionario (no su traducci on), la
que este en la posici
on indicada por lugar (que es un entero entre 0 y la cantidad de palabras
almacenadas). Retorna null si es un lugar no v
alido.
public int traducir(String palabra): busca la palabra en el diccionario, y retorna su traducci
on.
Si no la encuentra, retorna null.
public boolean swapPalabras(int lugar1, int lugar2): intercambia las palabras en los lugares
indicados de posici
on. Hace lo mismo con sus traducciones.
public String getPalabraEnTexto(String texto, int inicio): busca en el texto dado, desde la
posici
on inicio, la siguiente palabra hasta un espacio ( ) o hasta el fin del texto, y la retorna.

Clase InterfazUsuario: la siguiente clase ya viene definida e implementada, por lo que usted NO DEBE
IMPLEMENTARLA. Esta clase tiene metodos para pedir y mostrar la informaci on necesaria al usuario. A
continuacion se describen sus metodos p
ublicos para que usted pueda utilizarlos:

public int MostrarMenu(): muestra un men u con opciones al usuario, y retorna la opci
on elegida.
No realiza ninguna acci
on asociada; solamente retorna el n
umero de la opci
on indicada por el usuario.
Las opciones que presenta son:
(1) Cargar diccionario: retorna 1.
(2) Traducir archivo: retorna 2.
(3) Guardar archivo traducido: retorna 3.
(4) Salir: retorna 4.
public void AvisarNoEncontrada(String palabra): muestra un mensaje avisando que una palabra
no se tradujo pues no se encontr
o en el diccionario.
public String PedirNombreArchivo(): pide un nombre de archivo al usuario, y lo retorna.

IIC1103 Captulo 8: Archivos 89


public void MostrarDiccionario(Diccionario dic): recibe un objeto Diccionario, y muestra su
contenido en un mensaje en pantalla.

Clase Traductor: la siguiente clase debe ser implementada por usted. Esta clase es la encargada de traducir
el contenido de un archivo en base a un diccionario, y guardarlo. Puede tener todos los atributos y metodos
privados que usted considere necesarios. Debe tener los siguientes metodos p
ublicos:

public Diccionario cargarPalabras(String archivoEspanol, String archivoIngles, int cantMaxima)


throws IOException: Este metodo debe recibir como par ametro el nombre de dos archivos de diccio-
nario: el primero con palabras en espa nol, y el segundo con las traducciones al ingles. El formato de
cada archivo sera una palabra por lnea. Ademas, recibe un entero, cantMaxima, que indica el tama no
maximo en palabras del diccionario a crear. Este metodo debe abrir los archivos indicados, crear un
objeto Diccionario, cargarle las palabras y sus traducciones, y retornarlo. Si no exista uno de los
archivos, debe retornar null.
public Diccionario ordenarDiccionario(Diccionario dic): Este metodo debe recibir como par ame-
tro un diccionario, ordenar sus palabras (junto con sus traducciones asociadas) alfabeticamente, y
retornar el diccionario ordenado.
public String getContenido(String nombreArchivo) throws IOException: Este metodo debe re-
cibir como par
ametro el nombre de un archivo a traducir; debe leer su contenido, y retornar un string
con todo el contenido del texto, sin tomar en cuenta saltos de lnea.
public String traducir(String texto, Diccionario dic, InterfazUsuario GUI): Este meto-
do debe recibir como parametro un texto a traducir, un diccionario, y un objeto InterfazUsuario.
Debe utilizar el Diccionario para traducir el texto, sin importar si la palabra viene en may
usculas o
minusculas; se debe tomar como una misma palabra. Debe revisar cada palabra del texto (se toma
solamente el espacio ( ) como separador de palabras), e intentar traducirla. Si no pudo traducir
una palabra por no estar en el diccionario, deja la misma original, y avisa por un mensaje al usuario.
Retorna el texto traducido.
public void guardarTraducido(String textoTraducido, String archivoSalida) throws IOException:
Este metodo debe recibir como par ametro un texto traducido, y el nombre de un nuevo archivo. Debe
crear ese archivo (o sobrescribirlo si exista), y escribir el texto traducido en el.

Clase Principal: el metodo main de esta clase debe ser implementado por usted. Debe consistir en el
funcionamiento principal del programa, que debe realizar las siguientes funciones:

Tener el ciclo principal para el men


u del programa.
Realizar cada una de las opciones que ingrese el usuario, utilizando las clases anteriormente definidas.
En particular, dependiendo de la elecci
on, si eligi
o lo siguiente, debe hacer lo indicado:
(1) Cargar diccionario: cargar un diccionario de tama no maximo 100 palabras de los archivos
espanol.txt e ingles.txt, ordenarlo alfabeticamente, y mostrarlo al usuario. Si los archivos no
existen, debe avisar.
(2) Traducir archivo: si no se ha cargado un diccionario, avisa y no hace nada. Si se ha cargado,
debe pedirle al usuario un archivo, traducirlo, guardar internamente el texto traducido, y avisar
cuando finalice la traducci
on. Si el archivo no existe, debe avisar.
(3) Guardar archivo traducido: si no hay texto traducido, avisa y no hace nada. Si hay, debe
pedirle al usuario el nombre del archivo de salida, y guardar el texto traducido ah, avisando
cuando finalice. Si el archivo no existe, debe avisar.
(4) Salir: para terminar el programa.

IIC1103 Captulo 8: Archivos 90


A continuaci
on se muestra el c
odigo de las clases ya implementadas:

public class D i c c i o n a r i o {
// A t r i b u t o s
private String [] palabras ;
private String [] t r a d u c c i o n e s;
private int c a n t P a l a b r a s;

/* * C o n s t r u c t o r
* @cantMax la cantidad maxima de palabras que soporta */
public D i c c i o n a r i o( int cantMax ) {
palabras = new String [ cantMax ];
t r a d u c c i o n e s = new String [ cantMax ];
c a n t P a l a b r a s = 0;
}

/* * Agrega una palabra y su t r a d u c c i o n al d i c c i o n a r i o


* @param palabra la palabra original
* @param t r a d u c c i o n la t r a d u c c i o n de la palabra */
public void a g r e g a r P a l a b r a( String palabra , String t r a d u c c i o n) {
palabras [ c a n t P a l a b r a s] = palabra ;
t r a d u c c i o n e s[ c a n t P a l a b r a s++] = t r a d u c c i o n;
}

/* * Obtiene la palabra del lugar indicado


* @param lugar el lugar a obtener
* @return la palabra siguiente , o null si no era lugar valido */
public String g e t P a l a b r a( int lugar ) {
if ( lugar >= 0 && lugar < c a n t P a l a b r a s) {
return palabras [ lugar ];
} else {
return null ;
}
}

/* * Retorna la cantidad de palabras en el d i c c i o n a r i o


* @return la cantidad de palabras en el d i c c i o n a r i o */
public int g e t C a n t P a l a b r a s () {
return c a n t P a l a b r a s;
}

/* * I n t e r c a m b i a dos palabras y sus t r a d u c c i o n e s de lugar ,


* correspondientemente
* @param lugar1 el lugar de una de las palabras ( entre 0 y cantPalabras -1)
* @param lugar2 el lugar de la otra ( entre 0 y cantPalabras -1)
* @return true si se hizo el swap , false si uno de los lugares no era valido */
public boolean s w a p P a l a b r a s( int lugar1 , int lugar2 ) {
if ( lugar1 >= 0 && lugar2 >= 0 && lugar1 < c a n t P a l a b r a s
&& lugar2 < c a n t P a l a b r a s) {
String t e m p P a l a b r a = palabras [ lugar1 ];
String t e m p T r a d u c c i o n = t r a d u c c i o n e s[ lugar1 ];
palabras [ lugar1 ] = palabras [ lugar2 ];
t r a d u c c i o n e s[ lugar1 ] = t r a d u c c i o n e s[ lugar2 ];
palabras [ lugar2 ] = t e m p P a l a b r a;
t r a d u c c i o n e s[ lugar2 ] = t e m p T r a d u c c i o n;
return true ;
} else {
return false ;
}
}

/* * Retorna la t r a d u c c i o n de una palabra


* @param palabra la palabra a traducir
* @return la traduccion , o null si no tenia t r a d u c c i o n */
public String traducir ( String palabra ) {
for ( int i = 0; i < c a n t P a l a b r a s; i ++) {
if ( palabras [ i ]. equals ( palabra )) {
return t r a d u c c i o n e s[ i ];
}
}
return null ;
}

/* * Retorna una palabra en el texto , desde la posicion dada , hasta un espacio


* @param texto el texto

IIC1103 Captulo 8: Archivos 91


* @param inicio la posicion desde donde buscar
* @return la palabra hasta el espacio , o null si no es valido */
public String g e t P a l a b r a E n T e x t o( String texto , int inicio ) {
String palabra = null ;
if ( inicio < texto . length () && inicio >= 0) {
int nuevaPos = texto . indexOf ( " " , inicio );
if ( nuevaPos == -1) {
nuevaPos = texto . length ();
}
palabra = texto . s u b s t r i n g( inicio , nuevaPos );
}
return palabra ;
}
}

import i i c 1 1 0 3 P a c k a g e .*;
public class I n t e r f a z U s u a r i o {
/* * Muestra un menu de opciones , y retorna la opcion elegida
* @return un numero con la opcion elegida */
public int M o s t r a r M e n u() {
int opcion ;
do {
opcion = Usuario . entero (" Elija una opcion :\ n (1) Cargar d i c c i o n a r i o \ n " +
" (2) Traducir archivo \ n (3) Guardar archivo t r a d u c i d o \ n (4) Salir " );
} while ( opcion < 1 || opcion > 73);
return opcion ;
}

/* * Avisa cuando no se pudo traducir una palabra


* @param palabra la palabra no t r a d u c i d a */
public void A v i s a r N o E n c o n t r a d a( String palabra ) {
Usuario . mensaje ( " Palabra " + palabra
+ " no fue e n c o n t r a d a en diccionario , y no fue t r a d u c i d a. " );
}

/* * Entrega el nombre de un archivo


* @return el nombre del archivo dado por el usuario */
public String P e d i r N o m b r e A r c h i v o() {
String nombre ;
do {
nombre = Usuario . texto ( " Ingrese el nombre del archivo : " );
} while ( nombre == null || nombre . equals ( " " ));
return nombre ;
}

/* * Muestra el c o n t e n i d o de un d i c c i o n a r i o
* @param dic el d i c c i o n a r i o */
public void M o s t r a r D i c c i o n a r i o( D i c c i o n a r i o dic ) {
String mensaje = " D i c c i o n a r i o cargado y ordenado . C o n t e n i d o:\ n " ;
for ( int i = 0; i < dic . g e t C a n t P a l a b r a s (); i ++) {
mensaje += " \ n " + ( i + 1) + " ) " + dic . g e t P a l a b r a( i ) + " - "
+ dic . traducir ( dic . g e t P a l a b r a( i ));
}
Usuario . mensaje ( mensaje );
}
}

Criterios de soluci
on
Posible soluci
on

import java . io .*;


import java . util . Scanner ;

public class T r a d u c t o r {
/* * Carga las palabras de los archivos para hacer un d i c c i o n a r i o
* @param a r c h i v o E s p a n o l El nombre del archivo en espanol
* @param a r c h i v o I n g l e s El nombre del archivo en ingles
* @return un objeto Diccionario , o null si no existia el archivo */
public D i c c i o n a r i o c a r g a r P a l a b r a s( String archivoEspanol ,
String archivoIngles , int c a n t M a x i m a) throws I O E x c e p t i o n {
// Abrimos archivo y r e v i s a m o s si existe
File a r c h i v o E s p = new File ( a r c h i v o E s p a n o l);

IIC1103 Captulo 8: Archivos 92


File a r c h i v o I n g = new File ( a r c h i v o I n g l e s);
if ( a r c h i v o E s p. exists () && a r c h i v o I n g. exists ()) {
// Abrimos lectores
Scanner b L e c t o r E s p = new Scanner ( a r c h i v o E s p);
Scanner b L e c t o r I n g = new Scanner ( a r c h i v o I n g);

// Creamos d i c c i o n a r i o
D i c c i o n a r i o dic = new D i c c i o n a r i o( c a n t M a x i m a);

// Leemos cada palabra y su traduccion , y a g r e g a m o s


String palabra ;
while ( b L e c t o r E s p. h a s N e x t L i n e()) {
palabra = b L e c t o r E s p. nextLine ();
String t r a d u c c i o n = b L e c t o r I n g. nextLine ();
dic . a g r e g a r P a l a b r a( palabra , t r a d u c c i o n);
}

// Cerramos archivos
b L e c t o r E s p. close ();
b L e c t o r I n g. close ();
return dic ;
} else {
return null ;
}
}

/* * Ordena un d i c c i o n a r i o a l f a b e t i c a m e n t e
* @param dic el d i c c i o n a r i o
* @return el d i c c i o n a r i o ordenado */
public D i c c i o n a r i o o r d e n a r D i c c i o n a r i o( D i c c i o n a r i o dic ) {
// Usamos s e l e c t i o n sort para el orden
for ( int i = 0; i < dic . g e t C a n t P a l a b r a s (); i ++) {
int min = i ;
for ( int j = i + 1; j < dic . g e t C a n t P a l a b r a s (); j ++) {
if ( dic . g e t P a l a b r a( j ). c o m p a r e T o( dic . g e t P a l a b r a( min )) < 0) {
min = j ;
}
}
// Hacemos swap
dic . s w a p P a l a b r a s(i , min );
}
return dic ;
}

/* * Abre un archivo y retorna su c o n t e n i d o


* @param n o m b r e A r c h i v o
* @return un string con el c o n t e n i d o */
public String g e t C o n t e n i d o( String n o m b r e A r c h i v o) throws I O E x c e p t i o n {
// Abrimos archivo y r e v i s a m o s si existe
File archivo = new File ( n o m b r e A r c h i v o);
if ( archivo . exists ()) {
// Abrimos lectores
Scanner bLector = new Scanner ( archivo );

// Leemos cada palabra

String texto = " " ;


while ( bLector . h a s N e x t L i n e()) {
texto += bLector . nextLine ();
}

// Cerramos archivos
bLector . close ();
return texto ;
} else {
return null ;
}
}

/* * Traduce un texto
* @param texto el texto a traducir
* @param d i c c i o n a r i o el d i c c i o n a r i o
* @return el texto t r a d u c i d o */
public String traducir ( String texto , D i c c i o n a r i o dic , I n t e r f a z U s u a r i o GUI ) {
String t r a d u c i d o = " " ;

// A v a n z a m o s palabra por palabra

IIC1103 Captulo 8: Archivos 93


int inicio = 0;
String a T r a d u c i r = dic . g e t P a l a b r a E n T e x t o( texto , inicio );
while ( a T r a d u c i r != null ) {
String t r a d u c i d a = dic . traducir ( a T r a d u c i r. t o L o w e r C a s e ());
if ( t r a d u c i d a == null ) {
GUI . A v i s a r N o E n c o n t r a d a( a T r a d u c i r);
t r a d u c i d a = a T r a d u c i r;
}

// Vamos armando c o r r e g i d o
t r a d u c i d o += t r a d u c i d a + " " ;

// A v a n z a m o s
inicio += a T r a d u c i r. length () + 1;
a T r a d u c i r = dic . g e t P a l a b r a E n T e x t o( texto , inicio );
}

// Sacamos espacio final y r e t o r n a m o s


t r a d u c i d o = t r a d u c i d o. s u b s t r i n g(0 , t r a d u c i d o. length () - 1);
return t r a d u c i d o;
}

/* * Guarda el archivo t r a d u c i d o
* @param t e x t o T r a d u c i d o el texto t r a d u c i d o
* @param a r c h i v o S a l i d a el nombre del archivo donde guardar el texto t r a d u c i d o
* @throws I O E x c e p t i o n */
public void g u a r d a r T r a d u c i d o( String textoTraducido , String a r c h i v o S a l i d a)
throws I O E x c e p t i o n {
// Abrimos archivo a escribir
File archivo = new File ( a r c h i v o S a l i d a);
F i l e W r i t e r escritor = new F i l e W r i t e r( archivo );
P r i n t W r i t e r p E s c r i t o r = new P r i n t W r i t e r( escritor );

// Escribe texto
p E s c r i t o r. write ( t e x t o T r a d u c i d o);

p E s c r i t o r. close ();
escritor . close ();
}
}

import i i c 1 1 0 3 P a c k a g e .*;
import java . io .*;

public class P r i n c i p a l {
// Main del programa
public static void main ( String [] args ) throws I O E x c e p t i o n {
// V a r i a b l e s internas
I n t e r f a z U s u a r i o GUI = new I n t e r f a z U s u a r i o ();
T r a d u c t o r traduce = new T r a d u c t o r();
String t r a d u c i d o = null ;
D i c c i o n a r i o dic = null ;

// Ciclo p r i n c i p a l
boolean salir = false ;
while (! salir ) {
int opcion = GUI . M o s t r a r M e n u();
switch ( opcion ) {
case 1: // Cargar d i c c i o n a r i o
dic = traduce . c a r g a r P a l a b r a s( " espanol . txt " , " ingles . txt " , 100);
dic = traduce . o r d e n a r D i c c i o n a r i o( dic );
if ( dic != null ) {
GUI . M o s t r a r D i c c i o n a r i o( dic );
} else {
Usuario . mensaje ( " Archivos de d i c c i o n a r i o no e x i s t e n t e s" );
}
break ;
case 2: // Traducir archivo
if ( dic != null ) {
String a r c h i v o A T r a d u c i r = GUI . P e d i r N o m b r e A r c h i v o();
String c o n t e n i d o = traduce . g e t C o n t e n i d o( a r c h i v o A T r a d u c i r);
if ( c o n t e n i d o != null ) {
t r a d u c i d o = traduce . traducir ( contenido , dic , GUI );
Usuario . mensaje ( " Texto t r a d u c i d o" );
} else {
Usuario . mensaje ( " Archivo a traducir no e x i s t e n t e" );

IIC1103 Captulo 8: Archivos 94


}
} else {
Usuario . mensaje ( " No se ha cargado un d i c c i o n a r i o" );
}
break ;
case 3: // Guardar texto
if ( t r a d u c i d o != null ) {
String a r c h i v o T r a d u c i d o = GUI . P e d i r N o m b r e A r c h i v o();
traduce . g u a r d a r T r a d u c i d o( traducido , a r c h i v o T r a d u c i d o);
Usuario . mensaje ( " Archivo t r a d u c i d o guardado " );
} else {
Usuario . mensaje ( " No se ha t r a d u c i d o un archivo " );
}
break ;
case 4:
salir = true ;
break ;
}
}
}
}

IIC1103 Captulo 8: Archivos 95

También podría gustarte