Primer programa en Java

Topic created · 15 Mensajes · 9974 Visitas
  • Antes de empezar quizá te interese revisar los tutoriales anteriores:
    Cómo compilar y ejecutar programas en Java
    "Hola Mundo" en java, pero gráfico 😃

    Hoy vamos a hacer algo un poco más útil, y más complicado. El objetivo es entender un poco mejor lo que Java proporciona: programación orientada a objetos. Espero ser capaz de ayudaros a ver lo que esto significa, poco a poco.

    Bien, nuestro programa no va a tener interfaz gráfica. Aun es demasiado temprano para meterse en eso, aunque más adelante sería un buen ejercicio hacerle interfaz a este programa.
    Va a funcionar por consola de comandos.

    En qué va a consistir? Será una especie de "juego", donde el usuario tendrá que adivinar un número del 1 al 10. Sin duda de lo más divertido y adictivo :icon_mrgreen: (qué esperabas, un metin2 en java? jejeje)

    Así que el programa sacará un número aleatorio, y el usuario tendrá 3 intentos para adivinarlo. Sencillo, como todo ejemplo para principiantes. Algo así:

    Vamos a ello!


    hr
    Nuestro programa constará de dos clases: Main.java y AdivinaAleatorio.java
    En la clase Main, meteremos únicamente nuestro método main(). Todo programa debe tener este método, es por donde comienza la ejecución. Si no hay main, el programa da error, y no se ejecuta.
    Bien, pues nuestro main se encargará de decirle "bienvenido" al usuario, y de arrancar el juego.
    Pero toda la funcionalidad del juego estará en la clase AdivinaAleatorio.

    Vamos al código:

    AdivinaAleatorio.java
    Esta clase nos permitirá jugar a esta especie de juego un tanto estúpido. Como toda clase en java, empezamos escribiendo:

    public class AdivinaAleatorio {
    }
    

    Va a necesitar un par de atributos, que son el número máximo de intentos que permitiremos al usuario, y el número aleatorio que genera el programa. Con esas dos cosas el programa tendrá lo básico para funcionar. Lo añadimos a la clase, así:

    public class AdivinaAleatorio {
    	
    	public int intentos;
    	public int aleatorio;
    }
    

    Ya tenemos la clase y sus dos atributos. Ahora vamos a escribir el método constructor. Un constructor debe llamarse igual que la clase, en este caso debe llamarse AdivinaAleatorio, y va a hacer lo siguiente:

    	public AdivinaAleatorio() {
    		intentos = 3;
    		aleatorio = (int) (Math.random() * 10) + 1;
    	}
    

    Inicializa el número de intentos y "sortea" el número aleatorio que debe adivinar el usuario.
    El constructor nos permitirá crear objetos de la clase AdivinaAleatorio, es decir, nos permitirá hacer new AdivinaAleatorio(). Lo veremos después.

    Ok, tenemos la clase, sus atributos, y su constructor de objetos "AdivinaAleatorio". Ahora nos hacen falta un par de métodos, para que el juego haga algo jeje. Empecemos con un método facilote:

    	public void reiniciar()
    	{
    		intentos = 3;
    		aleatorio = (int) (Math.random() * 10) + 1;
    	}
    

    Este método vuelve a poner el atributo "intentos" a 3, y sortea un nuevo número aleatorio. Esto lo usaremos cada vez que el usuario acierte un número o agote sus intentos y empiece una nueva partida. Reiniciaremos los atributos para empezar un nuevo turno.

    Vamos a necesitar otro pequeño método que pida un número al usuario, lo llamaremos "leerNúmero" y tendrá esta pinta (es un poco feo el pobre, así que no os asustéis):

    	public int leerNumero()
    	{
    		BufferedReader linea = new BufferedReader( new InputStreamReader( System.in ) );
    		int num = -1;
    		System.out.println( "Introduzca un numero: ");
    		try
    		{
    			num = Integer.parseInt( linea.readLine( ) ) ;
    		}
    		catch (NumberFormatException e) {
    			System.err.println( "Error al convertir a entero" );
    		} catch (IOException e) {
    			System.err.println( "Error al leer entrada de datos" );
    		}
    		return num;
    	}
    

    Os dije que era feo, no se asuste nadie. En realidad esa mierda de código simplemente nos da el número que escribe el usuario. No hace más, sin embargo queda bastante feo porque leer un número no es tan sencillo como suena: ¿y si el usuario, muy cabroncete él, mete una letra? ¿y si ocurre algún error con la entrada de datos? Es delicado, por eso el código queda tan feo. Pero da igual, de momento sólo os importa que eso pide un número y lo devuelve, así que ahora cuando queramos un número del usuario, escribiremos tan solo: numero = leerNumero(); Y quedará guardado en la variable "numero" el valor introducido por el usuario. Así no volveremos a ver ese horrible pedazo de código.

    Ya casi está, tenemos la clase, los atributos, el constructor, un método que resetea el juego, y otro que lee un número del usuario. Nos falta juntarlo todo en un método principal.
    Ese método principal simplemente pedirá un número al usuario hasta que acierte o se agoten los intentos. Vamos a llamarlo jugarPartida y quedará así:

    	public void jugarPartida()
    	{
    		int usuario;
    		System.out.println( "Se ha generado un numero del 1 al 10, adivinelo =)" );
    
    		do
    		{
    			usuario = this.leerNumero(); //pedimos un número al usuario
    			if ( usuario == aleatorio ) 
    			{
    				System.out.println( "Enhorabuena, ha acertado! El numero es el: " + aleatorio );
    			}
    			else 
    			{
    				intentos = intentos - 1 ;
    				System.out.println( "Lo siento, no es correcto, le quedan " + intentos + " intentos." );
    			}
    		} while (intentos>0 && usuario != aleatorio);
    		
    		if (intentos==0)
    			System.out.println("Game Over! El numero era: " + aleatorio );
    	}
    

    Vamos línea a línea:
    1- public void jugarPartida()
    Esto declara un método público (otras clases podrán usarlo), que no nos devuelve nada (void) a diferencia del leer número que nos devolvía int, y que se llama jugarPartida.
    2- int usuario;
    Declara una variable llamada usuario, de tipo int (integer, o entero en español).
    3- System.out.println( "Se ha generado un numero del 1 al 10, adivinelo =)" );
    Muestra por pantalla esa frase "Se ha generado...".

    Ahora viene lo bueno, tenemos un do while. Es un bucle, que se repite mientras al usuario le queden intentos (intentos>0) y no haya acertado el número todavía (usuario != aleatorio). != significa distinto de.
    Dentro de ese bucle haremos una y otra vez lo mismo:
    leer un número, y comprobar si es el correcto o no.
    Si es el correcto, felicitamos al usuario.
    Si no es correcto, restamos uno al número de intentos restantes, y le decimos al usuario que no es correcto.
    Así hasta que acaben los intentos o el usuario acierte.
    Fin de la clase AdivinaAleatorio. Os dejo el código al completo. Las 3 primeras líneas son librerías necesarias para algunas órdenes que he usado, no tienen más importancia.
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;

    public class AdivinaAleatorio {

    /* Atributos */
    public int intentos; //aquí almacenaremos el número máx. de intentos que permitiremos al usuario
    public int aleatorio; //aquí guardaremos el número generado por el programa, que debe adivinar el usuario

    /* Constructor */
    public AdivinaAleatorio() {
    /* Inicializamos atributos */
    intentos = 3;
    aleatorio = (int) (Math.random() * 10);
    }

    /* Llamaremos a este método cuando queramos resetear
    * los valores del programa, por ejemplo cada vez que el usuario
    * adivine el número y quiera jugar de nuevo
    * */
    public void reiniciar()
    {
    intentos = 3;
    aleatorio = (int) (Math.random() * 10);
    }

    /* Este método se encarga de comparar el número que introduce el usuario
    * con el número generado aleatoriamente durante el máximo de intentos permitidos
    * */
    public void jugarPartida()
    {
    int usuario;
    System.out.println( "Se ha generado un numero del 1 al 10, adivinelo =)" );

    do
    {
    usuario = this.leerNumero(); //pedimos un número al usuario
    if ( usuario == aleatorio )
    {
    System.out.println( "Enhorabuena, ha acertado! El numero es el: " + aleatorio );
    }
    else
    {
    intentos = intentos - 1 ;
    System.out.println( "Lo siento, no es correcto, le quedan " + intentos + " intentos." );
    }
    } while (intentos>0 && usuario != aleatorio);

    if (intentos==0)
    System.out.println("Game Over! El numero era: " + aleatorio );
    }

    public int leerNumero()
    {
    BufferedReader linea = new BufferedReader( new InputStreamReader( System.in ) );
    int num = -1;
    System.out.println( "Introduzca un numero: ");
    try
    {
    num = Integer.parseInt( linea.readLine( ) ) ;
    }
    catch (NumberFormatException e) {
    System.err.println( "Error al convertir a entero" );
    } catch (IOException e) {
    System.err.println( "Error al leer entrada de datos" );
    }
    return num;
    }
    }

    Main.java
    Vamos con el remate final, hacer un main que cree un objeto de la clase AdivinaAleatorio y lo use. Como siempre que hacemos una clase, el código básico:

    public class Main {
    }
    

    Bien, atributos vamos a ponerle solamente uno. Esta vez no va a ser un "int", ni nada de eso. Va a ser una variable de tipo AdivinarAleatorio. Como ya hemos creado la clase con su constructor, podemos crear objetos de ese tipo. Similar a cuando creas un int, o un string... así de fácil. Veamos la línea exacta:

    public class Main {
    
    	static AdivinaAleatorio miJuego = new AdivinaAleatorio();
    }
    

    Crea un atributo, de tipo AdivinaAleatorio, llamado miJuego. La palabra reservada "new" es la que hace uso del constructor. Vamos, que al escribir esa línea, el programa "entra" en la clase AdivinaAleatorio, busca el método constructor, y ejecuta ese código. En nuestro caso inicializa el número de intentos y el aleatorio.

    Vale, por último creamos un método main dentro de la clase Main. Como dije al principio, el método main es el que se ejecuta. Si no hay método main, el programa no hace nada. Vale, añadimos un método main y quedará así:

    public class Main {
    
    	static AdivinaAleatorio miJuego = new AdivinaAleatorio();
    
    	public static void main(String[] args) {
    	}
    
    }
    

    Ya tenemos clase Main, atributo de tipo AdivinaAleatorio, y método main (vacío pero ahí está).
    Solo falta rellenarlo, vamos a ir metiendo cosas:

    		System.out.println( "----- Bienvenido al programa -----" );
    		System.out.println( "" );
    		System.out.println( "Pulse 1 para empezar una partida o 0 para salir" );
    

    Eso se entiende no? La segunda línea simplemente deja un "intro" adicional entre las dos frases.
    Ahora el usuario va a meter un número. Nos sirve la función que hicimos en la otra clase, la de "leerNumero". Así que vamos a usarla que no me apetece meter otra vez el tocho horrible de código aquel:

    int opcion = miJuego.leerNumero();
    

    Hay que poner "miJuego." delante, ya que ese método está en el objeto miJuego, no en nuestra clase Main.

    Y ahora, un bucle. ¿Para qué? Para que mientras el usuario no introduzca un 0, el programa siga permitiendo jugar. Ahí va el código:

    		while (opcion == 1)
    		{
    			miJuego.reiniciar();
    			miJuego.jugarPartida();
    			System.out.println( "Para jugar otra partida escriba 1. Si no, escriba 0" );
    			opcion = miJuego.leerNumero();
    		}
    

    Mientras el usuario siga poniendo la opción 1, reiniciamos el juego (para que se genere otro número aleatorio y los intentos restantes se reseteen a 3), y usamos el método de jugarPartida. Cuando termine la partida, le preguntamos al usuario si quiere jugar de nuevo y leemos el número que escriba. Si mete un 1, el bucle se repetirá. Si mete un cero, saldremos del bucle.

    Y ya está, le vamos a añadir una despedida cuando el programa termine:

    		System.out.println( "----- Gracias por usar el programa -----" );
    		System.out.println( "Que pase un buen dia!" );
    

    Ahora sí, hemos terminado.
    public class Main {

    static AdivinaAleatorio miJuego = new AdivinaAleatorio();

    public static void main(String[] args) {
    System.out.println( "----- Bienvenido al programa -----" );
    System.out.println( "" );
    System.out.println( "Pulse 1 para empezar una partida o 0 para salir" );

    int opcion = miJuego.leerNumero();

    while (opcion == 1)
    {
    miJuego.reiniciar();
    miJuego.jugarPartida();
    System.out.println( "Para jugar otra partida escriba 1. Si no, escriba 0" );
    opcion = miJuego.leerNumero();
    }

    System.out.println( "----- Gracias por usar el programa -----" );
    System.out.println( "Que pase un buen dia!" );
    }

    }

    Hemos acabado, os dejo los dos archivos fuente:
    [attachment=3][attachment=2]

    Y esos dos archivos ya compilados, para que podáis ejecutarlos sin necesidad de compilador:
    [attachment=1][attachment=0]

    Recordad, para compilar "javac Main.java"
    Para ejecutar algo compilado: "java Main".
    No se ejecuta la clase AdivinaAleatorio, lo he dicho varias veces, se ejecuta la clase que contenga el método main. Probad a ejecutar la otra jeje, escribid "java AdivinaAleatorio" y os dirá que no encuentra el main:

    Exception in thread "main" java.lang.NoSuchMethodError: main

    Bueno espero que os haya gustado. En un futuro espero que no muy lejano añadiremos otro tipo de juegos a nuestro main, para que al ejecutar el programa se dé la opción al usuario de escoger el juego al que prefiera jugar 😃

    [licencia][/licencia]

  • :(( Ponlo compilado ya, que quiero probarlo u.u que a mi el compilador no me rula xD!
    Por cierto, los códigos son supersimilares al de VB, el problema es, que al primer intento de adivinar el numero, fallas. El mismo programa busca otro número aleatorio, ¿no?
    Pero de todas formas, también, con una interfaz gráfica te digo yo que sería muy adictivo. Yo prefiero jugar a esto que al metin 😉 Ponlo para descarga directa porfi *-*
    Ah, y las explicaciones bastante bien, por lo menos no te quedas trabado como yo xD!

  • Terminado, y compilado. Todos podéis probarlo sin necesidad de tener instalado el compilador. Seguro que todos, o prácticamente todos vosotros tenéis la máquina virtual de java instalada, con lo cual con poner "java Main" en la consola podréis ver el programita funcionando.

    Anghios el programa se resetea al entrar en el bucle "while" del método main. Es decir, cada vez que el usuario pulsa 1. No se resetea nunca durante una partida, si miras el método jugarPartida() verás como no aparece ninguna llamada a "reiniciar()"

    Para más adelante lo haremos con interfaz gráfica, que tampoco es complicado, pero son bastantes más líneas de código. Meter tanto de golpe es mucho jeje.

    EDITO: Corregido un error que generaba números entre 0 y 9, en vez de entre 1 y 10 como pensaba xD. Bastó con añadir un "+1" en la generación de aleatorios.

  • @Anghios said:

    Pero de todas formas, también, con una interfaz gráfica te digo yo que sería muy adictivo. Yo prefiero jugar a esto que al metin 😉 Ponlo para descarga directa porfi *-*

    Siempre tengo ganas de hacer algo en java pero no se me ocurren ejercicios así que he hecho un programa como este pero con interfaz grafica. Le he añadido además una nueva funcionalidad, te dice las partidas ganadas y las perdidas. Espero que no le importe a Salva que haya adaptado su juego a una aplicación normal, me hacía ilu hacer un programa así sencillito.

    Además de adjunto lo pongo en mediafire y megaupload, comentar a ver qué tal y a ver si veis algún bug ^^

    http://www.mediafire.com/?9p96gonz9apzu3p
    http://www.megaupload.com/?d=BMC9S9VD

    Espero ver que os parece y estoy abierto a otras ideas para otros programas tengo ganas de programar :icon_cheesygrin:

    PD: es un jar ejecutable, no hace falta abrirlo desde la consola, solo doble clic, eso sí, aseguraos que en la misma carpeta donde este el programa esté también la carpeta que trae el archivo comprimido 😛

  • está genial, aunque por lo que veo se reinicia el juego al gastar los 3 intentos sin darle al botón de reiniciar verdad?
    estaría bien que guardase las estadísticas en un archivo, para que no desaparezcan al cerrar el programa. Lo puedes hacer creando una nueva clase (creo que es lo mejor) llamada por ejemplo "Estadisticas.java" donde meter el numero de partidas jugadas, ganadas, perdidas, numero medio de intentos por cada acierto, los 3 números que más se repiten... qué se yo, estadísticas jeje.
    Luego guardas un objeto de tipo "Estadísticas" en un fichero. A lo mejor la clase tiene que llevar el "implements serielizable" para que deje guardarlo pero vamos, es sencillísimo. Así aprendes a guardar datos a archivos jeje.

    Podías intentar explicar cómo lo has hecho, explica el código para ayudar a otros que estén aprendiendo. Aprendo yo, y es posible que aprendas tú también jeje.

  • pensé en guardar las estadisticas fijate pero es que es tarde y no tenia ganas xD otro dia si eso. respecto a como lo hice, lo confieso soy un vago y me ayudo netBeans xD pero subo el código fuente. No tengo ganas de explicarlo ahora que me voy a acostar pero si quieres tú por mi encantado.

    NetBeans hace las cosas un poco raro O.o lo pone todo en varios sitios diferentes pero lo que yo modifique está adjunta. Mañana si eso lo modifico y explico pero me voy a dormir buenas noxes xD

  • bueno, es normal usar entornos de desarrollo. Yo usé Eclipse. También desperdiga los archivos dentro de la carpeta del proyecto, en src los fuente, en lib las clases compiladas, etc. Es lo típico, cada cosa en su sitio jeje.

    uff, todo metido en una clase, eso es horrible de leer y entender xD
    Mira que hasta el más sencillo programa, como el del tutorial, tiene varias clases. Facilita la comprensión, la reutilización (seguramente podías haber usado la clase AdivinaAleatorio.java solo con algunos cambios) y ayuda a pensar en "modo orientado a objetos".
    Miraré con más detenimiento el código, y pensaré la forma en mi opinión más clara de resolver el programa. (más archivos no significa más complicado, al contrario!)

  • Salvatore, sabes si en el java se puede invocar codigos asm, o sea como el c++ que haces :

    __asm
    Y aki escribes el codigo asm

    Se puede?

  • ni idea, asm es ensamblador? no tengo ni idea, pero en principio no cuadraría con la idea de que java se "desentiende" de la máquina en la que se ejecutar, y usa su máquina virtual. Usar ensamblador rompería con la portabilidad de los programas java.

    aun así, repito, no sé si puede hacerse.

  • lo mismo que con el vb :S

    si ASM = ensamblador