Sei sulla pagina 1di 96

JavaTM para Niñ@s

Nadia Ameziane Garcia


JavaTM para Niñ@s
Nadia Ameziane Garcia

CopyrightⒸ 2017 Nadia Ameziane Garcia.


Queda prohibida, salvo excepción prevista en la Ley, cualquier forma de reproducción, distribución,
comunicación pública y transformación de esta obra sin contar con la autorización de los titulares de su
propiedad intelectual.
La infracción de los derechos de difusión de la obra puede ser constitutiva de delito contra la propiedad
intelectual (Arts. 270 y ss. del Código Penal).

Diseño de portada: Pixel Dizajn Studio


Todas las imágenes del interior obtenidas de Pixabay.com bajo licencia CC0.

Segunda edición, Marzo 2018

JavaTM es una marca registrada propiedad de OracleTM y como tal es mencionada con la primera letra en
mayúscula a lo largo de toda la obra.
La autora declina toda responsabilidad respecto a los perjuicios que pudiese causar la aplicación práctica del
contenido de este libro.
Intro (para tutores y tutoras)

Ante todo, muchas gracias por tomarte la molestia de hojear este libro, por querer entrar en
materia y conocer de primera mano en qué aguas se va a sumergir tu hija, alumno o cualquiera
sea la relación que te une al niño que va a aprender de estas páginas.

Quizá seas una persona con conocimientos previos de programación -tal vez incluso una
eminencia- que simplemente busca ideas para introducir estos conocimientos de forma creativa o
lúdica. En ese caso verás que hay temas por los que este libro pasa de puntillas, y es porque he
tratado de hacer pesar más las ideas generales que los detalles, de familiarizar al niño con la
forma de expresar instrucciones más que con los mil detalles o posibilidades que cada una podría
encerrar.

Si, por contra, no has tenido un contacto previo con esta disciplina, no tengas miedo. Este
libro no está pensado para dejar a nadie atrás, y si lo vas siguiendo verás que los conceptos son
muy claros y concisos, por lo que seguro que podrás echar una mano si te lo piden. Además
después de la introducción encontrarás una guía con todo lo que necesitas preparar en el
ordenador para cada capítulo del libro. No te dejaré quedar mal ;)

Tal vez incluso seas un adulto sin complejos que ha comprado este libro para sí mismo, en
ese caso ¡enhorabuena también! Estoy convencida de que también puede enseñarte cosas a ti.
Aunque lo enfocomo una guía para enseñar a personitas de 8 a 18 años, todo lo que leerás
también puede aplicarse a tu caso.

Algunas preguntas que tal vez te estés haciendo


Tal vez te estés preguntando qué puede hacer la programación por los niños. La verdad es que
yo sigo preguntándome qué NO puede hacer.

Programar es una excelente forma de construir nuevos puentes en nuestra forma de pensar: nos
predispone a abordar de forma LÓGICA las cuestiones que se nos presentan. Nos acostumbra a
ORDENAR los datos de que disponemos para abordarlos de forma eficiente. Siempre digo que
en toda persona que aprende a programar, a expresarse mediante algoritmos, se produce un click
mental que no tiene vuelta atrás. El pensamiento de programador se convierte en una
herramienta que nunca se pierde y que resulta útil en muchísimas facetas vitales.

Programando también se ponen a prueba nuestra PACIENCIA y TOLERANCIA A LA


FRUSTRACIÓN. A veces un pedazo de código es una partida de ajedrez contra nosotros
mismos. De pronto algo no sale y no sabemos por qué, pero simplemente no podemos dejarlo a
medias, y programar es algo que sigue ocurriendo en nuestra cabeza de camino al cole, mientras
nos duchamos, mientras paseamos… hasta que de pronto la solución al rompecabezas nos
ilumina la mente… ¡eureka! La sensación de haber superado un escalón, de haber crecido un
poco más cada vez que esto ocurre es un regalo inmenso para cualquiera, pero más aún
para una personita en desarrollo.

Aprender a programar también tiene una dimensión social… destierra de tu mente los prejuicios,
las imágenes de niños de 90kg que beben refrescos y no se despegan del ordenador. Tanto en la
red como en persona, la programación nos empuja a compartir, contrastar, colaborar… a formar
equipos, compartir proyectos y conocimientos, en fijarse en el código que otros han escrito y
aprender de sus errores y sus aciertos. A rodearse de otras cabecitas inquietas.

Por último -y no menos importante- programar es DEMOCRÁTICO. No requiere habilidades


especiales, no se circunscribe una edad mínima, no se ve limitado por ninguna discapacidad. No
necesitas un equipo carísimo, ni licencias de software de pago. Cualquiera puede aprender en
cualquier momento.

Tal vez te estés preguntando si programar es una actividad adecuada para tu hijo, que parece ser
una persona “de letras”. Aunque desde fuera pueda parecer una magia oscura destinada a
cerebritos o gente muy familiarizada con la tecnología, tengo que decirte que programar no es de
ni de letras ni de ciencias… sino todo lo contrario. Es una actividad multidisciplinar que
trasciende las divisiones más o menos comunes que el sistema educativo se empeña en trazas
entre unas y otras materias. Es una herramienta muy potente, que puede servir a la mente artística
y creativa del mismo modo que puede satisfacer intereses científicos. Y bueno, humildemente, a
veces los mejores programas surgen de la pereza. Del deseo de automatizar tareas tediosas
que uno no quiere hacer personalmente -o que quiere reducir a unos pocos segundos- nacen
grandes ocasiones de pensar, ingeniar y trabajar el pensamiento abstracto, una herramienta
imprescindible para cualquier estudiante.

Por último, pero no menos importante, los objetivos de aprendizaje de este libro.
Bien, mi idea al escribirlo no es que el niño o adolescente se convierta en un programador
experto, este libro no suple los estudios formales en ese campo. Mi romántico propósito es más
bien picar la curiosidad. Trazar un camino lo más fácil posible de seguir, sin una montaña de
teoría y de quisquillosas condiciones, para que el lector sea capaz de construir desde el
principio pequeños scripts o programas de forma autónoma. Pretendo que el aprendiz de
programador se sienta retado, interesado y capaz. Que tenga los conocimientos mínimos para
poder llevar a la realidad lo que su imaginación le proponga, y que jamás haga algo de forma
mecánica, sin entender el motivo. Confío en que su propia necesidad de ir más allá le llevará a
buscar la ampliación de los conocimientos que yo apenas le he esbozado, y nada me haría más
feliz que saber que un lector que termina este libro lo acaba con ganas de seguir profundizando,
porque si hay una verdad universal en el arte de la programación es que jamás termina uno de
aprenderlo.
Intro (para aprendices)

¡Enhorabuena! Ya eres casi programador o programadora. Gracias por confiar


en mí para semejante misión.

En este libro quería destapar un secreto que todos los libros de texto parecen querer ocultar:
programar es muy divertido. A mí me gusta programar porque es una de las pocas formas en el
mundo de hacer sueños realidad (está bien, algunos sueños). Es cierto que no es un sistema
infalible, pero personalmente no conozco muchas otras maneras de hacer que una idea se
convierta en una orden, y que ésta se cumpla a su vez, haciendo REAL aquello que sólo existía
en mi cabeza.

Además, para las personas curiosas programar es una oportunidad de intentar saber cómo
funcionan algunos objetos que nos rodean y que hasta ahora no nos llamaban la atención. En
cuanto sabes un par de cosas empiezas a mirar el mundo de otra manera, a imaginar qué se cuece
dentro de tu videojuego favorito, una máquina expendedora de refrescos, o incluso una báscula
de supermercado. Te preguntas si las instrucciones que los hacen funcionar serán las mismas que
tú escribirías. Tal vez incluso seas como yo y te guste ir más allá: ¿habrán tenido en cuenta todas
las posibles formas de usar ese aparato?... ¿Sabrías dar con la combinación de acciones
imprevista que hace saltar todo por los aires?

En fin, he intentado hacer de este libro algo entretenido e interesante. Quiero que empieces a ser
capaz de producir pequeños programas lo antes posible, y que puedas aplicar cada nuevo detalle
que aprendas. No he incluido nada que no sea básico y necesario para ti, por lo que te aconsejo
que no corras, no te saltes capítulos y sigas el orden del libro.
¡Ah! De vez en cuando verás unas anotaciones en recuadros grises, son pequeñas pistas que te
he ido dejando por si quieres investigar más algunos temas, si tu curiosidad te lo pide o
simplemente lo que te enseño te sabe a poco. También puedes dejar esos recuadros para más
adelante… o incluso no leerlos nunca: aquí mandas tú.

Sólo dos consejos más:


Si esto te gusta, ten paciencia. No seas demasiado exigente contigo misma/o, nadie nace
sabiendo. Date las oportunidades que necesites.

Si esto no te gusta, abandona el libro sin remordimientos. Incluso para las personas más jóvenes
la vida es demasiado corta como para perseguir trenes en los que uno no quiere montarse.

¡Buen viaje!
TABLA DE CONTENIDOS
INTRO (PARA TUTORES Y TUTORAS)
INTRO (PARA APRENDICES)
¿QUÉ VAMOS A NECESITAR?
PROGRAMAS Y COMPONENTES QUE VAS A NECESITAR
0. ESA MAGIA OSCURA A LA QUE LLAMAN PROGRAMAR...
ESCRIBIENDO MAGIA: LOS ALGORITMOS
1. EL LIBRO DE LOS HECHIZOS
HELLO, WORLD!
NUESTRA PRIMERA PRÁCTICA
2. UN TESORO VARIABLE
¿QUÉ ES UNA VARIABLE?
UNA PEQUEÑA PRÁCTICA: IMPRIMIR VARIABLES
¡OPERADORES!
LA HUCHA ELECTRÓNICA
ANEXO: OTRAS COSAS QUE PUEDES HACER CON STRINGS
2. MUCHOS CAMINOS DISTINTOS
ESTRUCTURAS DE CONTROL DE FLUJO
IF - THEN
PERFECCIONAMOS LA HUCHA ELECTRÓNICA
IF - THEN -ELSE
VOLVEMOS A MODERNIZAR NUESTRA HUCHA
LA SENTENCIA SWITCH
BLINDANDO NUESTRA HUCHA
4. UN JUEGO DE NIÑOS
PERO ¿QUÉ ES UN BUCLE?
WHILE
DO-WHILE
FOR
JUEGO: PIEDRA, PAPEL, TIJERAS
5. SIGUIENDO EL RASTRO
ALGUNOS CONCEPTOS PREVIOS SOBRE ARCHIVOS
LA CLASE FILE
TRY/CATCH
LA CLASE SCANNER (OTRA VEZ)
UN PAR DE EXPERIMENTOS
LA CLASE PRINTSTREAM
NUESTRA HUCHA ELECTRÓNICA RECUERDA LOS CAMBIOS
PRÁCTICA FINAL: EL DOCUMENTO SECRETO
6. ¿POR DÓNDE SEGUIR?
DRY (DON’T REPEAT YOURSELF)
YAGNI (YOU AREN’T GONNA NEED IT)
LA REGLA DEL BOY SCOUT
NO TE LANCES SOBRE EL TECLADO
TESTEA SIEMPRE
¿Qué vamos a necesitar?

Para llevar a cabo los ejercicios prácticos que se proponen en este libro necesitaremos un
ordenador. Puedes trabajar con un sistema operativo basado en Linux, como Ubuntu (eso sería
fantástico), o con Windows o MacOS en cualquiera de sus versiones.

La conexión a internet también te será muy útil.

Programas y componentes que vas a necesitar


JDK, o Kit de Desarrollo de JavaTM. Para poder ejecutar nuestras creaciones necesitaremos
que nuestro equipo pueda interpretar el lenguaje Java.
Podemos descargarlo gratis desde el sitio web de Oracle.com, en su sección de descargas.
Recuerda buscar el kit Java SE Development Kit 8, pues es la versión más reciente de Java y en
la que he basado este libro.

Recuerda verificar que bajas el kit adecuado a tu SO (Windows, Mac…) y procesador (X86 o
X64). Si no sabes qué tipo de procesador tienes, puedes verlo en tu equipo, en la sección de info
sobre la máquina (que se llamará Sistema, MiPC, About this Mac o algo similar).
Cuando hayas descargado el JDK deberás configurar tu variable de entorno. Este proceso es
distinto en cada sistema operativo, pero muy sencillo. Te recomiendo guiarte por los pasos que
encontrarás en la propia página de Oracle: https://www.java.com/es/download/help/path.xml

Editor de texto. Para los ejercicios que haremos al principio prefiero que uses un editor de texto
lo más sencillo posible. Algunos editores potentes y gratuitos son Notepad++, Atom o Vim. Yo
voy a usar el primero para mis ejemplos.
Puedes descargar Notepad++ desde https://notepad-plus-plus.org/

Consola de línea de comandos. En el caso de Windows dispondrás de la aplicación conocida


como Símbolo del sistema, en caso de Ubuntu y Mac tendrás la Terminal. Sería muy
recomendable familiarizarse con la forma de moverse entre directorios, ver los archivos que
contienen, etc. Una búsqueda rápida en la Wikipedia nos mostrará los comandos básicos que
podemos necesitar.

No necesitarás un IDE o software de desarrollo especial. Las actividades de este libro se han
diseñado para que se puedan completar sólo con el editor de texto.
0. Esa magia oscura a la que llaman
programar...

Me temo que, antes de ponernos manos a la obra, hay una serie de cosas que necesitas saber
sobre tu ordenador y el modo en que funciona. Programar es como hablarle al ordenador, y si
no sabemos cómo piensa nos costará mucho hacer que nos escuche.

Como tal vez ya sepas, un programa es un guion de órdenes en el que se basa tu ordenador
para realizar una serie de acciones. El problema aquí es que el ordenador no habla nuestro
idioma, sino uno al que llamamos “código máquina”, y que, para hacerlo más complicado, es
distinto en cada tipo de procesador. Este lenguaje se basa en números que expresan tipos de
operaciones, valores y otros datos y que listan cada acción por insignificante que parezca.
Como programar en código máquina sería terriblemente lento y complicado, tenemos otros
lenguajes diseñados para ser usados por las personas -como Java, el que aprenderemos en
este libro- que, cuando ejecutas el programa, son traducidos a código que tu procesador puede
entender. Sí, por confuso que nos parezca un pequeño pedazo de código en lenguaje Java, lo
cierto es que ésa no es más que una versión del lenguaje “fácil” para humanos… y esa traducción
de la que te hablaba la realiza un programa llamado compilador o intérprete.

Cuando compilamos el código que hemos escrito, el compilador lee nuestras instrucciones,
comprueba que las hemos escrito correctamente -aunque puedan ser órdenes equivocadas- y, si
es así, las traduce a un lenguaje que nuestra máquina comprende. Si las hemos escrito mal no
compilará el programa y nos avisará del error… no te lo tomes a mal, esto les ocurre a diario a
las y los programadores más expertos del mundo.
Escribiendo magia: los algoritmos
Bueno, ahora ya sabemos que para programar usamos un lenguaje diseñado para que nos resulte
cómodo a los humanos, y que luego lo enviamos a traducir para que el procesador lo entienda.

Pero ¿cómo organizamos esta serie de órdenes?


