Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.


Mensajes - Kabuto

Páginas: 1 ... 41 42 43 44 45 [46] 47 48 49 50
901
De todo un poco... / Re:Pregunta de java
« en: 15 de Noviembre 2017, 20:30 »
No te queda otra opción que, cada vez que recojas el dato por teclado, antes de guardarlo en el vector hagas un recorrido previo del vector comprobando si ya existe o no ese mismo dato.
Si no existe, lo guardas y pasas a pedir el siguiente.
Si existe, informas por pantalla de que el valor ya existe y vuelves a pedirlo.

Hay varias formas de gestionar esto, la más cómoda y elegante sería escribir un método (una función) por separado que devolviera true o false según si el dato ya existe o no dentro del vector.
Pero como estás empezando y quizás aún no has empezado a trabajar con métodos (programación modular), se puede hacer también valiéndote de una variable booleana y un bucle que compruebe si el dato está repetido.

Intentando mantener el código que ya has escrito...marco en rojo los cambios y en verde los comentarios explicativos

Citar
int [] vector = new int [9];


for(h=0;h<vector.length;h++){
            System.out.println("Ingrese cédula");
            boolean repetido = true;//Inicializamos en true, de lo contrario, no se ejecutará el bucle while
            int cedula;
            while (!sc.hasNextInt() || repetido){
                System.out.println("no se puede digitar letras");
                sc.next();
                cedula = sc.nextInt();
                //Comprobamos si la cedula ya existe.
                //Es necesario asegurarnos que la variable "repetido" comienza con valor false
                repetido = false;
                for(j=0; j<vector.length; j++){
                    if (vector[j] == cedula)
                        repetido = true;//Solo cambia a true si se encuentra el dato repetido
                }
                /* Terminado el for de comprobacion, si "repetido" ha adquirido valor true
                 * se cumplirá la condición del while y este se repetirá pidiendo el dato de
                 * nuevo.
                 * En cambio, si "repetido" conserva el valor false, el bucle while terminará y
                 * ahora sí podemos guardar la cedula en el vector, pues ya se ha
                 * comprobado que no está repetido.

                }
            vector[h]=cedula;
            }

No lo he probado, pero en teoría debería funcionar.

Pregunta cualquier cosa que no hayas entendido, te parezca rara.. o lo que sea.

902
De todo un poco... / Re:Ayuda..
« en: 15 de Noviembre 2017, 12:26 »
Hola Stiv,

me asalta una duda... ¿por qué el nombre está en una matriz?

No tiene sentido. Lo tendría si una cedula de identidad estuviera asociada a varios nombres de personas, pero eso no es posible.

Una cédula --> una persona ---> varios locales

Una cédula estará asociada a una ÚNICA persona. Y esta persona si puede tener VARIOS locales asociados. Así que la información de los números de locales si tiene sentido que esté almacenado en una matriz, pero no los nombres de personas.
Suponiendo que "número de locales" se refiera al número identificador de distintos locales, en este caso son datos múltiples asociados a una única persona, por eso tiene sentido que esté en una matriz:
Juan tiene el local L25, y el local L67, y también el local L99.

Si en cambio ese dato se refiere a la "cantidad de locales" que tiene dicha persona, entonces NO tiene sentido que esté guardado en una matriz, ya que se trataría de un dato único, y bastaría con un simple vector
Juan tiene 3 locales

A no ser que yo haya malinterpretado algo, de momento vamos a suponer que tenemos dos vectores y una matriz.
Muchas veces, para decidir que lógica seguir en un programa, ayuda mucho hacer un dibujo (con papel y lápiz) de los datos con los que hay que trabajar.
Aquí en el foro no podemos dibujar, pero podemos intentar hacer una representación.

Vamos a representar los vectores, poniendo en azul el dato almacenado y en rojo la posicion que ocupa dentro del vector

Vector Cédulas Identidad
  • (0) 0010
  • (1) 0020
  • (2) 0030
Vector Nombres
  • (0) Juan Garcia
  • (1) Maria Santos
  • (2) Lucas Ramirez
Y lo mismo con la matriz

Matriz Locales
  • (0)(0) L01, (0)(1) L03, (0)(2) L04
  • (1)(0) L12, (1)(1) L13, (1)(2) L14
  • (2)(0) L45, (2)(1) L47, (2)(2) L49

Ya tenemos la información representada.
Ahora vamos a suponer que Maria Santos quiere visualizar sus datos en pantalla.
Para ello, le introduce al programa su número de cédula que es el 0020

Lo que el programa tiene que hacer ahora es recoger ese número de cédula y recorrer el vector de Cédulas Identidad para comparar cada cédula almacenada, con la cédula que el usuario le ha indicado.
Si encuentra una cédula que coincida, deberá guardar en una variable el numero de posicion donde haya encontrado la coincidencia.

Es decir, para la cédula 0020, el programa encontrará una coincidencia en la posición (1) del vector.
Pues este número de posicion se ha de guardar en una variable, por ejemplo en nPos

Ahora, con nPos, quien recordamos ahora alberga el valor (1), ya podemos acceder al resto de datos de Maria Santos

nPos nos dará el nombre correcto del vector Nombres
(1) Maria Santos

Y también nos dará los locales de la matriz Locales, solo que en este caso necesitaremos otro bucle.
Si entendemos la matriz como si fuera una tabla, nPos nos estaría indicando la fila y necesitariamos un bucle para recorrer las columnas y así obtener los tres locales que Maria tiene asociados.

(1)(0) L12, (1)(1) L13, (1)(2) L14

Bien, pues esa es la lógica que hay que seguir.
Tu código ha de:
- Pedir número cédula al usuario.
- Ver si la cédula introducida existe en el vector de Cédulas.
- Si existe, guardar en una variable la posición donde se ha encontrado la cédula.
- Con esa posicion, mostrar el resto de datos, nombre y locales, ya que ocupan la misma posicion en sus respectivos vectores y matriz.
- En el caso de la matriz Locales, se necesitará un bucle para recorrer la fila de datos que encontraremos en esa posición.


Intenta escribir un código que cumpla esto. Haz lo que puedas, si no te sale, publica aquí lo que hayas escrito y entre todos te ayudamos a completarlo.

Un saludo.

903
Hola,

no podemos ver la imagen jpg que has posteado ya que no la has subido a Internet. Has puesto directamente una "ruta interna" de tu ordenador, no una URL de la web... así que no sabemos que pide el enunciado completo y sería importante para poder ayudarte.

Trata de subirlo a alguna web de alojamiento de imagenes, como http://www.subirimagenes.com por ejemplo.

O bien teclea tú la parte que no podemos ver.

De otro modo, no podemos saber que es lo que se supone que debes lograr hacer, y por lo tanto ver que estás haciendo mal.

Por lo pronto, veo un par de posibles fallos.
Código: [Seleccionar]
System.out.println("Venta en el dia "+r+" de "+n[fila]);
            dtrabajados [fila][col]=dato.nextByte();

Aquí por el mensaje en pantalla parece que estás pidiendo el valor de producción o venta del día, pero el dato que luego lees parecen ser... ¿los dias trabajados?

Luego, una pequeña tontería que nos pasa a todos...
Código: [Seleccionar]
System.out.println("Planta con mayor productividad");
            if((planta[0]=a1)>(a1+dtrabajados [fila][col])) {
            if((planta[0]=a2)>(a2+dtrabajados [fila][col])) {
            if((planta[0]=a3)>(a3+dtrabajados [fila][col])) {
            if((planta[0]=a4)>(a4+dtrabajados [fila][col])) {
            if((planta[0]=a5)>(a5+dtrabajados [fila][col])) {

En las condiciones de esos if, seguramente tendrás que poner doble igual "==" que es la instrucción para COMPARAR.
El igual simple "=" es la instrucción para ASIGNAR.

Hasta no conocer el enunciado completo, no podremos darte más indicaciones sobre como resolverlo.


Por último, solo un pequeño comentario, sin apenas importancia.

Los tipos de dato byte y float, está bien conocerlos y usarlos cuando puedan ser útiles. Pero en mi opinión, cuando se está aprendiendo, es mejor usar los tipos de datos que Java emplea por defecto, que son el int y el double.

Más que nada porque de lo contrario tienes que estar haciendo casting a byte o float varias veces, lo cuál provoca que el código sea un poquito más engorroso de leer y de escribir.. y de todos modos no ganas ninguna ventaja por usar tipos de datos que ocupan menos memoria, ya que hablamos de unos pocos bytes "de ahorro".

La verdadera utilidad de los tipos de dato float, byte, short.... es sobre todo en programas que tienen que trabajar con enormes colecciones de datos.
Por ejemplo operar con un arreglo que alberga, yo que se.. 5.000.000 de valores double supone un gran esfuerzo de procesado realizar operaciones aritméticas con ellos y puede ralentizar mucho la ejecución de un programa.
En cambio si podemos permitirnos transformarlos a float, el esfuerzo es mucho menor.

Aquí si que se nota, pero en pequeños ejercicios de aprendizaje como el que estamos haciendo, no aporta nada, excepto obligarnos a hacer casting de datos.
Así que es más comodo usar int y double directamente, excepto claro está, que el enunciado del ejercicio o el profesor que luego vaya a corregir el trabajo, pida expresamente utilizar otros tipos de datos.

Un saludo

904
Hola manu37

Solo una pequeña corrección.
Te sobra esta parte del código:
Código: [Seleccionar]
for(int i=0; i<palabra.length(); i++) {

System.out.println(palabra);

}

Esto lo que hace es mostrar la palabra entera, tantas veces como sea su longitud.
Es decir, si la palabra fuese: "avion"

En pantalla saldría esto:
Citar
avion
avion
avion
avion
avion

Así que ese bucle for puedes borrarlo sin más.

El siguiente bucle, sí es correcto y es el único que necesitas para cumplir el enunciado:

Código: [Seleccionar]
for(int i = 0; i<palabra.length(); i++) {

System.out.println(palabra.substring(i, i+1));


}
Esto, para "avion" te daría este resultado:
Citar
a
v
i
o
n

Aunque puedes mejorarlo un poco así:

Código: [Seleccionar]
for(int i = 0; i<palabra.length(); i++) {

System.out.println("Letra " + i+1 + ": " + palabra.substring(i, i+1));


}

Esto te mostraría en pantalla:

Citar
Letra 1: a
Letra 2: v
Letra 3: i
Letra 4: o
Letra 5: n

Cualquir posible duda que puedas tener, no dudes en preguntar.

Un saludo.

905
Aprender a programar desde cero / Re:Ayuda con ejercicio java
« en: 10 de Noviembre 2017, 00:22 »
Consulta: recorro el array para mostrar el contenido grabado y no me muestra nada. Mejor dicho me muestra un null y simbolos

Seleccione la opcion deseada: 4
tp4.Persona@4554617c
null

a que se puede deber este error?

Saludos

¿Cómo lo estás mostrando?

Meter el objeto en system.out no servirá..
Por ejemplo:
Código: [Seleccionar]
System.out.println(agenda[i]);Eso, solo funcionaría si hubieras sobreeescrito el metodo toString(), que todas las clases heredan de la superclase Object,  dentro de tus clases. Aunque esto es otro asunto que mejor dejar para otro momento para no liar más el asunto.

En tu ejercicio, para mostrar la información de los contactos has de llamar al método mostrarContacto(), que fue declarado como abstracto en la clase Contacto, y posteriormente sobreescribiste en los clases hijas, tal que así:

Código: [Seleccionar]
void mostrarContacto(){
        System.out.println(this.getNombreCompleto() + this.getDni() + this.getEmail() + this.getTelefonoCelular());
       
    }

Por lo tanto, dentro del bucle deberías poner algo así para llamar a este método:

Código: [Seleccionar]
agenda[i].mostrarContacto();
Recuerda que el bucle en principio no debería recorrer TODO el arreglo, pues el arreglo tiene 50 posiciones pero tu seguramente NO has creado 50 nuevos contactos. Esto puede explicar que te muestre algunos null en pantalla.
En el código que te pasé, usábamos la variable indiceAgenda para contar cuantos contactos vamos creando y así saber, entre otras cosas, hasta donde debe llegar el bucle a la hora de recorrer el arreglo y mostrar los contactos.
El límite del bucle ha de ser el valor de indiceAgenda, y no la longitud total del arreglo.

Por cierto, tu método mostrarContacto() no es muy "bonito".
Al mostrar contactos en pantalla saldrá algo parecido a:
Citar
Juan Ramon62535625wjuan.ramon@yahoo.com645789675
Es decir, saldrán todos los atributos juntos en una sola línea.

No hay que obsesionarse con la presentación, pero tampoco hay que despreciarla je je.
De momento concentrate en que funcione. Y luego puedes hacer el método mostrarContacto() un poco más elegante.
Por ejemplo:

Código: [Seleccionar]
@Override
public void mostrarContacto()
{
System.out.println("\nDATOS DEL CONTACTO");
System.out.println("------------------\n");
System.out.println("Nombre: " + super.getNombre());
System.out.println("E-Mail: " + email);
System.out.println("D.N.I: " + dni);
System.out.println("Num Celular: " + celular);
}

Por cierto, fíjate que sobre el método he especificado la cláusula @Override

Esta cláusula es para indicar al compilador que queremos sobreescribir un método heredado, en este caso, estamos sobreescribiendo a mostrarContactos() que viene heredado de la clase Contacto.

No es obligatoria poner esta cláusula, normalmente los compiladores ya detectan ellos solos si estamos sobreescribiendo o no.
Pero si es muy recomendable ponerlo. Por una parte es útil al programador para identificar fácilmente qué métodos están sobreescribiendo y cuáles no.

Pero sobre todo ayuda a prevenir posibles errores.
Por ejemplo:
el método mostrarContactos() es de tipo void, no devuelve ningún valor

Si yo en una clase hija escribo de nuevo el método mostrarContactos(), también como tipo void, el compilador sabrá que estoy sobreescribiendo, aunque no yo no use la cláusula @Override.
En cambio, supongamos que me equivoco. Yo quiero sobreescribir ese método, pero por error indico , que en lugar de void,  digo que es tipo String (estoy cambiando la "firma" del método) y hasta pongo que devuelva un dato de tipo String y todo...

En este caso, el compilador pensará que estoy "sobrecargando" (que no es lo mismo que sobreescribir) el método mostrarContactos() y no se quejará por haber cambiado la "firma", lo dará por bueno.
Sin embargo, yo he cometido un error, y no me he dado cuenta porque para el compilador es correcto.

En cambio, si yo hubiera especificado previamente la cláusula @Override, entonces el compilador ahora sí sabría que mi intención no es "sobrecargar", si no que quiero "sobreescribir". Y entonces sí se quejará si cometo algún cambio en la "firma" del método.

Por eso la cláusula @Override es importante. Porque así informo al compilador de cuál es mi intención (sobreescribir), aunque luego por despiste sin darme cuenta haga otra cosa diferente (sobrecargar), momento en el cuál el compilador me mostrará un warning

906
Aprender a programar desde cero / Re:iniciandome en java
« en: 09 de Noviembre 2017, 23:49 »
muchas gracias, me sabia mal preguntar tanto  :P
ya estoy con BlueJ haciendo los primeros programas y me gustaria saber donde estan las soluciones, pone en el archivo del curso que en los foros podemos encontrarlos. Estoy ahora con el de aviones.
Un saludo.

Hola.

En el foro encontrarás las soluciones propuestas por otros compañeros que también se inciaron como tú, con las posibles correcciones aportadas por otros compañeros más expertos.
Puedes probar a buscar usando el identificado de cada capítulo del curso, ese que es algo así --> CU00632B

Por otra parte, es mejor si en lugar de buscar las soluciones de otros, intenta hacer la tuya y, salga bien o mal..., la publiques aquí en el foro y entre todos te ayudamos a corregir o aclarar lo que sea necesario.

Saludos

907
Aprender a programar desde cero / Re:iniciandome en java
« en: 08 de Noviembre 2017, 00:30 »
Revisa la configuracion de las variables de entorno, tal y como se explica aqui

Por otra parte, el 99,9% de las veces NO vas a compilar desde la línea de comandos.
Lo normal es compilar desde un IDE (entorno de desarrollo) como NetBeans, Eclipse, IntelliJ, o BlueJ que es el que se propone en el curso para iniciar el aprendizaje..... y a todos estos les da igual como estén configuradas las variables de entorno.

Con esto quiero decirte que si ahora no consigues hacer funcionar lo de compilar desde la linea de comandos, no le dediques mucho tiempo, no es tan importante.
Sigue adelante con el curso y ya habrá tiempo de solucionar eso más adelante.

Y no dudes en preguntar todas las dudas que necesites  ;)

908
Aprender a programar desde cero / Re:iniciandome en java
« en: 07 de Noviembre 2017, 22:46 »
¿Como se llama el archivo de instalación que has descargado?

Es posible que hayas descargado el "entorno en tiempo de ejecución" (Java Runtime Environment o JRE) en lugar del "entorno de desarrollo" (Java Development Kit o JDK)

Para crear programas Java, necesitas el JDK, que a su vez ya contiene también el JRE.

Pincha aqui y descarga el JDK de Java SE version 9.0.1 acorde a tu sistema operativo.
Asegurate de que el archivo que obtienes al descargar su nombre empieza por jdk-xxx




909
Aprender a programar desde cero / Re:Ayuda con ejercicio java
« en: 07 de Noviembre 2017, 02:19 »
(..continua del post anterior..)

Este es el método nuevoContacto()
Código: [Seleccionar]
static void nuevoContacto()
    {
    if (indiceArreglo == 50)
    System.out.println("\nLa Agenda esta llena. No caben nuevos contactos");
    else
    {
    System.out.print("\nIndique si es una (E)mpresa o una (P)ersona (E/P): ");
char opcion = sc.nextLine().toUpperCase().charAt(0);

switch (opcion)
{
case 'E':
agenda[indiceArreglo] = pedirDatosEmpresa();
indiceArreglo++;
break;
case 'P':
agenda[indiceArreglo] = pedirDatosPersona();
indiceArreglo++;
break;
default:
System.out.println("No se reconoce la opcion indicada: " + opcion);
}
    }
    }

Lo primero que hace es comprobar si la agenda esta llena o no.
La forma que tenemos de saber si podemos añadir nuevos Contactos, y en que posicion del arreglo debemos añadirlo, es valiendonos de una varaible int que yo he llamado indiceArreglo

Al iniciar el programa, su valor es 0.
Esto significa que tenemos 0 contactos.
Y además significa que el primer contacto que añadamos, se colocará en la posición 0. Tras añadir el contacto, su valor se incrementa y ahora valdría 1.

Esto significaría que tendríamos 1 Contacto creado, que está en la posicion 0 (indiceArreglo - 1).
Y significaría que el próximo Contacto se añadiría en la posición 1.

Y así sucesivamente.

Por eso empezamos preguntando si indiceArreglo == 50. Porque si ya vale 50, significa que ya tenemos Contactos desde la posicion 0 a la 49 del arreglo, y entonces ya no queda sitio para nuevos Contactos

Si no vale 50, es que podemos añadir nuevos Contactos.
Pero primero tenemos que saber si se quiere añadir una Empresa o una Persona, así que se lo preguntamos al usuario mediante un simple char.
Aquí, para no complicar más el código, hacemos la pregunta confiando en que el usuario no se equivocará y sabrá elegir una opcion buena.
Se podría hacer un metodo similar al de pedirOpcion() comentado anteriormente, que compruebe que el usuario mete una opción valida y se repita la petición si no es así.
Pero no vale la pena complicar más el código en este momento.

Tras pedir el char, analizamos que ha elegido. Si es una Persona, metemos en la posicion que nos indica indiceArreglo, el objeto resultante del método pedirDatosPersona() e incrementamos el indice del arreglo.
Si es una Empresa, hacemos lo mismo pero con el método pedirDatosEmpresa().

pedirDatosPersona() y pedirDatosEmpresa() son métodos que piden al usuario los datos necesarios para crear un objeto de una de estas dos clases y los retorna ya listos para que podamos introducirlos directamente en el arreglo.


Código: [Seleccionar]
static Persona pedirDatosPersona()
    {
    System.out.print("\nIntroduzca ID: ");
int id = sc.nextInt(); sc.nextLine();
System.out.print("Introduzca Nombre: ");
String nombre = sc.nextLine();
System.out.print("Introduzca E-Mail: ");
String email = sc.nextLine();
System.out.print("Introduzca DNI: ");
String dni = sc.nextLine();
System.out.print("Introduzca numero celular: ");
String celular = sc.nextLine();

return new Persona(id, nombre, email, dni, celular);
    }

Código: [Seleccionar]
static Empresa pedirDatosEmpresa()
    {
    System.out.print("\nIntroduzca ID: ");
int id = sc.nextInt(); sc.nextLine();
System.out.print("Introduzca Nombre: ");
String nombre = sc.nextLine();
System.out.print("Introduzca numero tlf fijo: ");
String fijo = sc.nextLine();
System.out.print("Introduzca URL pagina web: ");
String web = sc.nextLine();
System.out.print("Introduzca numero empresa: ");
String nEmpresa = sc.nextLine();

return new Empresa(id, nombre, fijo, web, nEmpresa);
    }


Como ves, hacer uno o varios métodos especificos para determinadas tareas, puede parecer engorroso, pero en realidad hace que el código sea mucho más fácil de entender, mucho más fácil de mantener y mucho más fácil de reaprovechar.
Estos metodos para pedir datos de persona o empresa, pueden reutilizarse en otros métodos, e incluso en otras clases..

Creo que no haya nada más que comentar, si tienes alguna pregunta, dispara...

910
Aprender a programar desde cero / Re:Ayuda con ejercicio java
« en: 07 de Noviembre 2017, 02:01 »
Vamos comentando algunas cosas.

Primero, en la clase Contacto te falta el atributo de ID. Has de incluirlo si luego en el programa queremos buscar contactos por ID.
Otra opcion sería prescindir del ID y buscar por nombre, pero casi queda mejor hacerlo usando un atributo ID.

Segundo, el arreglo lo has declarado de tipo Object. Esto, funciona bien, pero no es lo ideal.
El tipo Object, es algo así como la clase "universal" de Java, todas las clases, incluso las creadas por ti mismo... heredan de la clase Object automaticamente, sin necesidad de indicarlo en ninguna parte.

Esto significa que en ese arreglo, puedes meter objeto de las clases Persona y Empresa sin problemas. Pero también significa que podrías meter un objeto String, un objeto Scanner, un objeto JButton, un objeto JPanel, un objeto Random, un objeto Date.... en definitiva, en ese arreglo se puede meter CUALQUIER cosa.

Lo ideal es limitarlo a las clases con las que queremos trabajar. Estas clases son Persona y Empresa, que todas ellas heredan de la clase abstracta Contacto.
Así que para ello, el arreglo interesa declararlo como de tipo Contacto, esto nos permite meter Personas y Empresas en ese arreglo, y nada más.


Sobre el menu, si queremos que salga varias veces hasta que el usuario decida terminar el programa, no queda otra que incluirlo dentro del bucle.
Puesto que la opción para finalizar el programa es que el usuario introduzca un 5, pues la condición del bucle es que se repita mientras la opcion sea distinta de 5

Sobre el código que estamos escribiendo, siempre es mejor dividirlo en porciones, usando varios métodos, de manera que el main quede reducido al menor número de lineas posibles.
Esto además es útil para que el código sea más legible y nos es más fácil aclarar ideas, pues muchas veces nos atascamos porque tenemos en pantalla tal cantidad de lineas e instrucciones, que la cabeza se nos embota...

Se puede hacer un método que se encargue únicamente de mostrar el menú. No hará nada más, solo eso, mostrar el menú.
Por ejemplo:
Código: [Seleccionar]
static void mostrarMenu()
    {
    System.out.println("\n");
    System.out.println(" 1 - Agregar contacto");
        System.out.println(" 2 - Buscar contacto por ID");
        System.out.println(" 3 - Editar contacto");
        System.out.println(" 4 - Mostrar todos los contactos");
        System.out.println(" 5 - Salir\n");
    }
Los "\n" es para que haga saltos de linea, asi cada vez que se escriba el menu en pantalla saldrá algo separado del texto de la anterior operacion que hubieramos hecho.
Como ves, es un método muy simple, tan solo escribe lineas de texto en pantalla.
Pero al ponerlo por separado, permite reducir lineas en el main, ya que nos bastará una sola linea para llamarlo en lugar de tener que poner las 6 lineas necesarias para escribir el menu.

Luego, podemos hacer otro método que se encargue de pedir la opcion, y de hecho podemos hacer que sea de tipo boolean, de manera que solo devuelva true si se ha introducido una opción válida (numero de 1 a 5).
Si se introduce cualquier otro numero, o una letra, devolverá false y podemos hacer que se repita la petición de la opción mientras este método devuelva false
Este podría ser el método para pedir la opcion:

Código: [Seleccionar]
static boolean pedirOpcion()
    {
    try
    {
    System.out.print("\nIntroduzca opcion: ");
    opcion = sc.nextInt(); sc.nextLine();//Tras leer valores numericos, interesa hacer un nextLine() para limpiar el stream.
    if (opcion >= 1 && opcion <= 5)
    return true;//Ha introducido una opcion valida
    else
    {
    System.out.println("Error. Solo se admite valor entre 1 y 5.");
    return false;//Opcion invalida
    }
    }
    catch(Exception e)
    {
    sc.nextLine();//De nuevo, es necesario limpiar el stream
    System.out.println("Error. Introduzca solo numeros, entre 1 y 5.");
    return false;//Ha introducido letras o simbolos, no números, lo cual provoca una excepcion
    }
    }

Aquí a lo mejor te parece un poco raro eso de hacer "un nextLine() para limpiar el stream".
La clase Scanner es un poco imperfecta, y tras leer valores numéricos, conviene hacer un nextLine() (sin asignar a ninguna variable) si luego queremos leer datos de tipo String (por ejemplo, nombres).
En este otro hilo lo explico un poco más a fondo.

Si quieres ver uno de los problemas que puede ocasionar, cuando el programa ya esté terminado, quita por ejemplo el nextLine() que hay dentro del catch, ejecuta el programa y mete una letra para forzar que ocurra la excepción por no haber metido un numero.
Verás la diferencia entre poner y no poner ese nextLine() que, aparentemente, no parece hacer nada útil....


Y ya puestos, podemos (casi que debemos) hacer un método para cada una de las opciones del menú: mostrar contacto, editar, listar....

Al dividir todo el programa en pequeños métodos (es lo que se llama programación modular), verás que el metodo principal main queda mucho más legible.
Y en caso de cometer algún error u olvidar algo, es mucho más fácil encontrar donde está el error/olvido ya que podemos irnos directamente al método en cuestión, en lugar de tener que recorrer arriba y abajo un metodo main enorme con cientos de lineas.

Si lo dividimos todo en pequeños métodos, que es lo ideal, surge un pequeño problema.
La mayoría de estos métodos necesitan que el arreglo de Contacto y el objeto Scanner para leer datos por teclado estén visibles para ellos.
Si declaramos el arreglo y el Scanner dentro del método main, como has hecho en tu código, estos métodos no podrán verlos, y no podrán acceder a ellos.
Para hacer que si sean visibles y cualquier método tenga acceso a ellos, tenemos que declararlos fuera del main, los declararemos como atributos de la clase Prueba.
Y han de ser declarados con la palabra reservada static, puesto que el main y el resto de método también serán estaticos.

Otras variables, como el int donde guardamos la opcion escogida por el usuario o la que nos dice hasta que posicion del arreglo tenemos Contactos registrados, también necesitarmos que sean visibles para varios métodos.

Si ahora mismo no tienes claro la diferencia entre estatico y no-estatico, no importa, podemos hablar de eso después. De momento centrémonos en hacer funcionar este programa.


Bien, mira, te dejo aquí una nueva clase Prueba, ya organizada, pero sin terminar.

Código: [Seleccionar]
package agendaContactos;

import java.util.Scanner;

public class Prueba {

    static Scanner sc = new Scanner(System.in);
    static Contacto agenda[] = new Contacto[50];
    static int opcion = 0;
    static int indiceArreglo = 0;
   
    public static void main(String[] args) {

        do{
        mostrarMenu();
       
        while(pedirOpcion() == false);
       
        switch(opcion)
        {
        case 1:
        nuevoContacto();
        break;
        case 2:
        buscarContacto();
        break;
        case 3:
        editarContacto();
        break;
        case 4:
        listarContactos();
        break;
        case 5:
        System.out.println("FIN DEL PROGRAMA");
        }
        }while(opcion != 5);

    }//Fin del metodo main()
   
    static void mostrarMenu()
    {
    System.out.println("\n");
    System.out.println(" 1 - Agregar contacto");
        System.out.println(" 2 - Buscar contacto por ID");
        System.out.println(" 3 - Editar contacto");
        System.out.println(" 4 - Mostrar todos los contactos");
        System.out.println(" 5 - Salir\n");
    }
   
    static boolean pedirOpcion()
    {
    try
    {
    System.out.print("\nIntroduzca opcion: ");
    opcion = sc.nextInt(); sc.nextLine();//Tras leer valores numericos, interesa hacer un nextLine() para limpiar el stream.
    if (opcion >= 1 && opcion <= 5)
    return true;//Ha introducido una opcion valida
    else
    {
    System.out.println("Error. Solo se admite valor entre 1 y 5.");
    return false;//Opcion invalida
    }
    }
    catch(Exception e)
    {
    sc.nextLine();
    System.out.println("Error. Introduzca solo numeros, entre 1 y 5.");
    return false;//Ha introducido letras o simbolos, no números, lo cual provoca una excepcion
    }
    }
   
    static void nuevoContacto()
    {
    if (indiceArreglo == 50)
    System.out.println("\nLa Agenda esta llena. No caben nuevos contactos");
    else
    {
    System.out.print("\nIndique si es una (E)mpresa o una (P)ersona (E/P): ");
char opcion = sc.nextLine().toUpperCase().charAt(0);

switch (opcion)
{
case 'E':
agenda[indiceArreglo] = pedirDatosEmpresa();
indiceArreglo++;
break;
case 'P':
agenda[indiceArreglo] = pedirDatosPersona();
indiceArreglo++;
break;
default:
System.out.println("No se reconoce la opcion indicada: " + opcion);
}
    }
    }
   
    static Persona pedirDatosPersona()
    {
    System.out.print("\nIntroduzca ID: ");
int id = sc.nextInt(); sc.nextLine();
System.out.print("Introduzca Nombre: ");
String nombre = sc.nextLine();
System.out.print("Introduzca E-Mail: ");
String email = sc.nextLine();
System.out.print("Introduzca DNI: ");
String dni = sc.nextLine();
System.out.print("Introduzca numero celular: ");
String celular = sc.nextLine();

return new Persona(id, nombre, email, dni, celular);
    }
   
    static Empresa pedirDatosEmpresa()
    {
    System.out.print("\nIntroduzca ID: ");
int id = sc.nextInt(); sc.nextLine();
System.out.print("Introduzca Nombre: ");
String nombre = sc.nextLine();
System.out.print("Introduzca numero tlf fijo: ");
String fijo = sc.nextLine();
System.out.print("Introduzca URL pagina web: ");
String web = sc.nextLine();
System.out.print("Introduzca numero empresa: ");
String nEmpresa = sc.nextLine();

return new Empresa(id, nombre, fijo, web, nEmpresa);
    }
   
    static void buscarContacto()
    {
    /*
    * Comprobar si existe al menos un contacto registrado.
    * Pista: Si indiceArreglo == 0, es que aún no hay Contactos registrados.
    * Si hay contactos en el arreglo:
    * Pedir ID del contacto que se quiere editar.
    * Recorrer arreglo hasta encontrar el Contacto con dicho ID
    * o hasta donde indique indiceArreglo, ya que quizás nos han dado un ID que no existe.
    *
    * Si se encuentra el Contacto, comprobar si es una instancia de Persona o Empresa,
    * hacer casting a la clase que corresponda y mostrar su datos actuales.
    * Pista: la instruccion instanceof nos dice cual es la clase con la que se instancio un objeto
    */
    }
   
    static void editarContacto()
    {
    /*
    * Comprobar si existe al menos un contacto registrado.
    * Pista: Si indiceArreglo == 0, es que aún no hay Contactos registrados.
    * Si hay contactos en el arreglo:
    * Pedir ID del contacto que se quiere editar.
    * Recorrer arreglo hasta encontrar el Contacto con dicho ID
    * o hasta donde indique indiceArreglo, ya que quizás nos han dado un ID que no existe.
    *
    * Si se encuentra el Contacto, comprobar si es una instancia de Persona o Empresa,
    * hacer casting a la clase que corresponda y mostrar su datos actuales.
    * Pista: la instruccion instanceof nos dice cual es la clase con la que se instancio un objeto
    *
    * Decidir si:
    * (Proceso fácil y rápido)
    * - Pedimos todos los datos completos otra vez y directamente sustituimos el contacto en la posicion del arreglo
    * donde encontramos el contacto que se quiere editar.
    * Se puede reaprovechar los métodos pedirDatosPersona() y pedirDatosEmpresa()
    *
    * (Proceso un poco más complejo)
    * - Preguntamos al usuario que atributo quiere modificar y solo nos ocupamos de ese atributo.
    * ESto es más complejo porque habría que mostrar nuevos submenus, distintos si es una Persona o una Empresa
    * y hacer más switch para ver que atributo se ha decidido modificar.
    */
    }
   
    static void listarContactos()
    {
    /*
    * Recorrer arreglo, hasta donde indique la variable indiceArreglo
    * y mostrar los datos de cada Contacto.
    */
    }
   
       
}
       

  • Los objetos y variables que necesitamos sean visibles para todos los métodos, están declarados ya como atributos estáticos.
  • El método principal main, está reducido a tan solo unas pocas líneas ya que todo el código importante estará separado en distintos métodos.
    Consta básicamente de un bucle do..while() (es prácticamente lo mismo que un while()) que se repetirá hasta que el usuario meta un 5 como ocpion.
    Cada vez que se repite:
    - llama al metodo que muestra el menu.

    - llama al metodo que pide opcion al usuario. Este metodo esta puesto como condicion de otro bucle while(), de este modo el metodo se repite cada vez que devuelve false.
    Recuerda que si devuelve false, es porque el usuario ha introducido una opcion equivocada.
    Esta linea te puede parecer un poco rara porque el metodo pedirOpcion() no está DENTRO del bucle while(), si no que está puesto como CONDICION.
    Esta es una forma de simplificar el codigo, en realidad el bucle while() esta vacío, carece de cuerpo.. simplemente comprobará la CONDICION (nuestro método pedirDatos()) una y otra vez hasta que devuelva TRUE, lo que significa que el usuario introdujo una opción válida.

    -Tras pedir opcion, ejecuta un switch y según la opcion introducida, llamará a los distintos métodos que se encargan de crear nuevo contacto, editar, mostrar o listar.
  • Después del main, vienen los métodos.
    El primero, el de dar de alta un contacto, te lo he dejado ya hecho. Fíjate que además se sirve de otros dos métodos que se dedican únicamente a pedir datos para crear y retornar un objeto Persona, o un objeto Empresa.
    Luego lo comentamos un poco más a fondo.
  • El resto de métodos estan sin hacer, aunque he puesto comentarios sobre más o menos los pasos que habría que seguir.
    Intenta hacer tu lo que puedas.
    El metodo de editarContacto es cierto que es un poco más dificil que el resto, en los comentarios ya he puesto que habría que decidir entre dos formas de hacerlo, una más simple y fácil y otra un poco más complicada.
    Podríamos hacer de momento la forma fácil, y una vez que esté terminado todo y funcionando, atrevernos con la forma difícil.
    En realidad esta segunda forma de hacerlo no es dificil, es solo que requiere mucho más código porque habría que presentar un nuevo submenú para que el usuario decida qué atributo quiere modificar, submenús que serán distintos segun si estamos con una Empresa o una Persona..