El ordenador es terriblemente literal: no hará nada que no le ordenemos, y llevará a cabo
todo lo que se le mande siempre que sea posible. Siempre necesitará que le digamos qué,
cómo, cuándo y en qué orden, e incluso qué esperamos de él en caso de que algo no pueda
hacerse.
Para poder expresar todo esto de una manera ordenada y clara necesitamos tener un método de
trabajo, una disciplina en nuestra forma de detallar las órdenes. Y aquí entran en juego los
algoritmos. Dice la Wikipedia -y no seré yo quien le lleve la contraria- que un algoritmo es un
conjunto prescrito de instrucciones o reglas bien definidas, ordenadas y finitas que permite
llevar a cabo una actividad mediante pasos sucesivos que no generen dudas a quien deba
hacer dicha actividad. Nos lo podemos imaginar como la secuencia de instrucciones que le
daríamos a alguien que tiene que hacer algo muy concreto, pero no tiene ni idea de cómo.

Un ejemplo de algoritmo que podríamos escribir para alguien que no sabe cómo regar un
geranio:

1. Coger la regadera
2. Situarla bajo el grifo
3. Abrir la maneta del grifo hasta que salga agua
4. Mantenerla abierta hasta que hayan 500ml en la regadera
5. Cerrar la maneta hasta que deje de salir agua
6. Llevar la regadera al jardín
7. Localizar el geranio
8. Inclinar la regadera sobre el geranio, mantenerla así hasta que haya salido toda el agua
9. Guardar la regadera

Como ves, hay varios detalles muy importantes para cada orden que hemos dado a nuestro
aprendiz de jardinero:
El orden en que hacer las acciones
Cuándo termina cada acción
Qué hacer al terminar de regar

Si no le indicásemos el orden, podría regar primero y llenar la regadera después... y la planta


moriría de sed. Si no le dijéramos cuándo cerrar el grifo, nuestro amigo sería capaz de inundar la
casa. Y si no le avisamos de que al final debe guardar la regadera, capaz es de quedarse con ella
colgando sobre el geranio para el resto de la eternidad. Así de literal es nuestro amigo, justo igual
que un ordenador, y por eso los algoritmos deben ser exactos, ordenados y tener fin.

Y ésta es toda la teoría previa que necesitabas conocer antes de empezar a teclear. ¡Hurra!

EJERCICIOS
Ahora te propongo unos ejercicios muy sencillos, para asegurarnos de que no hayas entendido
algo mal. No queremos matar de sed los geranios ;)

(tienes las soluciones a continuación, pero ¡no las mires antes de tiempo!)

UN PEQUEÑO TEST
1. El procesador puede ejecutar tu código escrito en Java
a) Por supuesto
b) Ni hablar

2. Un algoritmo es…
a) Un código diseñado para que el procesador lo entienda
b) Una secuencia de órdenes concretas, exactas y finitas

3. Para poder comprender el lenguaje en el que escribes, tu ordenador necesita las


traducciones de un...
a) Procesador
b) Intérprete
EVITANDO EL DESASTRE
Este algoritmo contiene algunos errores que nos pueden llevar al desastre. ¿Podrías
señalarlos y corregirlo?

Instrucciones para cocinar patatas fritas:

1. Preparar las patatas necesarias


2. Coger un cuchillo para pelar
3. Empezar a pelar patatas
4. Poner la sartén en el fogón
5. Encender el fuego a media potencia
6. Verter aceite en la sartén
7. Echar las patatas a la sartén
8. Freír las patatas
9. Sacar las patatas de la sartén y ponerlas en un plato

Prácticas extra, para estudiantes aplicados…


ESCRIBE TU PROPIO ALGORITMO
Crea las secuencias de órdenes para facilitar instrucciones a un ordenador imaginario. Te
propongo algunas ideas:

Planchar una camisa


Enviar una carta por correo
Lavarse los dientes
Hacerse una trenza a un lado de la cabeza
Atarse los zapatos
Hinchar un globo
SOLUCIONES
Soluciones del test:
1-b
2-b
3-b
Errores del algoritmo:
Instrucciones para cocinar patatas fritas

1. Preparar las patatas necesarias


2. Coger un cuchillo para pelar
3. Empezar a pelar patatas hasta que estén todas peladas
4. Cortar las patatas en rodajas de 1 cm de grosor (no querrás freírlas enteras)
5. Poner la sartén en el fogón
6. Encender el fuego a media potencia
7. Verter 100ml de aceite en la sartén (no queremos quedarnos para siempre con la botella
en la mano…)
8. Cuando el aceite esté caliente Echar las patatas a la sartén
9. Freír las patatas hasta que estén doradas/durante x minutos
10. Sacar las patatas de la sartén y ponerlas en un plato
11. Apagar el fogón

Obviamente esto es una simulación y no un programa real (aunque podríamos estar programando
el software de un robot cocinero), pero como puedes ver es vital concretar siempre en qué orden
realizar las acciones y cuándo parar, de lo contrario podemos eternizar algunas (esto lo veremos
más adelante).
1. El libro de los hechizos

Ahora ya sabemos que para programar usamos un lenguaje especial, diseñado para
humanos, y que con él escribimos algoritmos, secuencias con los pasos que deseamos que el
procesador dé.

Pero, ¿cómo es en detalle ese proceso cuando se trata de un programa real? En este capítulo
por fin lo veremos, y además para cuando llegues al final escribirás tu propio programa.
Como sabes, este libro se basa en el lenguaje Java para nuestro aprendizaje. Pues bien, para
ejecutar -hacer funcionar- un programa Java en tu ordenador, necesitas tres ingredientes:

Un editor de texto para escribir nuestro código. Nada especial, te sirve uno gratuito
como los que tienes recomendados en la sección “¿Qué vamos a necesitar?”
Un compilador de Java, que genera lo que llamamos bytecode
El intérprete que hará posible que nuestro procesador particular entienda lo que hemos
escrito
Para el nivel al que vamos a llegar en este capítulo, un programa Java no es más que una serie de
código creado en el editor de texto y guardado con la extensión .java -para que nuestro ordenador
sepa que debe procesar su contenido como código Java.
Pero vayamos al meollo de la cuestión. ¿Cómo hacemos para escribir órdenes válidas? ¿Escribo
cualquier cosa y rezo para que me entiendan, basta con que esté en inglés?

Pues no. Como toda buena magia, la programación se basa en librerías y libros llenos de
sortilegios que alguien escribió mucho antes que nosotros, y que aplicados correctamente
sobre un objeto generan un encantamiento concreto.

Cuando descargamos el JDK que mencionaba en la sección “Qué vamos a necesitar”, sin saberlo
nos trajimos todas las librerías de sortilegios y hechizos que componen Java, y cuando
escribimos nuestro programa lo que hacemos es irlos invocando según ciertas reglas. Una de
ellas, no la olvides, es que a los hechizos les vamos a llamar métodos y a los libros, clases.
Cuando empecemos a programar (sólo tardaremos un par de páginas más, ya verás) lo que
haremos será llamar a las clases que queremos usar, para que nos escuchen… y así poder
invocar sus métodos y que afecten a todo lo que queremos manejar.

Hello, World!
“Hola, Mundo” son tradicionalmente las primeras palabras que uno escribe cuando se estrena en
la programación, y nosotros no vamos a ser menos.
A continuación, tenemos un ejemplo de un programa, el primero que vamos a analizar y
comprender.
→ FÍJATE: este tipo de letra aparecerá en el libro cada vez que quiera indicarte que el
texto es código Java.

Lo primero que leemos es “public class”. Esto lo escribimos al principio del documento, para
que cuando lo lea el compilador sepa que a partir de ahí todo lo que va a leer es una clase. Y
además le damos un nombre a la clase, en este caso “HolaMundo”.
Lo siguiente que leemos es “public static void main…” esto lo escribimos siempre como
encabezamiento de nuestra clase principal (es como una contraseña que abre el conjuro).

Después tenemos una anotación que empieza con dos barras (//). A esto se le llaman
comentarios. ¡Las barras son como un hechizo de invisibilidad! Si las pones delante de una
frase el programa se ejecuta sin leerlas, lo cual es muy útil. Puedes usar los comentarios para
escribir cosas que necesites recordar luego, que aclaran qué hace el siguiente pedazo de código
etc. sin molestar al compilador.
Y aún hay más: para una sola línea puedes escribir las dos barras, pero si quieres hacer un
párrafo entero puedes usar una coraza de invisibilidad, /*así */, y el programa pasará por
encima sin leerlas.

//esto sería un comentario de una línea

/*y esto sería todo un bloque


de líneas
que el programa pasa por alto
por estar metidas en su fantástica coraza*/

Y, por último, tenemos la magia en sí. Hemos usado un conjuro que se llama System.println y
que tiene la habilidad de hacer que tu ordenador escriba cosas en la pantalla. En concreto,
las cosas que le pongas entre paréntesis (a eso le llamamos parámetro).
Escribimos el método con esta estructura:

método (“material para el método”) ;

Es decir, siempre:
- el método delante,
- y a continuación en una nube de humo (bueno, un paréntesis y comillas) el texto que queremos
embrujar para que se nos aparezca.
Y lo sellamos todo con un punto y coma.

Ahora vuelve a mirar el programa, ¿verdad que ya no parece un galimatías? Ahora tiene sentido:
Abro el libro de conjuros (la clase), anuncio que voy a empezar a hacer magia (método main) y
ya puedo empezar a lanzar hechizos (método System.println).

public class HolaMundo {

public static void main(String[] args) {


// Muestra el texto en una pantalla
System.out.println("Hola, Mundo");
}
}

{ Y, para que quede claro que cada pieza de código está contenida en otra, las rodeamos con

estas llaves {}. No las olvides, o el compilador se quejará, ya que no sabrá qué es cada cosa y

dónde parar de leer... }

Nuestra primera práctica

Ahora escribiremos nuestro primer programa.


Sigue los pasos con mucha atención:

1. Abre un editor de texto y copia el programa que hemos analizado. Quizá te apetezca
intentar copiarlo de memoria y luego ver qué te has olvidado y añadirlo.
2. Guarda el archivo. No te olvides de nombrarlo igual que el programa, según las
CurvasDelCamello, y ponerle extensión .java. Cierra el archivo.
3. Ahora vamos a compilar nuestro programa. Desde el terminal (si no sabes cómo hacerlo
busca la información que encontrarás en el capítulo Qué vamos a necesitar) escribimos
javac y el nombre de tu programa, con su extensión:
javac HolaMundo.java
Automáticamente el compilador crea un nuevo archivo llamado HolaMundo.class, ése
es el que ejecutaremos. Si todo ha ido bien no verás ningún mensaje.
4. Ejecutamos el programa, escribiendo java y el nombre del programa -esta vez sin
extensión:
java HolaMundo

¡Eureka! nuestro programa se ejecuta y gracias a nuestro hechizo la ventana de la terminal


muestra nuestro primer mensaje al mundo.

¿Algo no ha funcionado? Si al tratar de compilar aparece algún mensaje de error revisa los
siguientes detalles:
- Que coincidan el nombre de la clase y el del archivo
- Que hayas copiado exactamente el código
- Que hayas escrito la extensión para compilar
No te preocupes si no funciona a la primera… con un poco de mimo y calma, siguiendo de
nuevo las instrucciones paso a paso tiene que funcionar.
EJERCICIO
Partiendo del programa que hemos creado hace un momento, intenta crear las siguientes
modificaciones:

Un programa que en lugar de “Hola, Mundo” diga “Hasta luego, cocodrilo”


Un programa que diga “Hola, Mundo” y después “Hace un buen día”

Realiza los siguientes experimentos:

Incluir más de un mensaje entrecomillado, dentro del mismo paréntesis


Añadir o quitar llaves ({})
Añadir o quitar el caracter “;”
Hacer que no coincida el nombre del archivo con el nombre del programa (que indicas
en el método main)
¿Qué ocurre cuando realizas cada uno de esos cambios? ¿Qué mensajes te da el compilador? ¿Es
posible ejecutarlo?

SOLUCIONES

Para modificar el texto que se muestra por la pantalla sólo tienes que modificar lo que
escribiste entre las comillas. No olvides ponerlas ;)
Para escribir dos mensajes, puedes repetir el método:
System.out.println(“Hola, Mundo”);
System.out.println(“Hace un buen día”);
o poner los dos mensajes seguidos
System.out.println(“Hola, Mundo”, “Hace un buen día);
System.out.println(“Hola, Mundo Hace un buen día);
Aunque eso no queda tan bien, ya que nos lo escribe de golpe.

Hay otras formas de hacerlo (más adelante las aprenderás).

Por el momento, con este ejercicio comprobamos que puedes escribir todos los métodos que
necesites en la misma clase, dentro de las llaves del método main, o incluso indicar varios
parámetros (varios mensajes entre comillas) al método System.out.println.
2. Un tesoro variable
Ahora que ya sabemos algunas cosas sobre cómo se organiza un programa y la manera de usar
los hechizos, es hora de conocer un nuevo elemento importantísimo: las variables.

En este capítulo aprenderemos qué son, cuántos tipos existen y cómo empezar a manejarlas
mediante nuestros programas.

¿Qué es una variable?


Los manuales de programación nos dicen que una variable es un espacio en la memoria del
ordenador, donde guardamos un valor que hemos asignado a la misma. Existen diferentes
tipos de variables según el tipo de información que guardemos en ellas.

Pero como esto suena un poco denso, en este capítulo -como magos que somos- vamos a trabajar
con un tesoro que hemos creado mágicamente.
Nuestro tesoro está guardado en un enorme arcón, que sería como la memoria de un ordenador, y
custodia un montón de datos de todos los tipos y formas, y que tienen muuucho valor.
En nuestro pequeño inventario tenemos varios tipos de elementos, que usamos según la ocasión.
Los que más abundan son:

char - los chars son pequeñas gemas preciosas. Si las miras a contraluz, cada una esconde
un caracter (un signo, número o letra) en su interior, entre comillas simples.

int - los ints son monedas de oro, cada uno tiene un valor numérico, que puede ir desde
muy por debajo de cero hasta … bueno, un número altísimo y difícil de imaginar

double/ float - como las monedas siempre son un valor redondo a veces necesitamos
extender un cheque para pagar, por ejemplo, 25,75€. Los doubles y floats son eso, cifras que
contienen comas.

strings- “string” significa cuerda en inglés. Realmente los strings no son más que
collares que hemos engarzado entre comillas dobles para mantener juntos y en orden algunos
grupos de chars que no queremos tener sueltos, sería una lástima que se nos desperdigasen por
el arcón

bool - los booleanos no son un tesoro en sí, pero nos ayudan a mantenerlo. Son unos
pequeños candados que sólo tienen dos valores: cierto o falso (abierto o cerrado). Quizá ahora te
preguntes qué utilidad tienen, en el futuro lo irás descubriendo.

Bien, ahora que sabemos todo esto, volvemos a la carga. ¿Qué es una variable? Es un espacio
único en nuestro arcón (de hecho, le pondremos un nombre), de uno de los tipos anteriores, y
con un valor concreto. Algunos ejemplos de variables de nuestro tesoro podrían ser:

Un char llamado inicial, con valor ‘i’


Un int llamado paga, con valor 1500
Un double, o un float, llamado precio, con valor 1,45
Un string llamado saludo, con valor “Hola”
Un booleano llamado abierto con valor “true”

Cuando escribimos el programa podemos crear tantas variables como necesitemos. Las
podemos crear (o declarar, como dicen los expertos) al principio del programa, para que se
generen en cuanto lo ejecutemos, o en los métodos, para que vayan apareciendo sobre la marcha.
Verás que hay un montón de operaciones que podemos hacer con nuestras variables, incluso
sabiendo muy poquito.

Podemos realizar operaciones matemáticas con los ints y los doubles, podemos desordenar,
recortar y cortar las strings, podemos hacer que el programa tome decisiones usando
booleanos… tu imaginación es el límite.
La forma más correcta de crear una variable es con el esquema tipo - nombre - valor. Así
declaramos e inicializamos las variables que hemos escrito arriba :
char inicial = ‘i’;
int paga = 1500;
float precio = 1.45;
String saludo = “Hola”;
bool abierto = true;

→ Fíjate bien! Escribimos el valor del char entre comillas simples y el del string entre comillas
dobles.

Una pequeña práctica: imprimir variables


Vamos a partir otra vez del programa HolaMundo que hicimos en el capítulo anterior. Esta vez
en lugar de decirle exactamente qué texto queremos imprimir, le diremos el nombre de la
variable y nos mostrará su valor.

Copia este programa, compílalo y ejecuta:

Como puedes ver, al haber inicializado las variables previamente, podemos dar el nombre
de las mismas a nuestro método y él sabrá qué mostrar.
Pero, ¿qué ha pasado en la línea 15? Fíjate bien en lo que muestra tu programa… ha
multiplicado el valor de la variable precio (100) por el número que le hemos indicado, y ha
mostrado el resultado. ¿Por qué se ha comportado así?

¡Operadores!
¡Enhorabuena! Has descubierto los operadores: símbolos mágicos que realizan operaciones
sobre nuestras variables.

Existen de muchos tipos, por ejemplo los aritméticos, que puedes usar para manipular variables
de tipo numérico (int, float, double…): +, -, *, /… y que básicamente hacen operaciones
matemáticas. Estos no puedes usarlos con variables no numéricas (salvo el símbolo +, que
puede usarse para concatenar strings).

Usar estos símbolos mágicos es muy sencillo, sólo tienes que saber cuál es la función de cada
uno. Para eso tienes este manual de instrucciones, que podrás consultar siempre que necesites
invocarlos. Recuerda que NO necesitas memorizar esta tabla, no estamos aquí para repetir las
cosas como loros… ;) Con el tiempo y la práctica irás recordándolos sin ayuda.
= Operador simple de asignación

Operadores Aritméticos

+ Suma

- Resta

* Multiplica

/ Divide

% Nos da el resto en una división. Por ejemplo, 7


%5=2

Operadores Unarios

+ Positivo (por ejemplo una temperatura)

- Negativo

++ Suma 1 a un valor

-- Resta 1 a un valor

! Invierte el valor de un booleano (de true a false,


o viceversa)

Operadores de igualdad y relacionales

== “igual que”, por ejemplo: 5 == 5

!= “distinto que”, por ejemplo: 3 != 4

> mayor que

>= mayor o igual que

< menor que

<= menor o igual que

Operadores condicionales

&& Y, por ejemplo: “lunes && martes” significa”


los dos”

|| O, por ejemplo: “lunes || martes” significa” uno


de ambos”

?: ternaria. La incluimos pero no la usarás en este


libro

Operador de comparación de tipo

instanceof “de cierto tipo”. Por ejemplo, “5.6 instanceof


Double” sería = true

Ahora veamos un par de ejemplos de cómo usar estos operadores. ¿Te atreves a adivinar qué
mostrarán en pantalla estos programas?
Si compilas y ejecutas verás que, usando los operadores + y -, podemos realizar sumas, restas o
concatenar frases.

Y además, podemos usar los operadores para cambiar el valor de una variable, como hemos
hecho en el ejemplo de arriba al inicializar la variable sumaEdades .
En este caso la hemos inicializado como la suma del valor de otras dos, pero podríamos haber
hecho cualquier otro cálculo. Por ejemplo, aquí estamos inicializando una nueva variable,
indicando que el valor será el resultado de dividir las otras dos:

int sumaEdades = edadPadre / edadMadre;

o incluso usar una igualdad:

int sumaEdades = edadPadre;

que significa que se creará sumaEdades con el mismo valor que edadPadres tenga en ese
momento…
(Por si acaso te lo has preguntado, aunque edadPadre cambie más tarde de valor, sumaPadres no
lo hará, ya que, aunque al crearse haya mirado el valor que tiene para copiarlo, son espacios de
memoria distintos. Del mismo modo que si hoy me hago una foto y mañana cambio de peinado,
la foto no cambia conmigo).
Todo esto de igualar variables, sumarlas, restarlas... lo podemos hacer porque son del mismo
tipo. Si pruebas a escribir:

String a = edadPadre;

tendrás un error de compilación, porque no puedes darle a una String el valor que tenías
guardado en un int… como ya sabes, no son el mismo tipo de joya, así que no encajan.
Retos con variables y operadores
Vamos a atrevernos con algunos retos avanzados. Para eso, usaremos nuevos métodos que hasta
ahora no conocíamos.
Vamos a conocer la clase Scanner (recuerda, una clase era como un libro de conjuros de la
misma temática) que contiene el método Scanner. Este poderoso método nos da la oportunidad
de hablarle al programa desde el teclado, mientras se está ejecutando.

Para usar esa clase, primero tenemos que añadirla a nuestro programa, decirle que vamos a usar
ese libro. Y eso se hace añadiendo esta indicación al principio del programa:

import java.util.Scanner;

Una vez hemos importado la clase, ya podemos invocar sus métodos. Como si nos hubiésemos
traído el libro de la estantería para poder ir leyendo en él los conjuros necesarios.

Para usar el Scanner, seguimos estos pasos:

Abrimos un nuevo Scanner, y le ponemos un nombre, el que queramos:


Scanner Jaimito = new Scanner(System.in);
(Fíjate: un nuevo Scanner, llamado Jaimito, que lee de System.in o lo que es lo mismo,
el teclado del usuario dentro de paréntesis, a modo de parámetro).

Creamos una variable del tipo que necesitemos. Al inicializarla, le decimos que su
valor será igual a lo que escribamos en el teclado. Se hace así:
int i = Jaimito.nextInt();

(Como hemos creado un int, el programa esperará que introduzca un número sin decimales.
Fíjate que usamos el método como aprendimos lecciones atrás con el método println: nombre del
método-punto-parámetro. O lo que es lo mismo, Jaimito-punto-el siguiente Int que entre por el
teclado).

Y ya está todo listo para que escribamos. El programa capturará lo que hayamos tecleado y lo
guardará en el arcón de memoria, a modo de valor de una de nuestras joyas, una variable.

La hucha electrónica
Vamos a diseñar un programa que simula ser una hucha. El programa tiene estas funciones:
Recibir dinero
Contar el dinero
Indicar el saldo

1- Escribe el algoritmo que describe el proceso de uso de la hucha. No hay una única respuesta
correcta, existen muchas formas de hacerlo.

2. Asocia las siguientes acciones al método o herramienta que podrías usar para que se
realicen:

3. El ejercicio anterior, una vez solucionado, nos da una pista de cómo podría ser el código
de nuestro programa.
Intenta escribir el código, no pasa nada si no compila. ¡Es un ejercicio de ingeniería!
Después consulta la solución propuesta (recuerda, no hay solo una) y haz los retoques necesarios
hasta que el programa compile.

4. Juega con tu nuevo programa. Intenta hacer que falle. Intenta introducir cantidades en
negativo, ¿qué ocurre?

ACTIVIDAD OPCIONAL: SÓLO PARA ALUMNOS MUY AVANZADOS

¿Sabrías modificar tu programa para que pueda aceptar cantidades con decimales? Es
decir, que puedas guardar en tu hucha cheques además de monedas.
¿Sabrías modificar tu programa para que acepte variables de tipo String? Así podrás
guardar también collares en tu hucha.
PISTA: el apartado “otras formas de invocar al Scanner” podría tener la herramienta que
necesitas.
SOLUCIONES
1. Algoritmo.
No existe una única respuesta correcta, pero aquí tienes una propuesta de solución:

Se inicia el programa
Se muestra el total de dinero ahorrado por pantalla
Se solicita al usuario qué cantidad quiere echar en la hucha
El usuario indica la cantidad
Se añade el valor al que ya había en la hucha
Se muestra por pantalla el nuevo ahorro total

2. Recibir dinero - Scanner


Mostrar saldo - System.out.println
Contar el dinero - Operadores aritméticos
Indicar la cantidad - Teclado del usuario

3. Una posible forma de escribir el código y que funcione (el total ahorrado inicial puede ser
cero, o cualquier otra cantidad):

Si lo ejecutas verás que el programa hace lo siguiente:


1. Indica el total inicial
2. Solicita cuánto vas a ingresar
3. Espera hasta que tecleas una cantidad y pulsas Enter
4. Te muestra el nuevo total
Podíamos haber hecho lo mismo de otras maneras. Si te apetece, piensa en ello e intenta razonar
cuál sería la más útil.

4. Para adaptar tu hucha para recibir collares o cheques, sólo tienes que crear otras variables
y usar el mismo scanner tantas veces como quieras meter cosas.
Prueba con este fragmento de código (añádelo a tu programa dentro del método main):
ANEXO: Otras cosas que puedes hacer con strings
Como ya has visto, las Strings son una forma de “hablar” con el usuario. A menudo nos gusta
decorar un poco más su aspecto para que nuestro programa parezca más profesional. Por eso aquí
te dejo algunos trucos que puedes usar para manipular Strings, crear mensajes más complejos o
procesar los mensajes que el usuario teclee. Puedes jugar con ellos ahora o en las prácticas que
iremos haciendo a lo largo del libro.

Calcular la longitud de una String con String.lenght:


public static void main(String args[]) {
String collar = "Un collar de 76 perlas";
int longitud = collar.length();
System.out.println( "La longitud de esta String es de : " + longitud );
}

Concatenar Strings
Podemos mostrar varias Strings seguidas en un mensaje, como ya hemos hecho, usando el signo
“+”.

También podemos usar el método String.concat para concatenar los literales:


"Yo vivo en ".concat("Barcelona");
O concatenando las variables directamente:
String 1 = “Yo vivo en”;
String 2 = “Barcelona”;
1.concat(2);
Esto es así porque concat es un método que acepta como parámetro tanto variables como texto
entrecomillado.

Comparar Strings
Con el método compareTo puedes comparar dos Strings (usando la variable o directamente el
texto entre comillas) para saber si son idénticas. Obtenemos el resultado en una variable de tipo
int. Ésta valdrá 0 si son iguales, y una cifra positiva o negativa si son distintas.
Un ejemplo de uso:
public static void main(String args[]) {
String 1 = "Buenos días.";
String 2 = “Buenos días.”;
int result = 1.compareTo( 2 );
System.out.println("El resultado de la comparación es: "+result);
}

(Y usando el método compareToIgnoreCase puedes comparar Strings sin tener en cuenta


mayúsculas y minúsculas).

Reemplazar caracteres
¡Puedes reemplazar una letra concreta por otra para “esconder” cosas que has escrito, por
ejemplo… como una especie de clave! :)
public static void main(String args[]) {
String mensaje = new String(“Mi mensajito secreto”);
System.out.println(mensaje.replace('e', 'r'));

Para obtener un mensaje “escondido” así: “Mi mrnsajito srcrrto”).


Puedes cifrar tantos caracteres como quieras, y descifrar después otra vez.

Puedes encontrar más propuestas para manipular Strings en los tutoriales oficiales de
Oracle para Java 8:
https://docs.oracle.com/javase/tutorial/java/data/strings.html
2. Muchos caminos distintos
En los capítulos anteriores hemos aprendido los básicos de la programación: qué son los métodos
y las clases, qué son las variables -y qué tipos existen- e incluso a usar operadores para jugar con
ellas.

Pero cuando empezamos a tener ideas que queremos llevar a la realidad lo anterior se nos queda
corto. Los programas que hemos escrito hasta ahora sólo saben hacer la misma secuencia
una y otra vez… y en algunas ocasiones necesitamos que piensen un poquito más.

¿Sería posible que nuestro programa Hucha nos preguntase primero qué tipo de valor queremos
guardar para que sepa qué tipo de variable crear? ¿Que nos responda con un aviso si nos
equivocamos al escribir el dato, y podamos volver a introducirlo?

Por supuesto ¡es posible! (yo todavía no he encontrado nada imposible de programar… sólo
cosas que aún no sé hacer).

Estructuras de control de flujo


Para que nuestro programa pueda tomar decisiones sobre qué hacer en algunos casos, lo que
hacemos es prevenirlas y utilizar lo que llamamos estructuras de decisión, o de control de flujo.

Existen 3 tipos de estructuras de decisión:

IF IF - ELSE SWITCH CASE


Para entender cómo funcionan estas estructuras podemos imaginar nuestro programa como si
fuese un circuito mágico que alimenta un panel luminoso. Nuestro circuito está lleno de
caminos por los que corre la electricidad, algunos tienen interruptores abiertos y otros
cerrados y por eso la corriente mágica sólo llegará a las bombillas que están detrás de
interruptores en posición ON.
Cuando encendemos el interruptor principal, se genera el flujo de corriente. Cuando ésta pasa por
cada uno de los interruptores comprueba su estado para DECIDIR si debe alcanzar la bombilla
correspondiente. Si está en OFF, pasará de largo al siguiente interruptor.

IF - THEN
Entonces, podemos entender fácilmente que la sentencia “if” (“si”, en inglés) nos sirve para
realizar una comparación, para que el programa se haga una pregunta.
Para componer este tipo de instrucciones además usaremos los operadores condicionales que
tienes en la tabla de Operadores que hemos visto unas páginas atrás.
Por ejemplo, en nuestro programa Hucha, que ya habíamos visto, podemos añadir una norma que
diga que sólo aceptaremos ingresos que aumenten nuestro ahorro, no que lo disminuyan. Para
ello, en el punto en que antes hacíamos la suma, escribimos esto:
//crea una variable en la que guardar la cantidad a ingresar
int ingreso = miScanner.nextInt();
totalAhorrado = ingreso + totalAhorrado;

ahora podríamos escribir:


//crea una variable en la que guardar la cantidad a ingresar
int ingreso = miScanner.nextInt();
if (ingreso > 0) {
totalAhorrado = ingreso + totalAhorrado;
}

Fíjate: Con el operador “>” (mayor que) estamos diciendo que SI la cantidad ingresada es
mayor que 0, entonces puede entrar al bloque de código entre llaves y ejecutar la suma. SI la
cantidad ingresada es 0 o negativa, entonces el programa se saltará el bloque entre llaves y pasará
a la siguiente instrucción.

La forma de usar la sentencia IF es, por lo tanto:


IF ( elementos a comparar) { bloque a ejecutar si se cumple la condición ;}

Podríamos haber usado cualquiera de los otros operadores que ya conocemos para poner otras
normas:
Admitir solo ingresos superiores a 5
Admitir ingresos solo si tenemos menos de 100 ahorrados (en este caso la comparación
sería if totalAhorrado < 100)
Admitir ingresos si tenemos menos de 100 ahorrados, y con el ingreso no los superamos:
if (totalAhorrado<100 && totalAhorrado+ingreso < 100)

Perfeccionamos la hucha electrónica


Adapta tu programa hucha para que incluya estas nuevas normas:

Aceptar sólo ingresos mayores que 0


Aceptar sólo ingresos de cantidades par

Puedes usar los fragmentos de código que tienes más arriba. Lo importante no es que lo escribas
todo de memoria, no importa que tengas que copiarlo… sino que entiendas cómo funciona.

Ahora puedes jugar con tu hucha e intentar ingresar cantidades o conceptos no admitidos.
¿Qué ocurre en cada caso?