Para no hacer posts tan grandes, debajo posteo otro mensaje explicando un poco el método nuevoContacto()

911
Aprender a programar desde cero / Re:Ayuda con ejercicio java
« en: 05 de Noviembre 2017, 19:12 »
Hola compañero,

Están correctas.
Solo cabe mencionar unas cositas.

  • Has añadido un nuevo atributo, el ID, que yo no lo puse. Se supone que este atributo pertenece a la clase "padre" Contacto y de hecho en el constructor se lo transmites mediante la instrucción super() al igual que el nombre.
    Esto es correcto.
    Pero entonces a la clase Contacto hay que añadirle dicho atributo, hay que ponerlo también en su constructor, y los metodos setID() y getID() deberían estar escritos en la clase Contacto.
    Las clases Persona y Empresa los heredarán, así que no es necesario que ellas tengan estos métodos.
  • Sobre los atributos y su visibilidad o alcance (scope), la cuál puede ser: private, protected, public o friendly

    Cuando no se pone nada al atributo, tal y como tu has hecho, los estás declarando como friendly. Esto significa que otras clases contenidas en el mismo package podrían acceder directamente a estos atributos sin tener que usar los getters y lo setters.

    ¿Esto es algo malo? Pues no necesariamente. En este caso nos da un poco igual, pero por lo general, lo recomendable es declarar los atributos siempre como private, incluso en los casos en los que nos da igual sea cual sea su visibilidad.
    En determinadas ocasiones nos facilitará el trabajo ampliar la visibilidad de determinados atributos y entonces si podemos aumentarla con protected, friendly o public en casos extremos.
    Pero por "convencionalismo", en principio los atributos deberían ser privados y controlar su acceso mediante los métodos getter y setter.
  • Por último, una reflexión sobre el tipo de dato int.
    Por ejemplo, para telefonoCelular y dni has optado por usar el tipo de dato int, que es un dato numérico.
    Normalmente, nos interesará usar int solo en datos que representen cantidades, valores y/o de los cuáles esperamos hacer algún tipo de operación aritmética. Por ejemplo la edad, peso, estatura, distancias, temperaturas....

    Cuando no sea este el caso, lo más probable es que nos interese más usar el tipo de dato String.
    En principio, no es de esperar que vayamos a hacer operaciones aritméticas con el teléfono o el dni.
    Además, teléfono y dni son susceptibles de incluir simbolos y letras que no son admitidos por el tipo int.

    Por ejemplo para el teléfono puede ser necesario que indiquemos el prefijo del pais, que siempre empieza con un símbolo + --> +34678990011
    O en el caso de una Empresa, además del teléfono principal de esta, quizás también queramos especificar la "extensión" de nuestro contacto --> 934568912 ext:2216
    O especificar más de un teléfono con un separador: 934567890 / 934567891

    Para el dni, lo mismo. Normalmente en la mayoría de paises estos números incluyen letras de control --> 567452390-X
    A veces estas letras de control son importantes para determinar si el dni es de uan persona física, ya sea un particular o un autónomo (quien entonces sería una Empresa) o si es el identificador fiscal de una empresa.

    Otra ventaja de usar String es que luego nos facilita filtrar búsquedas en nuestra Agenda.
    Por ejemplo, quizás queramos listar todos los contactos cuyo teléfono pertenezca a la region de Madrid en España, es decir, los que empiezan por +3491xxxxxx
    O los de Acapulco en México, es decir, los que empiezan por +52744xxxxx

    Este tipo de búsqueda no podemos hacerla con un valor int (al margen de que no admite siquiera el simbolo +), porque no podemos extraer de él cifras numéricas concretas. Un int nos da un valor total, si queremos descomponerlo en cifras separadas, hay que transformarlo en un String.
    Pero entonces, mejor declararlo directamente como String.

    Como digo, esto es solo una reflexión que podemos hacernos a la hora de escoger el tipo de dato de un atributo.
    Aunque sea un atributo tipicamente representado mediante números, esto no implica que debamos usar tipos numéricos como int o double. De hecho, como hemos visto, en muchos casos nos interesa usar String.