IF - THEN -ELSE
Hasta ahora hemos visto que con la instrucción “IF” podemos hacer que el programa efectúe una
acción “SI” una condición se cumple. Y si no se cumple… ¿Qué hacemos? En algunas ocasiones
querremos ir un poco más allá, querremos determinar que si se cumple, se haga A, pero si no se
cumple, se haga B. Es decir, un bloque de código concreto al que sólo se entra si NO se
cumple la instrucción: a este bloque le llamamos ELSE.
Es como nuestro circuito luminoso del ejemplo anterior. Con una instrucción IF podíamos
decirle “si el interruptor está abierto enciende la bombilla”, pero con una instrucción IF- ELSE
le podríamos decir “Si el interruptor está abierto enciende la bombilla, y si no, que suene
una alarma”. Así, en caso de encenderse la bombilla nunca sonará la alarma: el bloque de
código contenido en ELSE sólo se ejecuta si la condición del IF no se cumple.

Veamos un ejemplo en código Java:

int temperaturaNevera = 3;
if (temperaturaNevera => 4) {
System.out.println("¡La temperatura en la nevera es demasiado alta! La”
+ “ temperatura es de "+temperaturaNevera+” grados.”)
} else {
System.out.println("Nevera enfriando correctamente");
}
Este podrá ser un fragmento de un programa que controla una nevera. Como ves, el programa
guardará el valor de la temperatura en una variable. Después evaluará si es superior a 3 grados, y
si es así nos va a alertar de que algo no está como debería. En cambio, si la temperatura es
inferior (es decir, en cualquier otro caso) nos muestra otro mensaje que confirma que está
enfriando como debería.
Si lo pruebas ves que en este caso saldrá el segundo mensaje, y si modificas el valor de
temperaturaNevera a 4 o más se mostrará el primero.

La sintaxis es sencilla, solo necesitas introducir el bloque nuevo a continuación del bloque
IF:

Es decir:

if ( condición a evaluar) {
Acción 1; } else {
Acción 2; }

Cada bloque con sus propias llaves {} y cada acción con su punto y coma.

Y aún hay más: ¡puedes añadir tantos bloques como quieras! Simplemente, del segundo al
penúltimo los nombramos “else if” y les añadimos su propia condición a evaluar. Por
ejemplo, este código nos diría si hemos aprobado el examen justo, con buena nota o si hemos
suspendido:

public class Nota{


public static void main(String []args){

int notaExamen = 8;

if (notaExamen>=8) {
System.out.println("Enhorabuena, has aprobado con nota.");
} else if (notaExamen>= 5) {
System.out.println("Has aprobado el examen.");
} else {
System.out.println("Lo siento, has suspendido el examen.");
}

}
}

Fíjate: Aunque el valor de notaExamen cumple las dos primeras condiciones (por pura lógica, si
es superior a 8 también lo es a 5) una vez el programa evalúa como cierto el primer caso, ejecuta
su bloque y abandona todo el bloque IF - ELSE. No continúa leyendo las siguientes condiciones
por si cumple alguna más.
Otro punto importante: pon atención a la forma en que se han escrito las condiciones. Si
solamente escribieses “mayor que 8”, “mayor que 5” y else, en caso de sacar justamente un 8 o
un 5 el programa te diría que has suspendido. ¡Menudo chasco!

Volvemos a modernizar nuestra hucha


Viendo el ejemplo de arriba, podrías modificar la hucha otra vez. Si añadieras un ELSE al IF que
ya implementaste, cuando el usuario hace un ingreso no admitido podría mostrarse un mensaje
indicándole que se ha equivocado y que el ingreso no se ha realizado.

A nadie le gusta intentar algo, que el ordenador no parezca responder y encima no sea
capaz de decirnos qué ocurre, así que es una MUY buena práctica intentar prever los errores y
acompañar las acciones del usuario si algo no va bien.

¿Ha funcionado la mejora? Si no ha sido así, a la vuelta de esta página tienes una posible
solución.

SOLUCIÓN
A continuación, tienes una posible solución al reto anterior.
Hay otras cosas que podríamos haber hecho, como por ejemplo mover la sentencia

System.out.println("El total ahorrado es " + totalAhorrado);

justo después de la línea 21 para que sólo muestre el total si éste cambia. Recuerda que en la
programación hay tantas maneras de implementar un algoritmo como cabecitas puedan
imaginarlo.

La sentencia SWITCH

Además de las sentencias IF y IF-ELSE, tenemos una tercera herramienta para controlar qué
piezas de código se ejecutan: la sentencia SWITCH.

SWITCH significa interruptor en inglés y lo que hace es exactamente eso: interrumpe el paso a
todas las instrucciones que no concuerden con la condición inicial. Igual que en una red de
tuberías en la que podemos abrir la llave de paso que queremos para llevar el agua por ese
camino, la sentencia switch se basa en una lista de posibles caminos, que el programa tomará
sólo si coinciden con la condición propuesta.

Veamos un ejemplo para entender mejor cómo usarlo.


Ésta es la solución anterior a nuestro programa de la hucha, pero usando una sentencia switch en
lugar de if - else:
//crea una variable en la que guardar la cantidad a ingresar
int ingreso = miScanner.nextInt();

switch (ingreso) {
case 0: System.out.println ("No se ha realizado el ingreso porque el importe debe ser mayor que cero.");
break;
case 1: totalAhorrado = totalAhorrado+ingreso;
break;
case 2: totalAhorrado = totalAhorrado+ingreso;
break;
case 3: totalAhorrado = totalAhorrado+ingreso;
break;
default:
break;
}
//muestra al usuario el total actual
System.out.println("El total ahorrado es " +totalAhorrado);
}
}

Paso a paso:

Iniciamos la sentencia switch, como parámetro indicamos el nombre de la variable


que tiene que comparar con cada caso
Entre llaves, listamos cada uno de los casos a comparar. En el ejemplo hemos listado
para el caso que ingreso valga 0, 1, 2, o 3.
Cada uno de los casos contiene la instrucción a ejecutar.
Tras cada caso, la sentencia “break”, que ordena al programa salir del bloque switch.
Es decir, si coincide con “0” no leerá las instrucciones de los demás.
Opcionalmente, un caso “default” que viene a ser algo así como “ejecuta esto si la
variable tiene un valor que no coincida con ninguno de estos casos”.

Se puede usar un switch case sin default o con el default vacío. Intenta comentar esas líneas con
las barras // y comprueba que compilan ;)

Fíjate: Hemos usado una variable de tipo int para la comparación. La sentencia switch también
puede funcionar para comparar chars, ints e incluso (si estás usando Java 7 o posterior) Strings.
Siempre comprueba que la variable a comparar sea del mismo tipo que la que indicas en cada
case.

Como ves, en este caso no era demasiado buena idea usar una sentencia switch, porque se pide al
usuario que introduzca un número cualquiera. Para tenerlo todo previsto deberíamos programar
un case para cada uno de los enteros que pueden caber en una variable int (-3, -2, -1, 0, 1, 2,
26…) y no acabaríamos nunca.

Si queremos comparar rangos de datos (cifras menores o mayores que) siempre es


mejor utilizar if o if/else.
Si queremos comparar unos pocos casos concretos, encontrando coincidencias exactas,
una sentencia switch puede ser mejor porque el código resultante es más limpio y
legible, y se ejecuta en menos tiempo.
Blindando nuestra hucha

Vamos a utilizar la nueva sentencia aprendida para blindar nuestra hucha frente al uso de
curiosos no autorizados ;)

Usando un switch y el método Scanner, que ya conoces, al iniciarse la hucha pedirá al usuario la
contraseña. Si ésta coincide podrá seguir adelante y ver el saldo.
Si se equivoca, lanzaremos un mensaje al usuario diciendo que la contraseña es incorrecta y que
no está autorizado para ver el saldo.

1. Escribe el algoritmo de la hucha que incluya iniciarse, pedir la contraseña, validarla, etc.
Es importante hacer este paso para tener claro el diseño y lo que tenemos que programar
después.
2. Intenta escribir el código para incluir la nueva funcionalidad. Recuerda que este nuevo
bloque debería ir antes de la parte en la que se hace el ingreso, y que la contraseña
deberá estar previamente guardada para que pueda compararla :)

SOLUCIÓN
No me canso de repetirlo: UNA de las innumerables soluciones posibles al reto.
import java.util.Scanner;

public class MiHucha {

public static void main (String []args){


String contrasena;
int totalAhorrado = 0;
String pideContrasena = "Introduce tu clave para poder operar y pulsa Enter";
String contrasenaOK = "::::Bienvenido a tu hucha securizada.:::";
String total = " >>> El total ahorrado es ";
String gracias = "::: Gracias por usar la hucha electrónica. :::";
String KO = "Contraseña incorrecta. No estás autorizado a usar esta hucha.";

Scanner miScanner = new Scanner(System.in); //abre nuevo Scanner


System.out.println(pideContrasena); //pide la contraseña
//crea una variable en la que guardar la contraseña que introduzca el usuario
contrasena = miScanner.next();
//ahora comprueba si es correcta para dejarle pasar
switch (contrasena) {
case "abracadabra":
System.out.println(contrasenaOK + "\n" + total + " " + totalAhorrado);
//pregunta al usuario
System.out.println("Indica la cantidad a ingresar, por favor");
//crea una variable en la que guardar la cantidad a ingresar
int ingreso = miScanner.nextInt();
if (ingreso > 0) {
totalAhorrado = totalAhorrado+ingreso;

} else {
System.out.println("El importe debe ser mayor que 0.");
System.out.println("No se ha realizado el ingreso.");
}
//muestra al usuario el total actual
System.out.println(total + " " + totalAhorrado+ "\n" + gracias);
break;
default:
System.out.println (KO);
break;
}
}
}

Varios detalles importantes a tener en cuenta de esta solución:

Hemos movido la sentencia que muestra el saldo, así como también las que evalúan el
ingreso, a dentro del bloque switch, dentro del primer caso. El motivo es que sólo
queremos que se ejecute esa parte del programa si el usuario introduce la contraseña
correcta.
Como default hemos creado un mensaje que avisa al usuario de que el texto que ha
tecleado no corresponde a la contraseña.
4. Un juego de niños

A estas alturas del libro ya tenemos cierto control sobre nuestros programas: sabemos crear
variables, manejarlas con operadores, usar métodos para provocar cambios en ellas e incluso
determinar diferentes tareas a realizar según se den algunas condiciones.
Pero a nuestros programas les sigue faltando “algo”.
En nuestro ejemplo de la hucha, es un poco raro que si no introduces la contraseña correcta al
primer intento ésta se cierre sin más… a veces nos equivocamos al escribirla y se agradece poder
repetir, ¿verdad? Pero, ¿cómo decirle al ordenador que ejecute una tarea varias veces, sin
tener que escribir bloques de código idénticos uno tras otro?
Tenemos unos poderosos ayudantes para esto: ¡los bucles! Igual que las sentencias condicionales
del capítulo anterior, los bucles son también herramientas para controlar el flujo de acciones
de nuestro programa. La diferencia es que, mientras las condicionales sirven para decir qué
hacer, los bucles indican cuántas veces o durante cuánto tiempo.

Pero ¿qué es un bucle?


Según el diccionario, un bucle es un rizo de cabello. También usamos la palabra bucle para
referirnos a las vueltas que dan sobre sí mismas las vías de una montaña rusa, cuando nos
ponemos cabeza abajo. En general, llamamos bucle a algo que gira alrededor de un centro, que
da vueltas sobre sí mismo.
Cuando nos referimos a la programación, al hablar de “bucles” nos referimos a un bloque de
instrucciones que se repite una y otra vez, hasta que se alcanza una condición determinada.

Para el caso de nuestra hucha, por lo tanto, podríamos crear un bucle para dar al usuario más
oportunidades para teclear la contraseña correcta, diciéndole al programa que repita la secuencia
leer del teclado-comparar contraseñas-denegar o dar acceso cada vez que éste se equivoque. Y
podríamos decidir si queremos darle un número de intentos concreto, o permitir que lo intente
indefinidamente hasta que lo averigüe: la decisión es nuestra.

En el lenguaje Java existen tres tipos de bucles, que aprenderemos a usar en este capítulo:

WHILE – DO WHILE - FOR

WHILE
La sentencia while (que significa “mientras” en inglés) evalúa el valor de una condición y,
mientras éste sea true, ejecuta el código que ésta contiene.

1. el programa comprueba si el valor de la condición es true


2. siempre que lo sea, a continuación ejecuta el código
3. vuelve a comprobar el valor de la condición
4. si sigue siendo true vuelve a ejecutar el bloque

En el momento en que en una comprobación encuentre que el valor de la condición sea false,
dejará de ejecutar el bloque y continuará con el resto del programa (o, dicho de otro modo,
saldrá del bucle).

Ten en cuenta:
Si en el paso 1 encuentra que la condición es false, jamás llegará a ejecutar el bloque de
código, y no lo comprobará más veces; pasará directamente a la siguiente tarea.
Y si el valor de la condición nunca cambia, tendremos un bucle infinito. El bloque
nunca dejará de ejecutarse.

¿Has oído hablar de los cañones de pelotas? Los jugadores de tenis se


entrenan con unas máquinas que les van lanzando pelotas, una tras otra, y ellos tienen que
golpearlas.
Éste sería un buen ejemplo de bucle while, en el que la condición sería “mientras siga lanzando
pelotas”. Mientras eso ocurra, ejecutaremos nuestro bloque de código, que es “devolver la pelota
con la raqueta”. Cuando deje de lanzar pelotas nosotros dejaremos de golpear y saldremos del
bucle.

Así es como programaríamos un bucle while:


while(condición) {
bloque a ejecutar;
}

¡Así de simple!
Por ejemplo, este programa simula la cuenta atrás para lanzar un cohete al espacio:

public class CoheteEspacial {

public static void main (String args[]) {


int cuentaAtras = 5;
String mensaje = "DESPEGUE";

while (cuentaAtras>0){

System.out.println(cuentaAtras);
cuentaAtras--;
}
System.out.println(mensaje);

}
}

Fíjate:
La condición es que el contador sea MAYOR que cero. Si indicamos >= se mostraría en
pantalla una vez de más… pruébalo en tu equipo.
La sentencia cuentaAtras--; significa “resta uno al valor de cuentaAtras”. Como la
hemos incluido dentro del bucle, solo restará cada vez que haya dado una vuelta al
mismo, es decir tras cada impresión por pantalla del valor de cuentaAtras.
La impresión del mensaje la dejamos FUERA del bucle. Si la metiésemos dentro se
imprimiría cada vez que mostrase un número por pantalla y no tendría sentido, nuestro
cohete saldría 5 veces al espacio ;P

UN POCO DE EJERCICIO
Para practicar los loops while, te propongo que codifiques estos programas:

1. Observa el siguiente fragmento de código. ¿Qué crees que se mostrará por pantalla?

int i = 0;
while (i < 3) {
System.out.println("eco");
i++;
}

2. Debe haber algún problema en este programa, porque lo he ejecutado y el bucle no


termina jamás, he tenido que cerrarlo por la fuerza. ¿Sabrías decir qué es?

int contador = 0;
while (contador <= 3) {
System.out.println("Mensaje para imprimir");
}
contador++;

3. Y uno para adelantados:

Dado un número (que introducirá el usuario) el programa cuenta cuántas veces se puede dividir
éste entre 2 sin dejar residuo, y muestra el resultado.
Por ejemplo:
El programa pregunta el número
El usuario introduce el 6
El programa divide el número entre 2 mediante un bucle while, y sus resultados
sucesivamente, hasta que uno ya no sea divisible (6÷2, después 3÷2 y el resultado que es
1,5 ya no podría dividirse. La respuesta sería 1 veces).
Se muestra al usuario por pantalla un mensaje con el resultado: “6 puede dividirse 1
veces entre 2”.

SOLUCIONES
1. Se mostrará la palabra 3 veces:
eco
eco
eco