Al margen de estos detalles, tu código está correcto.

Ahora viene el siguiente paso.
Ya hemos creado las clases básicas que representan los datos que queremos registrar y gestionar.
Ahora hay que decidir como registrarlos y gestionarlos.

El enunciado que has propuesto indica que usemos un arreglo de 50 posiciones. (Sería más fácil usando por ejemplo un ArrayList, que no hay que indicarle un tamaño fijo, puede ir creciendo y menguando dinámicamente según se añaden o eliminan registros)

Bien, este arreglo se podría declarar directamente en la clase principal main, es decir, la que realiza la ejecución del programa, y escribir en ella los métodos necesarios para mostrar el menú y los métodos para realizar las acciones necesarias: añadir contacto, mostrar, editar, etc...
Esto sería correcto y podría funcionar perfectamente.

Pero quizás sería más interesante crear otra clase, que podríamos llamar Agenda, cuyo atributo sea precisamente el arreglo de 50 posiciones donde se registrarán los Contactos.
Esta clase tendrá además los métodos necesarios para gestionar la Agenda: añadir contacto, mostrarlo, editarlo y listar la agenda completa.

Este podría ser su UML:


Quedando así el diagrama UML completo:



Así que, intenta si quieres crear esta nueva clase Agenda.
Esta clase no es abstracta, no hereda nada de Contacto, ni Contacto hereda nada de Agenda. (Fíjate en el diagrama UML, que las flechas son distintas)

Son clases diferentes, pero están relacionadas porque Agenda incluye a la clase Contacto como tipo de dato para su atributo, que es el arreglo de 50 posiciones.

Esta clase puede ser un poco más dificil de escribir, porque ahora hay que decidir como programar cada una de las funciones.
Por ejemplo, al añadir un nuevo Contacto, ¿como decidimos en que posición del arreglo lo vamos a guardar?
¿Deberíamos usar un segundo atributo, una variable int por ejemplo, que nos diga cuál es la primera posición que está libre en el arreglo?
La primera vez que ejecutemos el programa, la primera posición libre será [ 0 ] porque aún no hay contactos registrados.
Cuando registremos al primer contacto, la siguiente posición libre será [1], luego será [2], etc... así que cada vez que registremos un contacto podemos incrementar esta variable para saber en todo momento la siguiente posicion libre.

O tal vez otra forma podría ser, al inicializar el objeto Agenda, rellenar los 50 registros con valor null.
Y al querer añadir un nuevo Contacto, recorrer el arreglo y ahí donde encontremos el primer valor null disponible, lo cambiamos por el nuevo contacto.
Es otra forma, pero tal vez la primera sea más rápida ya que en todo momento sabremos directamente la primera posición disponible. En cambio en la segunda forma hay que estar buscando registros null cada vez que añadimos contacto nuevo.