2. El bucle es infinito porque hemos dejado la sentencia contador++; fuera del bloque while, así
que no va a sumar hasta que abandone el bucle. Entonces, por más vueltas que da, nunca
aumenta el valor.

3. Una posible forma -con la que he desarrollado la solución que te propongo- es iniciar un bucle
que funcione mientras el resultado de la división sea mayor o igual que 1. Y esto, ¿por qué? Pues
muy sencillo. Sabemos que ningún número menor que el 2 es divisible entre dos con residuo
cero así que, ¿para qué seguir dando vueltas?
int contador = 0;
int numeroUsuario = Scanner.nextInt();

while (numeroUsuario >= 1) {


numeroUsuario = numeroUsuario / 2;
contador++;
}
System.out.println(“Se puede dividir ”+ contador + “ veces.”);

Otra forma podría haber sido iniciar un bucle que funcione mientras numeroUsuario sea divisible
entre 2, usando el operador módulo.

DO-WHILE

La sentencia Do-While es muy parecida a la anterior, pero se diferencia en


que primero se inicia la ejecución del bloque de instrucciones y después se comprueba el
valor de la condición.

Se podría comparar con el juego de la piñata:

Golpear la piñata con el bastón


Comprobar: ¿sigue entera la piñata?
Si sigue entera, golpear de nuevo.
Volver a comprobar si sigue entera…
Y así sucesivamente. En el momento en que la variable piñataEntera tenga valor falso,
saldríamos del bucle, es decir, no daríamos un bastonazo más.

Como ves, la acción a ejecutar (dar un bastonazo) siempre se ejecuta por completo antes de cada
comprobación de la condición. Dicho de otro modo, pase lo que pase siempre se va a ejecutar
al menos una vez. Por eso le llamamos Do-While, en inglés “Hacer - mientras que…”.

UN RETO SENCILLO

Retoma el programa de la hucha e intenta incluir un do-while para que, mientras el usuario no
haya indicado la contraseña correcta, siga pidiendo una y otra vez que la ingrese.

Piensa bien antes de lanzarte, te recomiendo primero hacer un borrador con lápiz y papel o al
menos escribir el algoritmo que seguirás.

Algunos consejos para la práctica:


Recuerda que primero debes pedir la contraseña una vez, y a continuación comprobar si
el usuario acierta.
El resultado de la comparación sería la condición para evaluar
Si el usuario acierta se debe salir del bucle para dar paso al ingreso
Si el usuario se equivoca, se imprime el mensaje de error y se vuelve a pedir la
contraseña

SOLUCIÓN
import java.util.Scanner;
public class MiHucha{

public static void main(String []args){


int totalAhorrado = 0;
String pass;

//abre nuevo Scanner


Scanner miScanner = new Scanner(System.in);

do{
//pide la contraseña
System.out.println("Introduce tu clave para poder operar y pulsa Enter");
//crea una variable en la que guardar la contraseña que introduzca el usuario
pass = miScanner.nextLine();
} while (!"abracadabra".equals(pass)); //deja de pedirla cuando sea correcta

System.out.println("::::Bienvenido a tu hucha securizada.::: \n >>> El total ahorrado es " + totalAhorrado);


//pregunta al usuario
System.out.println("Indica la cantidad a ingresar, por favor");
//crea una variable en la que guardar la cantidad a ingresar
int ingreso = miScanner.nextInt();
if (ingreso > 0) {
totalAhorrado = totalAhorrado+ingreso;
} else {
System.out.println("El importe debe ser mayor que 0: no se hará el ingreso");
}
//muestra al usuario el total actual
System.out.println("El total ahorrado es " + totalAhorrado + "\n::: Gracias por usar la hucha electrónica. :::");
}
}

FOR
La sentencia for nos sirve para programar bucles indicados para aquellos casos en que sabemos
el número de veces que debemos iterar (dar vueltas al bloque de código).

Para ello, se define una variable con un valor numérico


inicial, otra con el valor máximo a alcanzar y se indica que cada vez que se ejecuta el bloque, se
suma uno a la primera. Cuando ha sumado tantos como el máximo, deja de iterar.
Por ejemplo, el juego del escondite. A Juan le toca buscar a sus 6 amigos:

Variable niñosEncontrados: al inicio es 0


Variable niñosJugadores = 6
Juan empieza a jugar. Como niñosEncontrados vale 0, da una vuelta al patio. Encuentra a
María.
Ahora niñosEncontrados es igual a 1. Como aún no vale 6, tiene que dar otra vuelta.
Juan da otra vuelta al patio y encuentra a Miguel.
Ahora niñosEncontrados es igual a 2. Eso tampoco es un 6 así que… tiene que dar otra
vuelta.
Si seguimos así, llegará un momento en que niñosEncontrados valdrá lo mismo que
niñosJugadores: 6 y 6. En ese momento Juan sale de su bucle y deja de buscar.

Y esto, en código Java, tiene el siguiente aspecto:

class MiEscondite {
public static void main(String[] args){
int niñosJugadores = 6;
int niñosEncontrados = 0;

for(niñosEncontrados; niñosEncontrados<niñosJugadores; niñosEncontrados++){


System.out.println("1 vuelta más. Niños encontrados: " + niñosEncontrados);
}
}
}

Fíjate:
Los parámetros del for siempre son 3, en este orden: inicio, término, incremento.
Número del que partes, número al que llegar, cuánto sumar en cada vuelta.
EL CERO CUENTA. Nunca se empieza a contar desde 1, si quieres que un bucle dé 6
vueltas deberás poner el número 5 como límite.
El parámetro de inicio siempre es una variable que se inicializa DENTRO del bucle for.
Si la inicializas al principio del programa queda fuera del bucle y no compilará (veremos
esto más adelante)
El parámetro de término siempre es una comparación aritmética, cuando ésta sea false es
cuando se detendrá el bucle
El parámetro de incremento se ejecuta cada vez que se recorre el bucle entero (no al
principio)
Muy importante indicar que niñosEncontrados > que niñosJugadores, ya que si indicases
>= el resultado no será false hasta que valga 7 y Juan va a dar una vuelta de más. Es
importante que siga el bucle sólo cuando tenga MENOS de 6 niños encontrados.
Dentro de las llaves del bucle metemos el código a ejecutar una y otra vez, igual que
hacíamos con el if.

TRES EJERCICIOS CON BUCLES FOR

1. Escribe un programa que muestre todos los impares contenidos entre el 0 y 50.
Pista: te recomiendo volver a consultar la tabla de operadores aritméticos, hay uno que
sirve exactamente para esto.
2. Escribe un programa que muestre todos los impares contenidos entre el cero y un
número que el usuario introduzca.
3. Modifica el programa del ejercicio 2 para que, después de mostrar los números,
muestre un mensaje diciendo cuántos impares ha encontrado.
Recuerda: el mensaje sólo debe mostrarse al final de la ejecución del programa.

SOLUCIONES

1. Como sabemos qué cifra máxima tenemos y siempre va a ser la misma, sólo necesitas un
bucle for que se ejecute 50 veces, y cada una de ellas estime si el valor de i (que parte de
1) es divisible entre 2 con residuo 0.
2. Para realizar el ejercicio simplemente hemos añadido la pregunta al usuario y modificado el
bucle for. Ahora en vez de tener un número fijo como máximo de vueltas a dar, tiene una
variable que contiene el número que el usuario ha dado.

Fíjate: hemos indicado <= en el for. El motivo es que si sólo indicas i < num y el usuario
introduce, por ejemplo, un 5, el bucle se detendrá cuando valga 4 y nunca te imprimirá el último.
Todo esto depende de lo que se te pida exactamente: todos los impares contenidos entre dos
cifras, o todos los impares mayores que una cifra y menores que otra.

3. En este caso, lo único que hemos hecho es:

Crear una variable que actúe como contador de impares


Sumarle 1 cada vez que un número es impar y entre en el bloque if
Imprimir el mensaje después de salir del bucle for
¡NUESTRO PRIMER JUEGO!

JUEGO: Piedra, papel, tijeras


Como ya vamos teniendo bastante por la mano esto de programar, con todo lo que ya sabemos y
un par de trucos que ahora aprenderás vamos a crear nuestro primer juego interactivo.
¡Hurra!

Como todos los buenos profesionales, antes de lanzarnos sobre el teclado tenemos que completar
un par de fases previas.

En primer lugar, recogeremos los requisitos. Dicho de otra manera, redactaremos la


mecánica de nuestro juego y escribiremos qué funciones debe tener el programa.
Normalmente cada requisito se traduce después en una función concreta del código, algo
que hay que programar.
A continuación, diseñaremos el algoritmo, es decir, la secuencia de pasos que dará
cuando lo ejecutemos
Seguidamente, por fin, escribiremos el código
Pondremos a prueba nuestro programa para comprobar que funciona como se espera
Refactorizaremos: haremos nuestro código más limpio y profesional para obtener el
mejor resultado posible.

¡Manos a la obra! ;)

REQUISITOS DEL PROGRAMA

Como es tu primera práctica de videojuego real y nadie nace enseñado, voy a listar
directamente los requisitos que debe tener. En las próximas prácticas te sugiero que primero lo
intentes por tu cuenta y después compruebes si coincide con la solución o te has dejado algo
importante.

Funciones que debe tener el juego:

Al iniciarse la ejecución el juego mostrará un menú


El menú tendrá las opciones de jugar partida o salir del juego
Los contrincantes serán el programa y el usuario
El programa mostrará al usuario los comandos: 1 para piedra, 2 para papel, 3 para tijera
En cada ronda el usuario elige una tirada usando el teclado, y el programa hace una
tirada aleatoria
Tijera gana a papel, piedra gana a tijera
En caso de empate se informa al usuario
En caso de que gane uno de los jugadores se muestra un mensaje indicando quién gana
El programa tiene que prever que el usuario introduzca un dato incorrecto en cualquier
momento, sin que se provoque un error
En una segunda versión del programa, podría mejorarse para que siga proponiendo
rondas mientras el usuario no pida salir

ALGORITMO DEL PROGRAMA

Ahora usa tu imaginación y recrea toda una secuencia de juego. Mientras lo haces anota cada
paso que se produce y exprésalo en forma de lista de sucesos, para componer el algoritmo.

A continuación tienes mi propuesta de algoritmo. Intenta primero hacerlo sin mirar la solución…

1. Se muestra la pantalla de inicio. Opciones 1) Jugar 2) Salir


2. Si el usuario elige 2 se cierra la aplicación
3. Si el usuario elige 1 se muestran las instrucciones: 1 papel 2 piedra 3 tijera
4. Si el usuario teclea cualquier otra cosa se muestra un mensaje “opción incorrecta” y se
vuelve al punto 1
5. Se inicia una ronda con la tirada del usuario
6. El programa hace una tirada aleatoria
7. Se comparan los resultados:
a. si inputOrdenador == inputUsuario se muestra el mensaje “EMPATE”
b. si inputOrdenador > inputUsuario se muestra el mensaje “TÚ PIERDES”
c. si inputOrdenador < inputUsuario se muestra el mensaje “TÚ GANAS”
d. si inputUsuario no es un número válido aparece el mensaje “TIRADA
INCORRECTA” y se vuelve al punto 3.

¿Verdad que parecía más difícil antes de escribir el algoritmo? Plasmar las cosas de forma
organizada nos ayuda a abordar mejor los problemas lógicos.

ESCRIBIENDO EL CÓDIGO

Para escribir el código, mi consejo es que lo vayas construyendo funcionalidad a funcionalidad,


comprobando a cada paso que lo que acabas de hacer funciona.
Para facilitártelo, dividimos en pasos las funcionalidades que tenemos que desarrollar. Crea una
nueva clase e intenta seguir estos pasos por tu cuenta; después puedes consultar mi solución
propuesta (en el código resultante te dejo comentarios con el paso al que refiere cada fragmento
de código).

1. Programar el menú inicial.


Programa un menú que se muestre por pantalla e indique al usuario las opciones que tiene (salir
o jugar).

2. Programa la lógica del menú.


Recoge la respuesta del usuario según lo que haya seleccionado: 1) inicia una ronda 2) sale del
programa 3) avisa del error y repite el punto 1.
CONSEJO: Para salir del programa puedes usar el comando System.exit(0) que hace justamente
eso.
Para controlar los errores -es decir, que el usuario introduzca cualquier cosa que no sea 1 o 2- te
aconsejo usar algún tipo de estructura de decisión o bucle.

3. Programa la lógica de una ronda.


Recoger el input del usuario. Hacer que el programa haga una tirada aleatoria.
Comparar tiradas de usuario y programa.
Informar de empate - victoria programa - victoria usuario - input incorrecto

CONSEJO: En el lenguaje Java, dentro de la clase MATH, existe el método random cuya
función es elegir un número al azar entre un rango proporcionado previamente. Te podría ser
muy útil para la tirada aleatoria del programa.

Para usarlo tienes que importar la clase Math (igual que haces con la clase Scanner: import
java.util.Math).
Aquí te dejo un ejemplo de uso de dicho método que hace algo parecido a lo que necesitas:
import java.util.Random;
public class random{

public static void main(String []args){


//crea un nuevo objeto random
Random random = new Random();

// usando el objeto random, obtiene un número entero


//de 0 a 100 y lo guarda en la variable randomInt
int randomInt = random.nextInt(100);
//lo muestra por pantalla
System.out.println(randomInt);
}
}

En mi caso, así es como he preparado la clase para empezar a programar:


SOLUCIONES
A continuación tienes la misma imagen, con los fragmentos de código desarrollado. La amplío
por separado para que puedas ver mejor los detalles:

MENÚ PRINCIPAL

Como ves, se puede decorar un poco el texto para que tenga un aspecto más propio de un juego.
Si has llegado hasta aquí, te aconsejo comprobar que de momento el programa compila y se
ejecuta tal como esperas.

LÓGICA DEL MENÚ

Para la lógica del menú hemos usado un while que se encargará de preguntar al usuario las veces
que hagan falta hasta que elija una opción correcta.
Una vez la elija saldremos del bucle y entonces manejaremos lo que haya escogido:
Si es la opción 1, iniciará la ronda de juego
Si es la opción 2, cerraremos el programa con el método System.exit(0);

LÓGICA DE UNA RONDA


Esta es la lógica de UNA ronda de juego. Todavía no hemos llegado a la fase en la que se podrá
jugar una y otra vez; como comentábamos en los requisitos esa es una mejora para una segunda
versión del programa.

Así que, de momento, metemos la lógica de una ronda de juego dentro del switch.
De nuevo, no había una sola manera de programar esta función. Además, se ha programado de la
forma más rudimentaria posible, con el objetivo de que veas con claridad el orden en que se
ejecutan las sentencias y comprendas qué controla cada una de ellas.

Con las herramientas que hasta ahora hemos aprendido a manejar, ésta es una solución bastante
casera, pero aparentemente estable.

La primera versión de nuestro programa está ya lista para la fase de pruebas.

PONEMOS A PRUEBA NUESTRO PROGRAMA


Durante el desarrollo de un programa nuevo, se realizan diversas operaciones para asegurar la
calidad del producto.

Éstas consisten en intentar identificar todos los posibles escenarios que se pueden producir al
usar el programa, para poder comprobar que responde correctamente a cada uno de ellos. A
continuación se escriben todos esos casos en forma de pruebas a realizar, y si alguna fallase se
vuelve a trabajar en el código para solucionarla. Las personas que escriben estas pruebas se
pueden basar en diversos factores: los requisitos del programa, su experiencia previa, errores ya
producidos anteriormente…