Elige la que más te guste, o idea otra forma de hacerlo que te parezca mejor.

Intenta escribir todo lo que puedas para esta clase Agenda y si te atascas en algún sitio, pues aquí estaremos.

Un saludo. :D

912
Aprender a programar desde cero / Re:Ayuda con ejercicio java
« en: 05 de Noviembre 2017, 01:12 »
Hola Dysloke.

El ejercicio no es complejo, pero si te lo damos ya hecho, te va a costar más entenderlo que no si intentas hacerlo tú, por supuesto eso sí, con nuestra ayuda.

Al tratarse de un ejercicio con varias clases, ya no es solo cuestión de dominar la sintaxis de Java o la lógica de la programación, si no que hay que decidir como enfocarlo.
Esto no se debe solucionar escribiendo todo el código en un único archivo (se puede, pero no es lo óptimo). Cada clase, se ha de escribir por separado, en su propio archivo .java.

Esto permite además, afrontar el ejercicio separado en partes (divide y vencerás...) de modo que podemos concentrarnos en "pequeñas cosas" en lugar de "un gran todo".

De momento, olvídate del arreglo, y del menú de opciones, etc...eso ya lo veremos después.

Lo suyo es empezar a concentrarnos en las clases básicas. Y una buena forma de organizar ideas antes de empezar a teclear código "a lo loco", es hacerse un diagrama UML.
UML es una serie de convenciones a seguir para crear diagramas que representen las clases de un programa, y como se relacionan entre ellas.
No te preocupes ahora por aprender dichas convenciones, eso es lo de menos... básicamente las clases se dibujan como un cuadrado donde dentro está su nombre, están contenidos los atributos de la clase indicando su tipo (String, int, double, boolean,...) y lo mismo con sus métodos... no necesariamente todos, pero si los principales.

Dichas clases se unen mediante flechas para indicar quien implementa a quien, o quien hereda de quien,.... ahora te pondré unas imágenes y lo entenderás enseguida. Es muy fácil.

Hacer un UML previo, aunque no cumpla convenciones ninguna y esté hecho "a nuestra manera", incluso con un lápiz y papel.... nos permite hacernos una idea de que código necesitaremos escribir y como estructurarlo.

Pero primero, ¿cuál es el objetivo del programa?
El objetivo del programa es registrar y gestionar contactos, que pueden ser personas o empresas.

De aquí, ya podemos deducir que clases básicas necesitamos crear.

La clase "padre" podría ser Contacto. Esta clase tendría dos clases "hijas": Persona y Empresa.

Expresado esto en términos de Programación Orientada a Objetos (POO), Contacto sería la clase abstracta, y de esta heredarían las clases Persona y Empresa.

Bien, la clase Contacto, ¿que atributos debería tener? En principio, lo normal es que tenga los atributos que sean comunes entre sus clases "hijas".

Persona y Empresa son muy diferentes, pero tienen un atributo en común, el nombre
Pues este debería ser el atributo que tenga la clase "padre" Contacto.
Esta clase, además, tendrá al menos el método abstracto mostrarContacto().
También tendrá su constructor y el correspondiente getter y setter para su atributo nombre.

Esta será el diagrama UML de la clase abstracta Contacto:


Tiene un atributo, nombre, de tipo String.

Metodos, como hemos dicho:
  • su constructor, que recibe como parametro el nombre de tipo String -> Contacto(String nombre)
  • el método abstracto -> void mostrarContacto(), que es de tipo void, ya que no devuelve ningún valor, sino que mostrará en pantalla los atributos del objeto.
  • un método getter para poder obtener el nombre del objeto, así que devuelve un String ->String getNombre()
  • un método setter, para poder modificar el nombre si quisieramos, así que recibe un String con el nuevo nombre y no devuelve ningún valor -> void setNombre(String nombreContacto)

Bien, las clases Persona y Empresa, tendrán sus propios atributos (el atributo nombre lo herederá de su "padre" Contacto) y sus própios métodos, incluyendo el método mostrarContacto() que es abstracto. Es decir, lo heredan de su padre Contacto, pero el código de este método será distinto para Persona y Empresa, ya que tienen distintos atributos.
Cada una tendrá sus getters y sus setters.

Esta podría ser la clase Persona:


Y esta la clase Empresa:


Y este sería el diagrama completo, donde se indica que las clases Persona y Empresa, heredan (son hijas) de la clase abstracta Contacto:



Vale, esto ya nos da un "boceto" de las clases básicas (con sus atributos y métodos) que necesitamos para empezar ya a escribir algo de código.

Empezaremos por escribir la clase Contacto. Dices que estás iniciándote y aún no dominas la sintaxis Java.

Bien, esta primera clase te la escribo yo.

Citar
package agendaContactos;

public abstract class Contacto {
   
   //atributo
   private String nombre;
   
   //Constructor
   public Contacto(String nombreContacto)
   {
      nombre = nombreContacto;
   }
   
   //metodo abstracto, sin código, ya lo implementarán sus clases hijas
   public abstract void mostrarContacto();
   
   //metodo para cambiar (setter) el nombre de este contacto
   public void setNombre(String nombreContacto)
   {
      nombre = nombreContacto;
   }
   
   //metodo para obtener (getter) el nombre de este contacto
   public String getNombre()
   {
      return nombre;
   }

}

Como ves, son unas pocas líneas y contienen lo que habíamos establecido en su diagrama UML.

Ahora te invito a que intentes a escribir tú el código de las clases Persona y Empresa.
No tengas miedo a equivocarte, o a no ser capaz de completarlo.
Tú inténtalo.
Si lo completas, bien.
Si te atascas y no sabes terminarlo, no importa. Publica aquí lo que hayas podido escribir y entre todos lo corregimos y te indicamos como continuarlo.

De hecho, es la única forma de aprender. Que te atasques y tengas que preguntar o investigar.
Cuando lees el código de otros ya terminado, normalmente se entiende más o menos casi todo y CREES que ya has aprendido.
Pero no, para aprender tienes que atascarte y equivocarte escribiendo tú el código, y luego preguntar para poder seguir.