Te sugiero que realices estas pruebas jugando con el programa para detectar si hay errores, o si
ocurre lo que se espera de él:
Menú principal: elegir salir
Menú principal: elegir una opción incorrecta
Menú principal: elegir jugar
Jugada 1: elegir tijera
Jugada 2: elegir papel
Jugada 3: elegir piedra
Jugada 4: elegir una opción incorrecta

¿Ha ido todo bien? Si no ha sido así repasa tu código y compáralo con mi solución propuesta.

REFACTORIZANDO NUESTRO JUEGO


La refactorización es un proceso que consiste en hacer cambios en la estructura de nuestro
programa de manera que mejoremos el código sin alterar el funcionamiento del mismo.

Es decir, no se trata de cambiar las cosas que el programa hace, sino de intentar usar un
código más sencillo, limpio y seguro para hacer lo mismo.

Refactorizar es una muy buena costumbre que nos ayuda a mejorar nuestros trabajos y
seguir aprendiendo.

¿Qué podemos mejorar en nuestro juego?

Si te fijas, la estructura actual del juego es un poco engorrosa.

Tenemos bastantes bucles, incluso algunas estructuras anidadas (como por ejemplo un IF y un
WHILE dentro de un SWITCH). Esto hace que sea un poco difícil de leer y que nos resulte
delicado hacer cambios en él, porque cuando tenemos tantas sentencias que contienen otras,
cambiar un pequeño detalle afecta a todo lo demás.
Lo primero que podemos hacer para limpiar nuestro código es mejorar la estructura IF. Fíjate,
nos podríamos haber ahorrado tres líneas si en lugar de comparar 0 con 0, 1 con 1, y 2 con 2
hubiésemos escrito “ if(tiradaPrograma==tiradaUsuario)”.

Además hemos escrito varias veces las mismas Strings (para comunicar empate, victoria o
derrota) cuando las podríamos haber definido al principio del programa en 3 variables.
Haciendo estos dos cambios sencillos, ahora el bloque IF tiene este aspecto:

//comparamos ambas tiradas para encontrar al ganador


if(tiradaPrograma==tiradaUsuario){
System.out.println(empate);
} else if (tiradaPrograma==0 && tiradaUsuario==1){
System.out.println(ganaUsuario);
} else if (tiradaPrograma==0 && tiradaUsuario==2){
System.out.println(ganaPrograma);
} else if (tiradaPrograma==1 && tiradaUsuario==0){
System.out.println(ganaPrograma);
} else if (tiradaPrograma==1 && tiradaUsuario==2){
System.out.println(ganaUsuario);
} else if (tiradaPrograma==2 && tiradaUsuario==0){
System.out.println(ganaUsuario);
} else if (tiradaPrograma==2 && tiradaUsuario==1){
System.out.println(ganaPrograma);
}
break;

case 2: System.exit(0);
break;
Y además ahora tiene otra ventaja, y es que si en el futuro queremos cambiar el mensaje que
aparece cuando ganas o pierdes, sólo tendrás que modificarlo en la declaración de la variable.

Otra cosa útil que podemos hacer es encapsular algunos de nuestros fragmentos, construyendo
métodos con ellos.
Ya has visto algunos métodos que vienen incluidos en las librerías de Java, como el método
Scanner o el método Random. La buena noticia es que tú también puedes crear tus propios
métodos a medida, situarlos en una zona separada del código e irlos invocando cada vez que se
les necesite.

Para crear un método con el código que controla una ronda, hacemos lo siguiente:

1. Crea un nuevo método fuera del método main (no debes declarar un método dentro de
otro). Para saber dónde, fíjate en las llaves que separan cada sección:
public class MiClase{
public static void main(String[]args){
//espacio dentro del método main
}
//espacio DENTRO de la clase MiClase, pero FUERA del método main donde puedes poner el método “ronda”-o
cualquier otro que escribas.
}

2. Declaramos el método, como viste en anteriores capítulos: tipo de acceso, tipo de retorno,
nombre del método, parámetro y llaves:
public static void ronda(){}

3. Movemos el código que gestiona toda una ronda de juego, desde el case1 del switch case a
dentro del nuevo método; y en su lugar en ese punto invocamos al método ronda. Te recomiendo
muchísimo que en lugar de cortar y pegar, comentes ( // ) las líneas en el switch y las copies al
nuevo método. De este modo si algo sale mal y abandonas el intento no perderás lo que ya tenías
y funcionaba bien.

4. Ahora la estructura general del programa queda así (yo no he comentado el código, lo he
borrado para que sea más fácil de ver… ¡no soy un ejemplo de cautela!)
import java.util.*;
public class PiedraPapelTijera {
public static void main (String[]args){
//Menú inicial.
System.out.println(":::::::::::::::::::::::::::\n"
+":::PIEDRA, PAPEL, TIJERA:::\n"
+"::: BIENVENID@ :::\n"
+":::::::::::::::::::::::::::\n\n"
+"Elige una opción:\n 1)JUGAR 2) SALIR ");

//Lógica del menú.


Scanner scan = new Scanner(System.in);
int opcion = scan.nextInt();
//controla que vuelva a preguntar si el usuario no elige 1 o 2
while (opcion!= 1 && opcion != 2) {
System.out.print("Por favor, elige una opción válida:\n" + "1)JUGAR 2) SALIR");
opcion = scan.nextInt();
}
//una vez tenemos opción válida este switch la gestiona
switch(opcion){
case 1: ronda();
break;
case 2: System.exit(0);
break;
}

}
Fíjate: elimino de ese punto el código, lo sustituyo por una llamada al código que ahora lo
contiene.
Como el método que hemos creado no necesita ningún parámetro para funcionar, dejamos el
paréntesis vacío -pero vacío de verdad, ¡no vayas a dejar un espacio!

5. Movemos el código al método. Cuidado con comerte o añadir llaves ;)



case 2: System.exit(0);
break;
}

}
/*Lógica de una ronda.*/
public static void ronda(){
System.out.print("Elige tu tirada:\n" + "0)PAPEL 1) TIJERA 2) PIEDRA");

Scanner tirada = new Scanner(System.in);


int tiradaUsuario = tirada.nextInt();

//con este while controlamos que la tirada del usuario sea válida
while (tiradaUsuario!=0 && tiradaUsuario!=1 && tiradaUsuario!=2){
System.out.print("Elige tu tirada:\n" + "0)PAPEL 1) TIJERA 2) PIEDRA\n");
tiradaUsuario = tirada.nextInt();
}
//generamos una tirada aleatoria del programa
Random random = new Random();
int tiradaPrograma = random.nextInt(2);

//informamos al usuario de las tiradas elegidas


System.out.println("Has elegido " + tiradaUsuario + ". Yo he elegido " + tiradaPrograma + "\n::::::::::::::::::::::::::::::::::::::::\n");

String empate = "empate";


String ganaUsuario = "¡GANASTE!";
String ganaPrograma = "¡PERDISTE!";

//comparamos ambas tiradas para encontrar al ganador


if(tiradaPrograma==tiradaUsuario){
System.out.println(empate);
} else if (tiradaPrograma==0 && tiradaUsuario==1){
System.out.println(ganaUsuario);
} else if (tiradaPrograma==0 && tiradaUsuario==2){
System.out.println(ganaPrograma);
} else if (tiradaPrograma==1 && tiradaUsuario==0){
System.out.println(ganaPrograma);
} else if (tiradaPrograma==1 && tiradaUsuario==2){
System.out.println(ganaUsuario);
} else if (tiradaPrograma==2 && tiradaUsuario==0){
System.out.println(ganaUsuario);
} else if (tiradaPrograma==2 && tiradaUsuario==1){
System.out.println(ganaPrograma);
}
}
}

Y ahora, la prueba definitiva: guarda y comprueba si compila. Si no, revisa las diferencias entre
tu código y el de este libro.

La última vuelta de tuerca

Separar partes del código que controlan funciones concretas -como una ronda de juego-
tiene mucho sentido. Puedes cambiar o ampliar esos métodos sin alterar el main, reutilizarlos…
y llamarlos varias veces, cada vez que haga falta.

Cuando recogíamos los requisitos de nuestro videojuego dijimos que en una segunda versión
sería genial que pudieses jugar rondas seguidas sin tener que reiniciarlo.

Pues bien, ésa es otra utilidad de separar métodos.

Creamos otro método nuevo, en la misma sección que el anterior (dentro de la clase, fuera del
método main) al que llamamos, por ejemplo, menú:

public static void menu(){

Scanner scan = new Scanner(System.in);


int opcion = scan.nextInt();

//este bucle controla que se vuelva a preguntar si el usuario no elige 1 o 2


while (opcion!= 1 && opcion != 2) {
System.out.print("Por favor, elige una opción válida:\n" + "1-JUGAR 2-SALIR");
opcion = scan.nextInt();
}

//una vez tenemos opción válida este switch la gestiona


switch(opcion){
case 1: ronda();
System.out.println("¿Quieres jugar otra ronda?\n 1-SI 2-NO");
menu();
break;

case 2: System.exit(0);
break;
}
}
Dentro del método, en el case 1, y justo debajo de la llamada a ronda(); volvemos a imprimir por
pantalla el mensaje preguntando si quieren jugar. A continuación lanzamos el método menu() de
nuevo.

Si sigues el código con atención verás lo que ésto provoca: cada vez que eliges jugar, primero
lanza una ronda y luego te devuelve al menú. Así es como encadenamos rondas mientras el
usuario quiera seguir eligiendo 1)jugar.

¡Reto conseguido!
5. Siguiendo el rastro

Hasta este momento, todos los programas que hemos escrito se ejecutaban sin dejar huella en
nuestro sistema de archivos.

En este capítulo aprenderemos a escribir programas capaces de buscar archivos en nuestro


equipo, crear nuevos y guardar cambios. Esto nos será muy útil si, por ejemplo, queremos que
nuestra hucha empiece a recordar qué saldo tenemos de una vez para otra, o si queremos que
nuestros video juegos guarden un registro con nuestro historial de victorias.
Algunos conceptos previos sobre archivos
Los archivos no son muy distintos de las variables que manejamos en nuestros programas: son
pequeños espacios asignados en la memoria del ordenador, con un contenido y formato
determinado. O, de manera más formal, conjuntos de bits con un nombre asignado y una
descripción de la carpeta que los contiene.

Al nombre que identifica el lugar exacto -dentro de nuestro sistema de carpetas- donde vive el
archivo le llamamos ruta.
Por ejemplo, al archivo .class que contiene el video juego de la práctica anterior lo llamé
PiedraPapelTijera.class, ése es su nombre de archivo. Y, como lo guardé directamente en el
escritorio de mi equipo, la ruta de dicho archivo es
C:\Users\Nadia\Desktop\PiedraPapelTijera.class.

Haz la prueba: Abre cualquier carpeta de tu ordenador (la de descargas, la de archivos de


programa, una carpeta que tengas con tus documentos…).
Observa en la barra de dirección cómo se muestra la ruta hacia ese punto.

El aspecto de la ruta varía un poco entre sistemas operativos (Windows, Ubuntu, MacOS…) pero
el concepto es el mismo.

Así pues, ya sabemos que la ruta es la dirección en la memoria que conduce hasta el archivo.

Ahora bien, existen dos tipos de rutas:

Ruta absoluta: Es aquella que empieza desde la letra o nombre de la unidad de memoria,
como en el ejemplo anterior. Es decir, muestra toda la dirección completa desde la unidad de
origen hasta el archivo.

Ruta relativa: Es aquella que sólo detalla la dirección desde el punto del sistema en el que
nos encontremos, hasta el archivo. Por ejemplo, la ruta anterior
C:/Users/Nadia/Desktop/Scripts/CoheteEspacial.class se podría expresar como
/Desktop/Scripts/CoheteEspacial.class si el usuario o el programa ya están situados en la carpeta
/Nadia de mi sistema.

Cuando escribas programas que trabajen con rutas o direcciones de archivos deberás tener en
cuenta siempre si necesitas indicar la ruta relativa o absoluta.

La clase File
File (archivo) es una clase Java creada para manejar archivos o, mejor dicho, los lugares
donde están. Lo cierto es que, aunque el nombre parece claro, lo que esta clase gestiona son las
rutas donde se encuentran los ficheros, y no los documentos en sí.

Ayudándote de los métodos que incluye esta clase puedes realizar muchas funciones con
archivos, por ejemplo:

Comprobar si un archivo existe


Crear carpetas
Renombrar, mover, copiar, borrar archivos

Fíjate: Con la clase File NO podemos leer qué hay dentro de los archivos, eso lo veremos más
adelante.

La forma de invocar esta clase es parecida a lo que ya vimos cuando usamos Scanner y
Random (aunque File no es una colección de métodos como lo son estas dos, sino más bien un
tipo de dato):

1. Importar java.io.File al principio de la clase, antes de declararla


2. Instanciar File con la sentencia File file = new File(String rutaArchivo); Como siempre, puedes
ponerle el nombre que quieras (no necesariamente file) y en el parámetro puedes
pasar directamente la dirección del archivo, o bien una variable tipo String que contenga
la misma, como yo he hecho

Resumiendo: una vez instanciado File, puedo crear un nuevo objeto File -o dirección de
archivo- usando una variable:

String rutaApuntes = c:/Documentos/Deberes/Apuntes/apuntesJueves.doc


File misApuntes = new File(rutaApuntes);

O indicar la ruta directamente en el parámetro:

File misApuntes = new File(“c:/Documentos/Deberes/Apuntes/apuntesJueves.doc”);

Algunos métodos útiles para trabajar con la clase File


A continuación tienes una lista de los métodos más útiles y sencillos que puedas usar para
manejar archivos:

.exists() Comprueba si existe el archivo, y es muy útil ejecutarlo como precaución antes de usar
otros métodos que puedan dar un error porque el archivo no esté donde esperamos. Este
método genera un booleano que adquiere valor true o false según si el archivo existe o no.

File archivo = new File(ruta);


bool existeArchivo = archivo.exists();
System.out.println(“¿El archivo existe?: “+ existeArchivo);

.mkdir() (o mkdirs) Crea un nuevo directorio, y genera un booleano con valor true o false
según si ha conseguido crearlo o no.

File archivo = new File(ruta);


bool crearArchivo = archivo.mkdir();
System.out.println(“¿Se ha creado el directorio?: “+ existeArchivo);

.renameTo() Este método cambia el nombre de un archivo. También podemos usarlo para
cambiar el nombre de la ruta, y lo que hará es moverlo a esa nueva ruta. Es decir, no cambiará el
nombre de las carpetas que lo contenían, sino que buscará si existen las que ahora hemos
indicado y, si es así, lo moverá a esa ubicación. También nos crea el booleano para saber si se ha
movido o no.

File a = new File(“C:/Usuario/Escritorio/Maria.jpg”);


File b = new File(“C:/Usuario/MisFotos/Maria.jpg”);
bool moverArchivo = a.renameTo(b);
System.out.println(“¿Se ha movido el archivo? “+ moverArchivo);

Como ves, en este ejemplo lo hemos movido ya que el nombre de archivo es el mismo y la ruta
es la que ha cambiado, ahora está en otra carpeta.

.delete(); Este método borra el archivo en cuestión y genera un booleano informando de si ha


podido o no borrarlo.

File file = new File("C:/Users/Ana/Desktop/test.txt");


boolean borrar = file.delete();
System.out.println(borrar);

Alerta: no lo mueve a la Papelera de Reciclaje, lo borra permanentemente. Así que haz tus
pruebas con cuidado ;)

TRY/CATCH
Antes de seguir aprendiendo a manejar archivos, hay una técnica que debemos conocer, ya que el
compilador de Java nos obligará a usarla cuando queramos gestionarlos.
Es posible que al ejecutar los programas que escribiste en los ejercicios anteriores te hayas
encontrado con alguna excepción. Es decir, un error durante la ejecución que se producía
cuando ocurría algo excepcional o inesperado y que el programa no sabía manejar.