Cuanto tengamos las tres clases básicas terminadas, ya pensaremos en como hacer lo del arreglo, el menú de opciones, etc...

913
Si es para Android, pues Android Studio sin duda..

Ahora bien, Android Studio no te va a hacer ninguna app por si sola. Se requiere que primero tengas conocimientos de Metodología de la programacion, conocimientos de Java (o C++ como alternativa) y unas nociones básicas de lenguaje de marcas XML.

Más luego, además, nociones de como funciona el sistema Android (qué es una Activity, cuales son sus distintos "Ciclos de vida"..., etc...)

Android Studio te facilita muchísimo la creación de una app, pero no es cuestión de ir haciendo clicks aquí o arrastrando ventanitas por allá..
Los conocimientos y la lógica que ejecutará el programa, ha de salir de tu cerebro, así que previamente hay que aprender a programar, y creo que empezar directamente con Android no es buena idea.

914
Aprender a programar desde cero / Re:ayuda con java
« en: 27 de Octubre 2017, 23:48 »
soy nuevo en esto me en la escuela me pidieron realizar un programa que pida 14 numero y diga cuantos son pares y cuantos impares. usando if

Hola.
El ejercicio que te plantean es sencillo, pero tienes que hacerlo tú, no nosotros... más que nada es que si lo hacemos nosotros no te estaremos beneficiando en nada.

Con esto quiero decirte que empieces planteando al menos un código escrito por tí, aunque no esté completo, al menos un programa que pida los 14 números, aunque luego no sepa discernir si un número es par o no...

A partir de ahí te podemos aclarar las dudas y ayudarte a completarlo. Pero tenemos que hacerlo a partir de un código escrito por tí, ya sea en Java o pseudocódigo.


Como pista, puedo decirte que para discernir si un número es par o no, el "truco" es dividirlo entre 2 y comprobar si su "resto" es 0 ó no.
Si el resto de la division es 0, entonces es un número par.
Sino, entonces es un número impar.

Comienza escribiendo un código que pida 14 números. Y luego investiga cómo obtener en Java el resto o residuo de una división.
Si no lo consigues, entonces te lo explicaremos aquí.

Si no tienes los conceptos básicos puedes encontrarlos en el curso de programación Java desde cero en https://aprenderaprogramar.com/index.php?option=com_content&view=category&id=68&Itemid=188

Un saludo.

915
La clase Scanner de Java tiene una pequeña peculiaridad que puede ser bastante molesta.

Cada vez que lees por teclado un valor numérico, por ejemplo en:

Citar
this.edad = sc.nextInt();

Para introducir un valor, tu tecleas el valor y luego pulsas la tecla return/intro para que el valor sea recogido por el programa.
Entonces, en el flujo de datos (stream) ahora mismo se encuentran los caracteres de los valores que has introducido, por ejemplo 23, pero también está el caracter que corresponde a la tecla return, que es \r. (También conocido como retorno de carro CR)
Es decir, en el stream tendríamos esto:
Código: [Seleccionar]
23\r
Java, cuando lee números con los métodos adecuados (nextInt(), nextDouble(), nexftFloat(),....)  recoge el valor numérico, pero deja en el flujo de datos el caracter \r porque no es un número, y por lo tanto lo ignora.

Esto significa que después de que hayas leido la edad, en el stream todavía tenemos esto:
Código: [Seleccionar]
\r
El programa sigue su ejecución, con ese \r en el stream, aburrido y esperando a que venga alguien que no lo ignore, que sí quiera leerlo y recogerlo como valor.

El método nextLine(), si que lo recogerá, aunque el caracter \r no tenga representación visual como el resto de caracteres alfanuméricos ('a', 'G', 'h', '1', '%',.. etc), nextLine() lo recogerá y lo sacará del flujo de datos.
Porque de hecho, ese \r es quien le indica a nextLine() que el usuario ha terminado de introducir la "linea de datos" y ya puede recoger lo que se haya tecleado.

Y aquí es donde viene el problema.
Si tras leer la edad, haces una lectura de valores "no numéricos" , por ejemplo el nombre de un nuevo contacto, con nextLine():

Citar
System.out.println("Dame el nombre");
        this.nombre = sc.nextLine();

Este nextLine() se va a encontrar con la situación de que en el stream ya hay un \r, el que había quedado ignorado tras leer la edad.
Y entonces nextLine() se cree que lo que pasa es que el usuario ha pulsado ya la tecla return, cuando en realidad no ha tenido ocasión de teclear nada todavía, y entonces recoge una "cadena vacía" que termina con el caracter \r (que ahora sí es recogido).

Y por lo tanto el programa continua pasa a la siguiente inserción de datos:
Citar
System.out.println("Dame la direccion");
        this.direccion = sc.nextLine();

Este nextLine() si que se encuentra el stream totalmente vacío, así que ahora si que esperará a que el usuario introduzca datos hasta que realmente pulse la tecla return.

Por esto el usuario percibe que Java se ha "saltado" la inserción de datos para el nombre del contacto. Pero en realidad no se la ha saltado, lo que ha ocurrido es que un \r olvidado en el flujo de datos le ha hecho creer que el usuario ha pulsado la tecla intro.


Este error es muy puñetero y un auténtico dolor de cabeza cuando nos iniciamos en la programación en Java. Porque es tan tonto y absurdo, que no somos capaces de entender cuál es el problema.

Afortunadamente, es sencillisimo de solucionar.

Basta con que hacer un nextline() "extra" cuando hayamos terminado de introducir datos numéricos.
Este nextLine() no hace falta que guarde el dato recogido en una variable, simplemente llamamos al método y punto.
Citar
this.edad = sc.nextInt();
sc.nextLine();
Así, tras leer la edad y guardarla en la variable edad, quedará un \r en el flujo de datos.
Pero el siguiente nextLine() lo recogerá y como no está asignado a ninguna variable, simplemente el \r desaparece y ya tenemos el stream limpito para no tener problemas en la próxima lectura de datos.

Pruébalo, pon un nextLine() extra tras cada lectura de datos numéricos.
Por ejemplo también en el menú:

Citar
System.out.println("9-. Salir");
System.out.println("opcion -->");
op = sc.nextInt();
sc.nextLine();//Para limpiar el flujo de datos
            switch (op) {
                case 1:


Seguro que con esto evitas este problema.

Otra forma de evitarlo es utilizar únicamente el método nextLine() para recoger datos y luego, si quieres valores numéricos, parsearlo, por ejemplo.
En lugar de esto:
Citar
this.edad = sc.nextInt();
Hacemos esto:
Citar
String datoEdad= sc.nextLine();
this.edad = Integer.parseInt(datoEdad);

Así tienes un valor numérico y evitas dejar \r ignorados en el flujo de datos.

Son dos formas distintas de esquivar este problema, no hay una mejor que otra. Yo suelo usar la primera forma, la de meter nextLine() extra tras leer números.

Comentanos si esto te ha solucionado el problema, de lo contrario, buscaremos otro motivo.
Un saludo


916
Aprender a programar desde cero / Re:Guía
« en: 09 de Septiembre 2017, 00:10 »
Hola,
empieza practicando con pseudocódigo

Pseudocódigo es una simulación de lenguaje de programación que sirve para aprender las nociones de algoritmia comunes a todos los lenguajes.

Es decir, aprender a programar consta de básicamente dos partes.
Una, aprender como resolver problemas usando la lógica de los ordenadores (algoritmia).
Dos, aprender un lenguaje de programación para poner en práctica dicha algoritmia.

Aprender ambas cosas a la vez es un poco arriesgado, porque a veces se pierde más tiempo en aprender las instrucciones y peculiaridades de un lenguaje, en lugar de conseguir desarrollar la algoritmia que es lo realmente importante.

Por eso, lo ideal es empezar con pseudocódigo, un lenguaje "inventado" y simplificado para poner en juego la algoritmia sin complicarse con tener que aprender un lenguaje real.
Por ejemplo, para sacar un simple mensaje en pantalla, cada lenguaje lo hace de forma distinta, algunos incluso de forma absurdamente complicada:
Citar
C
printf("Aprender a Programar");
C++
std::cout << "Aprender a Programar";
C#
System.Console.WriteLine("Aprender a Programar");
Arduino
Serial.println("Aprender a Programar");
BASIC
10 PRINT "Aprender a programar"
Java
System.out.println("Aprender a Programar");
JavaScript
console.log("Aprender a programar");
PHP
echo 'Aprender a Programar';
.....
PostgreSQL
CREATE FUNCTION mensaje_aprender() RETURNS text AS $$
BEGIN
RETURN 'Aprender a Programar';
END
$$ LANGUAGE plpgsql;

SELECT mensaje_aprender();

En cambio, en pseudocódigo podemos resolverlo con un simple:
Citar
ESCRIBIR "Aprender a Programar"

Esta instrucción no es real, no es algo que pueda compilar un ordenador. Pseudocódigo está pensado para que, con papel y boli, practiquemos y desarrollemos algoritmos de forma sencilla de modo que solo tengamos que preocuparnos de aplicar la lógica de la programación.

De hecho un buen programador profesional primero hará un esbozo del programa en pseucódigo antes de ponerse a escribir código real.

Una vez somos capaces de desarrollar algoritmos usando la lógica de la programación, podemos elegir un lenguaje y empezar a hacer nuestros primeros programas reales.

Esto supone que la programación al principio puede ser tediosa de aprender.
Primero todo es algo teórico, haciendo pseudocódigo en un papel.
Luego por fin podemos hacer algo práctico en un lenguajer real, pero será todo en modo texto, mensajes en una consola de comandos.

Puede pasar mucho tiempo antes de que empieces a crear una interfaz de ventanas y botones.... pero es que aquí no hay atajos y es necesario empezar por lo básico desde el principio y armarse de paciencia.

Afortunadamente, existe un programa llamado PseInt, que interpreta el pseudocódigo como si fuera un lenguaje de programación real y podemos ver funcionar nuestros programas sin haber aprendido antes un lenguaje de programación.
Esto hace más ameno el proceso de aprendizaje.

Pero vamos, como dice el famoso dicho: La paciencia es la madre de todas las ciencias.

Ánimo, que el camino puede ser algo largo, pero vale la pena recorrerlo.

917
Gracias!!

Luego miraré de hacer pruebas, pero no comprendo el por qué se expresan así estos sleep();

Código: [Seleccionar]
Thread.sleep(1*1000);
Thread.sleep((1/1)*1000);
Thread.sleep(1*800)

¿Por qué no ponerlos así?
Código: [Seleccionar]
Thread.sleep(1000);
Thread.sleep(1000);
Thread.sleep(800)

Los tiempos solicitados son los mismos, pero supongo que hay alguna razón para realizar esas multipliaciones que no alteran el tiempo solicitado.
A ver si alguien me lo puediera explicar...

Gracias de nuevo.  ;)

918
Hola a todos,

vereis, a modo de práctica, me he propuesto hacer un especie de jueguecito de rol por turnos en Java, donde desplazo a un personaje por un tablero y puedes encontrar muros, agujeros, cofres y, por supuesto,  enemigos.
No es nada serio, el motivo es más bien practicar y aprender nuevas cosas de la libreria Swing y tal...aunque obviamente para hacer juegos hay otras herramientas más adecuadas.

Voy bastante avanzado y seguramente más adelante iré pidiendo cierta ayuda. Pero ahora mismo tengo un problemita de escasa importancia.

Cuando se inicia un combate por turnos, aparede un JDialog con imagenes del jugador y el enemigo, botones.. y abajo un JTextArea donde se va mostrando la información del proceso del combate: Quien ataca, que daños ha causado, si ha fallado el ataque.. etc...

Mi intención es que tras cada linea de información, que agrego al area de texto, haya una pequeña pausa temporal (un delay) hasta que ocurra la siguiente acción.

Lo he intentado con un pequeño método que he llamado delay(), al cual le paso un tiempo en milisegundos y uso el método Thread.sleep() para que se detenga la acción.

Código: [Seleccionar]
private void delay(long milis)
{
try {
Thread.sleep(milis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Así, lo que hago es llamarlo varias veces en determinados momentos para pausar "la acción" del combate. Os pongo un método en donde lo llamo, a modo de ejemplo (es un método incompleto, aun en construcción..)

Citar
@Override
      public void actionPerformed(ActionEvent arg0) {
         pJugador.pBotones.ataque.setEnabled(false);
         pJugador.pBotones.huida.setEnabled(false);
         delay(1000l);
         pInfo.addTexto("\n\t************************\n");
         pInfo.addTexto(jugador.getNombre() + " ataca con " + jugador.getInventario()[0].getNombre());
         delay(1000l);
         int ataqueJugador = atacar(jugador);
         int defensaCPU = defender(CPU);
         int resultado = ataqueJugador - defensaCPU;
         if  (resultado <= 0)
         {
            pInfo.addTexto("Daños causados: 0");
            delay(1000l);
            pInfo.addTexto("¡¡Tu ataque ha fallado!!");
         }
         else
         {
            CPU.pierdeVida(resultado);
            pCPU.setVida(CPU.getVida());
            pInfo.addTexto("Daños causados: " + resultado);
            delay(1000l);
            if (ataqueJugador > jugador.getAtaque())
               pInfo.addTexto("¡¡Has causado daños críticos!!");
         }
         
         if (CPU.getVida() <= 0)
         {
            delay(1000l);
            pInfo.addTexto("Has derrotado a " + CPU.getNombre());
         }
         else
         {
            delay(1000l);
            pInfo.addTexto("Es el turno de " + CPU.getNombre());
            delay(250l);
            int ataqueCPU = atacar(CPU);
            int defensaJugador = defender(jugador);
            resultado = ataqueCPU - defensaJugador;
            if  (resultado <= 0)
            {
               pInfo.addTexto("Daños causados: 0");
               delay(500l);
               pInfo.addTexto("¡¡" + CPU.getNombre() + " ha fallado!!");
            }
            else
            {
               jugador.pierdeVida(resultado);
               pJugador.setVida(jugador.getVida());
               pInfo.addTexto("Daños causados: " + resultado);
               delay(500l);
               if (ataqueCPU > CPU.getAtaque())
                  pInfo.addTexto("¡¡Has recibido daños críticos!!");
            }
         }
         
         if (jugador.getVida() == 0)
         {
            delay(1000l);
            pInfo.addTexto("Has muerto. FIN DE LA PARTIDA");
         }
         else if (CPU.getVida() == 0)
         {
            delay(1000l);
            pInfo.addTexto("¡¡Enhorabuena!! Has derrotado a tu enemigo.");
         }
         else
         {
            pJugador.pBotones.ataque.setEnabled(true);
            pJugador.pBotones.huida.setEnabled(true);
         }
            
         
      }

Este es el método que se ejecuta cuando se pulsa el botón "Atacar" y como veis llamo a mi método delay() en varios sitios.
Pero no está funcionando como yo esperaba. Parece como si, a pesar de que lo llamo en distintos sitios, al comenzar el método se crea un pausa muy larga, como si se sumasen todos los delays en uno solo.... y tras esta "macropausa" sale de golpe todas las lineas de texto en el JTextArea.... cuando mi idea es que vayan saliendo poco a poco, con distintas pausas repartidas a lo largo de la ejecución del código.

Ni siquiera se percibe la desactivación de los botones, y posterior reactivación al final del método.
Como digo, se hace un "macrodelay" inicial y luego pum, se ejecuta todo el código seguido.

¿Cómo podría conseguir lo que quiero hacer...? si es que es posible....

Espero haberme explicado bien.... gracias  y un saludo.

919
Yo empecé con videotutoriales en youtube.
Este me gustó bastante, el autor explica bastante bien, aunque los videos son un poco largos. Yo solía ponerlos a velocidad 1.5x y si acaso, pausarlo en algun momento puntual.

Por otro lado, si vienes con conocimiento totalmente cero en programación, estaría bien empezar con este Curso de Bases de la Programación
Son contenidos válidos para luego facilitar el aprendizaje de cualquier lenguaje de programación.

920
No soy un experto ni mucho menos, así que no puedo aportar mucho.

Pero se supone que la etiqueta base solo afecta a rutas relativas, no a las absolutas.

Si el enlace del www.google.com te falla, tal vez sea porque sea necesario poner el https:// delante para que sea considerada como absoluta.

Páginas: 1 ... 41 42 43 44 45 [46] 47 48 49 50

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".