Por ejemplo, en nuestra primera versión de la hucha ésta no tenía ningún tipo de defensa ante la
posibilidad de que intentases ingresar una string en lugar de un int, y si lo intentabas el
resultado era algo como:

Exception in thread "main" java.util.InputMismatchException


at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at MiHucha.main(MiHucha.java:26)

A la misma vez, terminaba la ejecución del programa.

Pues bien, éso es una excepción, y aunque ahora no profundizaremos en ello (porque es un tema
para alumnos más avanzados) debes saber que hay dos tipos de excepciones (checked y
unchecked, es decir comprobadas o no) y que cuando sean del primer tipo el compilador nos va a
obligar a dejar algo previsto por si ocurren. Ese algo previsto es un bloque Try/Catch (en inglés,
intenta o captura).

Resumiendo: siempre que uses un método que lance excepciones de tipo checked, aunque el
código esté perfecto, nunca va a compilar a menos que añadas un bloque Try/Catch.
Los bloques gestores de excepciones tienen tres componentes a los que llamamos Try, Catch y
Finally (es decir Intenta, Captura y Finalmente).
El esquema de uso sería el siguiente:

try {

//aquí ponemos el código que contiene esos métodos que nos obligan a capturar excepciones

} catch (tipoDeExcepción NombreDeExcepción){


//aquí el código que va a gestionar la excepción. Sólo se ejecuta si ésta se produce

} finally {
//código que se ejecuta SIEMPRE, haya excepción o no
}

Es una manera de estructurar el código, indicándole al programa que INTENTE hacer algo, sino
funciona CAPTURE la excepción -en lugar de irla lanzando hacia arriba- y FINALMENTE haga
algo en concreto.
La sentencia finally es opcional, es decir, no vas a tener un error de compilación por no
incluirla. Pero es interesante tenerla en cuenta, ya que normalmente se usar para limpiar o cerrar
procesos. Por ejemplo, si en el bloque try hemos abierto un archivo para examinar lo que
contiene, es muy buena costumbre añadir un bloque finally que, tanto si try va bien como si se
lanza una excepción, cierre correctamente antes de que el programa siga con otra tarea o termine
su ejecución.
Especialmente por el hecho de que al producirse una excepción lo normal es que el
programa deje de ejecutarse, es importante intentar asegurarse de que, dentro de lo que
cabe, el programa falle lo mejor posible.

Un ejemplo de uso de try/catch/finally


Para acabar de entenderlo, vamos a ver cómo usar esta técnica en el caso de un bloque de código
que ya hemos usado antes: el de la cuenta atrás del cohete espacial. Este ejemplo no requeriría
usar try/catch (no usamos ningún método que lance excepciones de tipo checked) pero lo vamos
a usar porque es un código que entendemos:
public class CoheteEspacial {
public static void main (String args[]) {
int cuentaAtras = 5;
String mensaje = "DESPEGUE";

try{
while (cuentaAtras>0){
System.out.println(cuentaAtras);
cuentaAtras--;
}
System.out.println(mensaje);

} catch (Exception e){

System.out.println("Se ha producido una excepción: " + e);


}
}
}
Fíjate: Lo que he hecho es asignarle un nombre a la excepción (la he llamado e porque me
parecía intuitivo) y, en el bloque catch, determinar que se muestre un mensaje que incluye la
excepción. No se imprimirá la letra e, sino una descripción de lo que ha ocurrido.

Hay mucho más que aprender sobre el manejo de excepciones, pero para lo que pretendemos
(que compile el programa al usar ciertas clases) hasta aquí es suficiente.

Y ahora, volvamos al tema del capítulo: manejar archivos.

La clase Scanner (otra vez)


Tal y como viste en el capítulo 1, la clase Scanner contiene métodos diseñados para leer flujos de
datos o mensajes. Hasta ahora hemos practicado con métodos como .nextInt() o nextLine() que
nos servían para leer datos introducidos por el usuario en el teclado.
Bien, esta clase también sirve para leer flujos de datos que provengan de archivos
existentes en tu sistema. Con el método adecuado, Scanner podrá gestionar las cadenas de texto

que tengas en un archivo doc (por ejemplo) y manipularlas como hasta


ahora hemos venido haciendo.
De hecho, dentro de cualquier archivo, los datos están ordenaditos de forma secuencial,
colocados en fila, y cuando se accede a los mismos para trabajar con ellos casi siempre se leen
justamente así. Por eso se habla de streams o corrientes; puedes imaginarte los pequeños datos
circulando uno tras otro como si saliesen por un grifo.

A continuación, veremos cómo la clase Scanner nos proporciona métodos para leer streams de
caracteres procedentes de un archivo.
Para indicar a la clase Scanner qué archivo queremos abrir, hacemos uso de la clase File de la
manera que acabamos de aprender: indicándole la ruta.
Así, de la misma manera que para leer del teclado hacíamos:

Scanner scanTeclado = new Scanner(System.in);

Para leer de un archivo haremos:

Scanner scanArchivo = new Scanner(File ruta);

Fíjate bien, simplemente se trata de usar Scanner igual que siempre, pero con una ruta como
parámetro -en lugar de un teclado.

Y para indicarle que lo lea usamos los mismos métodos que al leer del teclado: nextInt(),
nextLine() o lo que consideremos que va a contener el archivo.

Un ejemplo
Crea en tu sistema un documento de texto que contenga esta frase:
(Te aconsejo guardarlo como .txt).

Y ahora copia este programa. Cuidado con la ruta, tiene que coincidir con la ubicación real del
archivo en tu máquina.
import java.io.File;
import java.util.Scanner;

public class LectorArchivos{

public static void main(String []args){

try{
//creo la ruta
File ruta = new File("C:/Users/Desktop/texto.txt");
//abro el lector, con la ruta como parámetro
Scanner scanArchivo = new Scanner(ruta);

/*le indico que lea la primera fila, es decir


hasta el primer salto de línea*/
String frase = scanArchivo.nextLine();

//muestro por pantalla lo que ha leído


System.out.println(frase);
scanArchivo.close();

}catch (Exception e){


System.out.println(e);
}

}
}
Fíjate: cuando termino de trabajar con un fichero siempre, siempre, siempre, siempre, SIEMPRE
lo cierro: scanArchivo.close(); Esto es tan importante como lavarse los dientes después de cada
comida.

Si lo has copiado bien, se mostrará en la consola el texto que había en el fichero.


¡Genial! ¡Ahora ya sabemos leer documentos desde un programa!

Un par de experimentos

1. En el programa anterior, sustituye el método nextLine() por Next(). ¿Qué ocurre?


¿Por qué?

2. Ahora sustituye el método next() por nextInt(), ¿qué ocurre?

3. Ahora sustituye la línea String frase = scanArchivo.nextLine(); por este bloque de


código:
for(int i=0; i<4; i++){
String frase = scanArchivo.next();
//muestro por pantalla lo que ha leído
System.out.println(frase);
}
¿Qué conclusiones puedes sacar?

SOLUCIONES

1. Al sustituir NextLine() por Next() sólo lee la primera palabra de la frase, porque en eso
consiste el funcionamiento de estos métodos: leer la siguiente línea o la siguiente palabra
-entendiendo palabra como el texto hasta el siguiente espacio.

2. Se lanza una excepción. El motivo es que el método nextInt() espera encontrar uno o
varios números enteros separados por espacios o saltos de línea, y en lugar de eso
encuentra Strings. Como hemos controlado la excepción en el bloque catch, el fallo es
controlado e indicando el motivo.

3. Este experimento nos demuestra de qué manera podemos usar estructuras de decisión o
bucles para leer ciertas partes del documento. Esto nos abre muchas posibilidades, por
ejemplo:
a. Leer un documento sólo si incluye ciertas palabras
b. Leer un documento en parte
c. Leer un documento de forma sucesiva mientras vamos manejando su contenido
d. … y cualquier idea que se te ocurra

La clase Printstream
Ahora que sabemos buscar archivos y leerlos, el siguiente paso lógico es escribir en ellos. Y para
eso haremos uso de otra clase nueva llamada Printstream (palabrita que viene a significar algo así
como imprimir corriente).

Y la buena noticia es que los principales métodos de esta clase, a estas alturas, ya los tenemos
dominados: println() y print().

print() escribe el string que incluyamos como parámetro, y nada más


println() escribe el string, y a continuación incluye un salto de línea

Ten en cuenta que:


si necesitas incluir espacios entre strings deberás indicarlos tú. Si no lo haces, cada
vez que escriba insertará el texto pegado al último string que encuentre
si usas estos métodos en un archivo que ya existía sobrescribirás su contenido (es
decir, perderás lo que había escrito anteriormente en él)
igual que hacemos cuando acabamos de leer un fichero, también cerramos el stream
cuando acabamos de escribir en él

Un ejemplo de uso
Retomo el programa del ejemplo anterior (que leía el contenido de nuestro .txt).
Ahora lo he mejorado para que en primer lugar lea el contenido de mi archivo, después escriba
un nuevo texto en él y a continuación vuelva a leerlo, para así comprobar que ha podido hacer la
modificación.

import java.io.File;
import java.util.Scanner;
import java.io.PrintStream;

public class LectorArchivos{


public static void main(String []args){

try{
//creo la ruta
File ruta = new File("C:/Users/Albert/Desktop/texto.txt");

//PARTE 1: LEER
//invoco al Scanner
Scanner scanArchivo = new Scanner(ruta);
//muestro el texto
String frase = scanArchivo.nextLine();
System.out.println(frase);
scanArchivo.close();

//PARTE 2: ESCRIBIR
//invoco Prinststream
PrintStream escritor = new PrintStream(ruta);

//Escribo un texto en mi archivo


String texto = "He conseguido escribir el archivo";
//Escribo en el archivo
escritor.print(texto);
escritor.close();

//PARTE 3: LEER OTRA VEZ


Scanner lector = new Scanner(ruta);
frase = lector.nextLine();
System.out.println(frase);
lector.close();

}catch (Exception e){


System.out.println(e);
}

}
}
Como ves, se cumple lo que te decía más arriba: si usamos los métodos de escritura sobre un
archivo que ya existe, se sustituye su contenido antiguo por el nuevo.

Nuestra hucha electrónica recuerda los cambios


La hucha electrónica, que llevamos varios capítulos desarrollando, tenía un error de diseño que
nos impedía ahorrar: cada vez que terminaba de ejecutarse “olvidaba” la cantidad que le
habíamos ingresado.

Ahora que podemos leer y escribir en ficheros, es hora de sustituir la variable con el ahorro
indicado que siempre usa como base, y empezar a usar un documento a modo de base de
datos.
Partiendo de la última versión de nuestra hucha, intenta hacer las siguientes modificaciones:

1. Cambia a 0 el valor inicial de la variable totalAhorrado

2. Genera un archivo txt que contenga una cifra (que será el nuevo valor ahorrado)

3. Implementa un método o fragmento de código que lea el contenido del .txt y lo guarde
en la variable totalAhorrado. De esta manera cuando muestre el total lo hará siempre a
partir de lo que diga el archivo

4. Implementa un método o fragmento de código que, cuando el usuario introduce la


cantidad a ingresar, lo sume a totalAhorrado y escriba el resultado en el .txt. De esta
manera cuando salgas del programa el total del texto habrá cambiado (si es que has
ingresado algo).

No olvides que necesitarás usar Try/Catch para que compile :)

A continuación, y para que te sea más fácil, te copio el código de mi última versión por si quieres
usarlo como punto de partida para el ejercicio. Será más fácil comparar soluciones si partimos de
la misma base.
import java.util.Scanner;
public class MiHucha {

public static void main (String []args){


String contrasena;
int totalAhorrado = 0;
String pideContrasena = "Introduce tu clave para poder operar y pulsa Enter";
String contrasenaOK = "::::Bienvenido a tu hucha securizada.:::";
String total = " >>> El total ahorrado es ";
String gracias = "::: Gracias por usar la hucha electrónica. :::";
String KO = "Contraseña incorrecta. No estás autorizado a usar esta hucha.";

Scanner miScanner = new Scanner(System.in); //abre nuevo Scanner


System.out.println(pideContrasena); //pide la contraseña
//crea una variable en la que guardar la contraseña que introduzca
//el usuario
contrasena = miScanner.next();
//ahora comprueba si es correcta para dejarle pasar
switch (contrasena) {
case "abracadabra":
System.out.println(contrasenaOK + "\n" + total + " " + totalAhorrado);
//pregunta al usuario
System.out.println("Indica la cantidad a ingresar, por favor");
//crea una variable en la que guardar la cantidad a ingresar
int ingreso = miScanner.nextInt();
if (ingreso > 0) {
totalAhorrado = totalAhorrado+ingreso;
} else {
System.out.println("El importe debe ser mayor que 0.");
System.out.println("No se ha realizado el ingreso.");
}
//muestra al usuario el total actual
System.out.println(total + " " + totalAhorrado+ "\n" + gracias);
break;
default:
System.out.println (KO);
break;
}
}
}

SOLUCIÓN
Por partes, para que lo veas más claro.

1. En primer lugar importo las clases necesarias: File y Printstream (Scanner ya estaba
importada).
import java.util.Scanner;
import java.io.*;
Fíjate: El asterisco después de .io sirve para importar todas las clases que existan en ese
paquete. Así me ahorro importar File y Printstream por separado.

2. Cambio el valor inicial de totalAhorrado a 0

3. Declaro la ruta. Lo hago a continuación de declarar las variables de la clase:


File ruta = new File("C:/Users/Desktop/scripts/totalAhorrado.txt");

4. Incluyo el try catch para poder usar Printstream:

try{
switch (contrasena) {
case "abracadabra":
Scanner scanTxt = new Scanner(ruta); //nuevo Scanner archivo
totalAhorrado = scanTxt.nextInt();
System.out.println(contrasenaOK + "\n" + total + " " + totalAhorrado);

//pregunta al usuario
System.out.println("Indica la cantidad a ingresar, por favor");

//crea una variable en la que guardar la cantidad a ingresar


int ingreso = miScanner.nextInt();
if (ingreso > 0) {
totalAhorrado = totalAhorrado+ingreso;
} else {
System.out.println("El importe debe ser mayor que 0.");
System.out.println("No se ha realizado el ingreso.");
}

//muestra al usuario el total actual


System.out.println(total + " " + totalAhorrado+ "\n" + gracias);
break;
default:
System.out.println (KO);
break;
}
}catch(Exception e){
}
Fíjate: - He metido el bloque del switch dentro del try/catch.
He creado un nuevo objeto Scanner (llamado scanTxt) específico para leer en el
archivo.
He indicado que totalAhorrado adoptará el valor que lea scanTxt en mi archivo
He preparado el bloque catch pero aún no he puesto código en él

En este punto, me aseguro de que el programa compile de nuevo.Ahora ya tengo la primera


modificación importante: mi hucha ya no parte siempre del mismo valor, sino del que
encuentre en su archivo. Lo siguiente es conseguir que también escriba en él.

Ahora me ocupo de la segunda parte, que escriba los cambios. Para ello:

1. Dentro del bloque if, después de actualizar el valor de totalAhorrado creo el objeto
Printstream con la misma ruta como parámetro. Le indico que escriba el valor de
totalAhorrado en ese archivo:
if (ingreso > 0) {
totalAhorrado = totalAhorrado+ingreso;

//invoco Prinststream
PrintStream escritor = new PrintStream(ruta);
escritor.print(totalAhorrado);
escritor.close();

2. En la línea donde muestra el total actual tengo muchas posibles opciones, éstas son
algunas:
1. No modificar nada, pues el valor a mostrar (totalAhorrado) es el mismo que se
escribe en el fichero, con lo cual implícitamente ya confirmo que ha escrito lo
correcto
2. Escribir una sentencia que compare el contenido del archivo con totalAhorrado y
genere un booleano. Si el booleano es false, que me avise. Un poco enrevesado.
3. Modificar el parámetro de System.out.println para que el saldo final que muestra
lo lea de nuevo del archivo, así también compruebo lo que se ha escrito en él.

Yo he optado por la versión a, pero si te sientes aventurero/a te sugiero que intentes codificarlas
todas, sólo por experimentar y ver si eres capaz.

Por último, me ocupo de algunos detalles finales:

1. Dentro del bloque catch incluyo esta sentencia para que, en caso de lanzar excepción, la
pueda manejar informando al usuario de lo ocurrido:

}catch(Exception e){
System.out.println(e);
}

2. Me aseguro de que los streams estén cerrados. Si te fijas ya indicamos escritor.close()


después de escribir en el archivo, pero nunca hicimos lo mismo con scanTxt. Así que
añado esta línea después de mostrar el total al usuario:
scanTxt.close();

Y por último, vuelvo a comprobar que mi programa compile :)


Por fin tenemos una hucha real, que recuerda las cantidades que vamos ingresando.
PRÁCTICA FINAL: El
documento secreto

Te propongo una práctica final que usa prácticamente todo lo que hemos visto en este libro.
Verás que la dificultad es más elevada -por eso es una práctica final-, puedes intentar resolver
el reto por tu cuenta o usar los fragmentos de código que te daré.

Vamos a crear un nuevo juego que nos servirá para cifrar y descifrar mensajes. Así
podremos guardar contraseñas, frases secretas o cualquier otra cosa que nos gustaría tener a
salvo de espías indeseados, e incluso intercambiar mensajes cifrados con nuestros amigos si
les pasamos nuestro programa.

¿Cómo funciona el cifrado del texto?

Un texto cifrado es el que está escrito con caracteres que sólo pueden comprenderse si se dispone
de la clave, es decir, de la guía que indica lo que en realidad significa cada uno.
Existen muchos tipos de cifrados y estándares de encriptación. De hecho, Java dispone de
algunas librerías específicas para este tipo de prácticas… pero como su uso aún nos resultaría un
poco complicado, vamos a aprovechar para bucear en la historia y conocer uno de los sistemas
de cifrado más antiguos que se conocen.
El Cifrado del César

Julio César Augusto fue el primero de los emperadores de la antigua Roma. Precisamente a él se
le atribuye el sistema de Cifrado César -o cifrado por desplazamiento-, que, según parece,
utilizaba para enviar mensajes secretos a sus tropas.
El sistema es muy simple: consiste en sustituir cada letra del alfabeto, con la que le
corresponde si la desplazamos un número de veces concreto.
Por ejemplo, en un sistema de Cifrado César de 2 posiciones, ésta sería la correspondencia de
letras:

Éste es el caso de un alfabeto inglés, no recoge algunas letras como la ñ o la ç.


Entonces, si tenemos un string “programa”, después de cifrarlo con este sistema el string
contendría la palabra “npmepyky”.

Basándonos en este sistema, vamos a construir un programa que cifra y descifra mensajes.
El programa usa siempre un archivo de trabajo en una ubicación fija del sistema de archivos del
ordenador.

Así, puedes distribuir este programa a alguno de tus amigos, y enviaros mensajes cifrados
que sólo vosotros, usando el programa, podréis convertir a texto legible.

Requisitos del programa

1. Muestra un menú al usuario para que elija opción (cifrar o descifrar)


2. Lee el mensaje y lo procesa en el sentido solicitado
3. Guarda el nuevo contenido en el archivo
4. Muestra por pantalla el contenido resultante
5. Nuestro programa siempre va asociado a un archivo específico que ya existe

Por lo tanto, la forma de usar el programa sería ejecutarlo, introducir el mensaje y pedirle que lo
procese, eligiendo la opción de encriptar o desencriptar.
Algoritmo del programa
Trata de escribir el algoritmo de este programa. A continuación tienes mi propuesta.
Propuesta de Algoritmo

1. Inicio del programa


2. Solicita al usuario que escriba el mensaje a procesar
3. Solicita al usuario qué hacer con el mensaje: 1 Encriptar 2 Desencriptar
4. Usuario elige 1:
a. Se encripta el mensaje
b. Se guarda el mensaje encriptado en el archivo preexistente
5. Usuario elige 2:
a. Se desencripta el mensaje
b. Se guarda el mensaje desencriptado en el archivo preexistente

¡Programando!

Para facilitarte la organización de lo que tienes que ir haciendo, aquí tienes la imagen de la clase
tal y como yo misma la he preparado para empezar a trabajar:

Como ves, te propongo hacerlo más limpio desde el principio, creando métodos específicos para
encriptar y desencriptar a los que podamos llamar según sea necesario.

Algunos consejos:
Crea un array de chars a modo de diccionario. Lo definimos FUERA de main porque
queremos que sea de acceso global (nuestros métodos para cifrar y descifrar lo usarán).
No te preocupes si no sabes trabajar con arrays, te facilitaré los métodos más adelante
Deberás definir un int con el número de posiciones a desplazar. Puedes dejarlo como
un dato permanente o pedírselo cada vez al usuario, yo he preferido dejarlo fijado en 5.

Éste es el array de caracteres que he usado como diccionario:

Cómo programar los métodos para cifrar y descifrar

El funcionamiento de los métodos es sencillo, aunque trabajoso de codificar:


Vuelca el string que ha introducido el usuario en un array de chars
Por cada char en el array, lo busca en el diccionario recorriéndolo
Cuando lo encuentra, lo transforma por el que se encuentre a x posiciones

Te animo a que intentes programarlo por tu cuenta. Lo consigas o no, es un ejercicio interesante
que te obligará a diseñar bien el método y hacer pruebas.

Si no quieres intentarlo o no lo consigues, aquí tienes dos métodos de encriptar y desencriptar


que funcionan. De todos modos, tendrás que encajarlos en tu código y comprobar que funcione
todo junto :)

Encriptar:
static String encriptar(String texto, int desplazamiento)
{
char[] arraylegible = texto.toCharArray();

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


for (int j = 0; j < chars.length; j++) {
if (j <= chars.length - desplazamiento) {
if (arraylegible[i] == chars[j]) {
arraylegible[i] = chars[j + desplazamiento];
break;
}
}
else if (arraylegible[i] == chars[j]) {
arraylegible[i] = chars[j - (chars.length - desplazamiento + 1)];
}
}
}
return String.valueOf(arraylegible);
}

Desencriptar:
static String desencriptar(String cifrado, int desplazamiento)
{
char[] arrayCifrado = cifrado.toCharArray();
for (int i = 0; i < arrayCifrado.length; i++) {
for (int j = 0; j < chars.length; j++) {
if (j >= desplazamiento && arrayCifrado[i] == chars[j]) {
arrayCifrado[i] = chars[j - desplazamiento];
break;
}
if (arrayCifrado[i] == chars[j] && j < desplazamiento) {
arrayCifrado[i] = chars[(chars.length - desplazamiento +1) + j];
break;
}
}
}
return String.valueOf(arrayCifrado);
}

Resultado final
A modo de solución, éste es mi código final. Recuerda que lo importante no es que el tuyo sea
igual, sino que realice las mismas funciones.

import java.io.File;
import java.util.Scanner;
import java.io.PrintStream;

public class Encryption


{

static char[] chars = {


'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
'#', '$', '%', '^', '&', '(', ')', '+',
'-', '*', '/', '[', ']', '{', '}', '=',
'<', '>', '?', '_', '"', '.', ',', ' '
};
public static void main(String[] args) {

//define posiciones a mover


int desplazamiento = 5;
System.out.println("Por favor, escribe el mensaje secreto y pulsa Enter");
Scanner reader = new Scanner(System.in);
String texto = reader.nextLine();

System.out.println("Q HACER?");
int opcion = reader.nextInt();
switch (opcion) {
//ENCRIPTAR
case 1: //llama a encriptador y guarda resultado en variable
String enc = encriptar(texto, desplazamiento);
try {
File f = new File("C:/Users/Albert/Desktop/scripts/secreto.txt");
PrintStream writer = new PrintStream(f);
writer.print(enc);
writer.close();
} catch (Exception e) {}
//escribe el resultado en pantalla y archivo
System.out.println("Encrypted text: " + enc);
break;

//DESENCRIPTAR
case 2:
String dec = desencriptar(texto, desplazamiento);
System.out.println("Decrypted text: " + dec);
break;
}

static String encriptar(String texto, int desplazamiento) {


char[] arraylegible = texto.toCharArray();

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


for (int j = 0; j < chars.length; j++) {
if (j <= chars.length - desplazamiento) {
if (arraylegible[i] == chars[j]) {
arraylegible[i] = chars[j + desplazamiento];
break;
}
} else if (arraylegible[i] == chars[j]) {
arraylegible[i] = chars[j - (chars.length - desplazamiento + 1)];
}
}
}
return String.valueOf(arraylegible);
}
static String desencriptar(String cifrado, int desplazamiento) {
char[] arrayCifrado = cifrado.toCharArray();
for (int i = 0; i < arrayCifrado.length; i++) {
for (int j = 0; j < chars.length; j++) {
if (j >= desplazamiento && arrayCifrado[i] == chars[j]) {
arrayCifrado[i] = chars[j - desplazamiento];
break;
}
if (arrayCifrado[i] == chars[j] && j < desplazamiento) {
arrayCifrado[i] = chars[(chars.length - desplazamiento + 1) + j];
break;
}
}
}
return String.valueOf(arrayCifrado);
}
}
PROBAR
Es el momento de hacer pruebas con nuestro programa.

Diseña todos los escenarios de uso posibles y comprueba qué ocurre. Algunos podrían ser:

Introducir un texto legible, cifrarlo


Introducir el texto anterior, descifrarlo
Introducir un texto con números, mayúsculas, minúsculas

MEJORAR
Aunque no se encuentran en el alcance de esta práctica, hay bastantes detalles que podrían
mejorarse en este programa y que puedes realizar como proyecto más adelante. Por ejemplo:

El número de posiciones a desplazar los caracteres podría ser variable (ahora está
hardcodeado, y ya sabes que eso es un poco chapucero). Es más, si lo pidiese al usuario
al iniciar el cifrado, podrías usar este programa con varios amigos y tener un número
clave con cada uno, así nadie podría leer mensajes que son para otra persona

Una versión posterior del programa podría leer de un archivo en lugar del teclado. Así
te podrían enviar el archivo por mensajería o email y al cargar el programa lo encontraría
y descifraría. Incluso puedes incorporar una función que liste los archivos para que elija
uno, o que busque por nombre de archivo en un directorio.

No hemos añadido protección ante errores de usuario… como por ejemplo, que elija
la opción 3 (que no existe) o similares.
6. ¿Por dónde seguir?

Mi más sincera enhorabuena por llegar hasta aquí.


Ya has sentado una buena base de conocimiento, pero sobre todo has demostrado
tenacidad y paciencia.
Programar es una actividad capaz de sacar lo mejor de nosotros (perseverancia, lógica, reflexión)
pero también lo peor cuando las cosas no salen (frustración, impotencia, inseguridad…). Todos
nos atascamos en algún momento de nuestro aprendizaje -de hecho, en muchos momentos, y
no sólo cuando aprendemos. Los profesionales se equivocan todos los días.

Si quieres seguir profundizando en la programación en Java y te estás preguntando qué hacer a


continuación, tengo dos consejos básicos:

1. Repasa otra vez lo que hasta ahora has aprendido e incorpora buenas prácticas
2. Cuando lo hayas dominado, adéntrate en la programación modular y orientada a
objetos

Este libro no puede ayudarte en lo segundo, pues el objetivo del mismo era que entrases en
contacto con las principales estructuras y tipos de datos y adoptases el pensamiento algorítmico.

Respecto al primer punto, quería cerrar el libro con una serie de buenas prácticas o patrones que
te sugiero apliques en tu día a día. Aunque expresadas aquí pueden parecer un poco abstractas, te
animo a que reflexiones sobre ellas mientras repasas los programas que has producido hasta
ahora. Con el tiempo verás que tienen mucho, muchísimo margen de mejora -pocas veces en la
vida se puede asegurar que un programa está terminado y en su mejor versión posible- y tal vez
te atrevas a retomarlos, darles una vuelta siguiendo estos enfoques y encontrar formas de
hacerlos más limpios, más simples, más eficientes.
Hay pocas satisfacciones más grandes que programar bonito.
DRY (Don’t repeat yourself)

“No te repitas”. Un principio importantísimo que estoy segura de que ya


puedes empezar a interiorizar. Intenta evitar el código duplicado; cuando notes que estás
copiando y pegando sentencias probablemente sea el momento de extraer ese código a un
método que puedas reutilizar. Esta norma persigue un código más estable y mantenible:
siempre será más sencillo cambiar algo UNA SOLA vez, que tener que retocarlo todas las
veces que aparece en un programa.

YAGNI (You Aren’t Gonna Need It)


“No lo vas a necesitar”. ¿Sabes eso que nos pasa a todos cuando nos vamos de vacaciones y
metemos en la maleta el doble de cosas que al final usamos? Programando tendemos a hacer lo
mismo. Este principio nos dice que no añadamos funcionalidades “por si acaso”; porque un
programa que hace más cosas es más propenso a errores y complicado de mantener. Cuando
diseñes tus aplicaciones, programa únicamente lo que necesitas en este momento. Siempre
hay tiempo de actualizar un programa si necesitas que haga más cosas.

La regla del Boy Scout


Los Boy Scouts tienen la norma de dejar siempre el bosque más limpio de lo que lo
encontraron. Aplícate este lema siempre que mejores un programa que ya existía, sobre todo si
no lo creaste tú. Como dijimos hace un par de capítulos, refactoriza una y otra vez.

No te lances sobre el teclado


Antes de empezar a programar escribe, proyecta, diseña. Dibuja y borra mil veces lo que quieres
construir hasta que tengas un esquema claro. Te ahorrarás muchas horas de rehacer métodos y algoritmos :)
Testea SIEMPRE
Aunque sea tentador darlo por hecho cuando compila, un programa no está terminado hasta
que hayas hecho las pruebas necesarias (y éstas hayan salido bien). Que el compilador no se
queje no significa que nuestro programa no tenga errores o haga cosas inesperadas cuando se
use… Intenta enumerar siempre todas las posibilidades y probarlas; no sólo debes probar los
casos que deben funcionar sino también los que deben fallar. Y recuerda que los usuarios son
casi imprevisibles… seguro que hay formas de usar tu aplicación en las que no has pensado.
Muchas gracias…

a ti, por leer este libro.


Tanto si te ha gustado como si no, me haría muy feliz que dejases tu crítica en la página de producto de
Amazon. Las opiniones de mis lectores me ayudan a mejorar mi trabajo y a que este proyecto siga adelante.

Recuerda también que puedes encontrar el código completo de todas las prácticas de este libro en mi
cuenta de GitHub: https://github.com/nadieta

Si quieres apuntarte a mi lista de correo para recibir noticias sobre mis próximas publicaciones o
lanzamientos, puedes hacerlo en este enlace:
http://eepurl.com/c9qObn


A Saïda y Leila, mi ikigai.

A Albert, por la fe.
Nadia Ameziane Garcia
Octubre de 2017.

Potrebbero piacerti anche