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 ... 36 37 38 39 40 [41] 42 43 44 45 46 ... 50
801
Hola.

Solo comentar que sigo con este ejercicio, porque la verdad me parece divertido.

Creo que he dado con una solución y hoy que tengo algo de tiempo libre intentaré desarrollarla.
No se si es quizás demasiado compleja (soy propenso a dar con soluciones más difíciles de lo necesario) pero es la única que se me ha ocurrido.

Básicamente consiste en dotar a la clase Rectángulo unos métodos para que sea capaz de proporcionarnos todas las posibles posiciones adyacentes a él donde podríamos intentar colocar otro Rectángulo.

Así cuando el Jugador 1 quiera insertar un nuevo Rectángulo, lo que hacemos es mirar cuáles otros Rectángulos tiene ya en el tablero y a cada uno pedirle sus posiciones adyacentes.
Que nos digan que posiciones tienen a su derecha, a su izquierda, por debajo y por arriba. Y con ellas ir probando a insertar el nuevo Rectángulo hasta encontrar un sitio donde encaje correctamente.

Luego intentaré explicarlo mejor, quizás con algún dibujo, porque no es fácil je je.

Saludos.

802
Además las reglas no me quedan del todo claro..

Supongamos que el jugador 1 es el color azul y el jugador 2 es el verde.

¿La colocación de los rectangulos tal que un rectángulo azul está en la parte superior izquierda y un rectángulo verde está a su derecha unido pero no en todo su lateral y luego otro rectángulo azul debajo unido al verde pero tocando también el lateral del azul sería correcto?
¿Basta que sean contiguos por solamente una pequeña parte de un lado?


803
Hola.
Estoy echándole un vistazo, y la verdad, es más difícil de lo que parece.
Cuando empiezas a tener en cuenta todas las posibles situaciones que pueden darse y si se quiere cumplir correctamente con las reglas de inserción de rectangulos...., te das cuenta de que esto no se va a resolver simplemente recorriendo la matriz en busca de posiciones con 0 donde intentar meter el rectángulo.

Creo que habrá que buscar otro enfoque, a ver si se me ocurre algo.
Un saludo.

804
Aprender a programar desde cero / Re:Ejercicio CU00659B
« en: 10 de Mayo 2019, 23:40 »
OK. Ahora ningún purista de la programación podrá acusarte de cometer sacrilegios con el break je je..

Por último comentar que, sin duda está todo correcto, pero siempre hay alguna mejora posible y por ejemplo en este caso podrías haberte ahorrado algunas variables como lonCad y contador, haciendo algo como esto:

Código: [Seleccionar]
        int i = 0;
        while(i < cadena.length() ){
            deletrea=cadena.substring(i, i+1);
            System.out.println("Letra "+ i + " "+ deletrea);   
            i++;
        }

E incluso la variable deletrea nos la podríamos ahorrar también.

Esto lo comento como algo secundario. No es importante ahora mismo.
De hecho cuando se empieza a programar, puede venir bien usar más variables de lo necesario para clarificar mejor las ideas de lo que se está haciendo.
Con el tiempo, cuando ya se tienen las ideas más claras, tú mismo irás descubriendo que el código se puede simplificar fácilmente.

Un saludo.


805
Aprender a programar desde cero / Re:Ejercicio CU00659B
« en: 10 de Mayo 2019, 15:34 »
Hola.

Aunque el programa funcione, has optado por usar un bucle infinito (while(true)) para luego "romperlo" con un break cuando se cumpla la condición de salida.

ESto lo has hecho siguiendo el ejemplo explicativo de esa entrega 59, pero fíjate que en esa misma entrega ya se indica que esta forma de hacer el bucle while es meramente un ejemplo explicativo y no debería ser la forma habitual de proceder

Citar
[...] en general la salida a un bucle se realizará de forma natural mediante la evaluación de la condición y no mediante una instrucción break;.

Así que lo ideal sería que reescribas tu bucle while y en el lugar del true pongas ahí la condición que ha de cumplirse para que se repita el while.

Esta condición es muy similar a la que has usado en el if, pero será distinta.

Fíjate que en el if, has tenido que pensar en la condición que VA A PONER FIN al bucle.

En cambio, para la condición del while, vas a tener que pensar en la condición que VA A HACER QUE SE REPITA el bucle.

Es decir, MIENTRAS se cumpla dicha condición, el bucle se repetirá. Cuando  deje de cumplirse, el bucle finalizará.


El uso de break para romper bucles, ya sean while, do..while o for debe evitarse siempre que sea posible.
Habrá situaciones muy concretas en las que usar break puede suponer una simplificación importante del código y entonces sí podría ser preferible su uso.

Hay puristas de la programación que te dirán que no, que usar break para romper bucles es prácticamente un sacrilegio je je...
Yo no diría tanto. Siempre evito usar break, pero si me encuentro en una de esas situaciones que hacen que el código quede más simplificado y más legible, entonces no dudo en emplearlo.

En fin, prueba a reescribir ese while como te he dicho, y si tienes dudas pregunta.
Elegir bien las condiciones en los bucles tiene su importancia. En este caso no es difícil, pero hay ocasiones en las que hay que combinar más de una condición. Y saber elegir las condiciones óptimas y en que orden combinarlas, es importante.

806
El problema seguramente viene por el null que pones al principio.

Citar
String mensaje3 = String.format(null,"Nombre del ciudadano:   %s\n Apellido Paterno:   %s\n Apellido Materno:   %s\n edad:   %s\n Fecha de nacimiento:   %s\n Nombre de la calle:   %s\n Numero de la calle:   %s\n Codigo Postal:   %s\n Municipio:   %s\n Estado:   %s\n",nom,apellidopaterno,apellidomaterno,edad,fechanacimiento,nomcalle,Nocalle,cp,municipio,estado);
    JOptionPane.showMessageDialog(null,mensaje3);

El compilador, al encontrarse con ese parámetro null, piensa que estás llamando al método que recibe como primer parámetro un objeto Locale, pero como dicho parámetro está "nulleado".., le resulta extraño.

Simplemente quita ese null y ya está.

Por cierto, al final de todo no es necesario usar String.format()

Citar
String mensaje2 = String.format("No puede votar");

Puesto que es una simple cadena sin variables que formatear ni nada, puedes hacerlo simplemente así:
Citar
String mensaje2 = "No puede votar";

807
Intentando mover el mensaje de un forero a esta sección, parece que se ha perdido por el camino. Pero he podido recuperar el texto de su consulta:


TEXTO DE LA CONSULTA

Qué tal, estoy empezando a ver el tema de Java con Netbeans y estamos con JOption y los recuadros de dialogo este es mi programa que hice casi todo compila bien sale el recuadro excepto el ultimo que me tiene que mostrar los datos que se ingresan y de echo me sale el siguiente mensaje

reference to format is ambiguous
both method format(String,Object...) in String and method format(Locale,String,Object...) in String match

Código: [Seleccionar]
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package estructuradatos;

import javax.swing.JOptionPane;

/**
 *
 * @author wordl
 */
public class SistemaINE {
    public static void main (String[] args, String String) {
    int edad, Nocalle, cp;
    String nom, apellidopaterno, apellidomaterno, fechanacimiento, nomcalle, municipio, estado;
   
   String n = JOptionPane.showInputDialog ("Ingrese su edad");
   edad = Integer.parseInt(n);
   
    if (edad >17) {
       
    String mensaje = String.format("Si puede votar", edad);
    JOptionPane.showMessageDialog(null,mensaje);
   
     String a = JOptionPane.showInputDialog ("Ingrese Nombre del ciudadano");
    nom=(a);
   
    String b = JOptionPane.showInputDialog ("Ingrese Apellido Paterno");
    apellidopaterno= (b);
   
    String c = JOptionPane.showInputDialog ("Ingrese Apellido Materno");
    apellidomaterno= (c);
   
    String d = JOptionPane.showInputDialog ("Ingrese su edad");
    edad= Integer.parseInt(d);
   
    String e = JOptionPane.showInputDialog ("Ingrese su fecha de nacimiento");
    fechanacimiento= (e);
   
    String f = JOptionPane.showInputDialog ("Ingrese el nombre de su calle");
    nomcalle= (f);
   
    String g = JOptionPane.showInputDialog ("Ingrese el numero de su vivienda");
    Nocalle= Integer.parseInt(g);
   
    String h = JOptionPane.showInputDialog ("Ingrese su codigo postal");
    cp= Integer.parseInt(h);
   
    String i = JOptionPane.showInputDialog ("Ingrese el municipio");
    municipio= (i);
   
    String j = JOptionPane.showInputDialog ("Ingrese estado al que pertenece");
    estado= (j);
   
    String mensaje3 = String.format(null,"Nombre del ciudadano:   %s\n Apellido Paterno:   %s\n Apellido Materno:   %s\n edad:   %s\n Fecha de nacimiento:   %s\n Nombre de la calle:   %s\n Numero de la calle:   %s\n Codigo Postal:   %s\n Municipio:   %s\n Estado:   %s\n",nom,apellidopaterno,apellidomaterno,edad,fechanacimiento,nomcalle,Nocalle,cp,municipio,estado);
    JOptionPane.showMessageDialog(null,mensaje3);
   
    }
    else {
   
    String mensaje2 = String.format("No puede votar");
    JOptionPane.showMessageDialog(null,mensaje2);
   
   
   
           
    }
    }
   
}



Gracias

808
Hola.

Yo lo que haría sería usar 4 funciones distintas: una para comprobar lineas horizontales, otra comprueba lineas verticales, otra comprueba diagonal ascendente y la última diagonal descendente.

Serían funciones booleanas, así por cada posicion del tablero, compruebo a ver que me devuelve cada una de estas funciones. Si alguna devuelve true, es que he encontrado una linea de 5 válida.

Mira, supongamos este tablero 10x10 de ejemplo:

Código: [Seleccionar]
char tablero[10][10] = { {'X',' ',' ',' ','X',' ','X','X','X','X'},
         {' ',' ',' ','X',' ',' ',' ',' ',' ',' '},
         {' ',' ','X',' ',' ','X','X','X','X','X'},
         {' ','X',' ',' ',' ',' ',' ',' ',' ',' '},
         {'X',' ',' ',' ',' ',' ',' ',' ',' ',' '},
         {' ',' ','X',' ',' ',' ',' ','X',' ',' '},
         {'X',' ',' ','X',' ',' ',' ','X',' ','X'},
         {'X',' ',' ',' ','X',' ',' ','X','X',' '},
         {'X',' ',' ',' ',' ','X',' ','X','X','X'},
         {'X',' ',' ',' ',' ',' ','X','X','X',' '},
};

Ahí he puesto 4 lineas válidas, una de cada tipo, más unas cuantas X que no forman líneas válidas.

Ahora declaro mis 4 funciones:
Código: [Seleccionar]
bool buscaLineaVertical(int, int); //Busca lineas verticales
bool buscaLineaHorizontal(int, int); //Busca lineas horizontales
bool buscaLineaDiagonalAscen(int, int); //Busca lineas diagonales ascendentes
bool buscaLineaDiagonalDescen(int, int); //Busca lineas diagonales descendentes

Fíjate que a cada una le pasaré dos int, estos serán las posiciones a comprobar en el tablero.

En la función main() uso dos bucles anidados para recorrer el tablero y como dije antes, para cada posición consulto a ver que me devuelven estas funciones.
En realidad, según que posiciones, no llamaré a algunas funciones.

Por ejemplo, solo buscaré lineas verticales si la variable i es menor o igual que 5. Porque si vale 6 o más, no van a haber casillas suficientes para encontrar una linea de cinco 'X', así que entonces no vale la pena llamar a la funcion.
Por eso en el if donde pregunto por lineas verticales, una condición previa es que i <= 5

Código: [Seleccionar]
int main()
{
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++) {

if ( i <= 5 && buscaLineaVertical(i, j))
cout << "Encontrada linea VERTICAL en posicion X:" << i << " Y:" << j << "\n";

if (j <= 5 && buscaLineaHorizontal(i, j))
cout << "Encontrada linea HORIZONTAL en posicion X:" << i << " Y:" << j << "\n";

if ( (i <= 5 && j >= 4) && buscaLineaDiagonalAscen(i, j))
cout << "Encontrada linea DIAGONAL ASCENDENTE en posicion X:" << i << " Y:" << j << "\n";

if ( (i <= 5 && j <= 5) && buscaLineaDiagonalDescen(i, j))
cout << "Encontrada linea DIAGONAL DESCENDENTE en posicion X:" << i << " Y:" << j << "\n";
}
system("PAUSE");
}

Visto el main(), ahora vamos a ver el detalle de las funciones, que es lo interesante.
Son muy sencillas en realidad, básicamente son un bucle for que incrementa un indice de 0 a 5.
Este indice se lo sumo o resto, a las posiciones X y/o Y, según cada caso.
Y cada vez que incremento, pregunto si aún estoy encontrando el caracter 'X'.
Si ya no lo encuentro, retorno false y la función termina.
Si aún estoy encontrando dicho caracter, no hago nada, dejo que el bucle se repita para aumentar el incremento y volver a preguntar.

Si este bucle for termina sin haber retornado false, es que he encontrado los 5 caracteres necesarios para componer una línea, así que retornaré true.

Para buscar líneas verticales, tengo que incrementar la x

Código: [Seleccionar]
bool buscaLineaVertical(int x, int y) {
//Buscaremos en vertical hacia abajo, por lo que incrementaremos la x
for (int i = 0; i < 5; i++) {
if (tablero[x + i][y] != 'X') //Si no hay una 'X' es que no hay línea
return false; //así que retornamos false poniendo fín a este método
};
//Si el bucle for a logrado finalizar sin retornar false...
return true; //...es que tenemos una línea de 5, así que retornamos true
}

Para las horizontales, incremento la Y:
Código: [Seleccionar]
bool buscaLineaHorizontal(int x, int y) {
//Búsqueda horizontal, incrementaremos la y
for (int i = 0; i < 5; i++) {
if (tablero[x][y + i] != 'X')
return false;
};

return true;
}

Para diagonales ascendentes, incremento X y DECRemento la Y.
Código: [Seleccionar]
bool buscaLineaDiagonalAscen(int x, int y) {
//Se incrementa x, se decrementa y
for (int i = 0; i < 5; i++) {
if (tablero[x + i][y - i] != 'X')
return false;
};

return true;
}

Y para diagonales descendentes, incrementamos ambos.
Código: [Seleccionar]
bool buscaLineaDiagonalDescen(int x, int y) {
//Se incrementan x e y
for (int i = 0; i < 5; i++) {
if (tablero[x + i][y + i] != 'X')
return false;
};

return true;
}

No se si esta es la forma más eficiente. Por mi parte, siempre prefiero "modular" tanto como sea posible y tener así funciones encargadas de tareas muy específicas.
Prueba y revisa mi código, a ver si te sirve o al menos te da nuevas ideas.

Te lo pongo aquí de nuevo el código completo juntito, por si quieres copiar y pegar:

Código: [Seleccionar]
using namespace std;

char tablero[10][10] = { {'X',' ',' ',' ','X',' ','X','X','X','X'},
{' ',' ',' ','X',' ',' ',' ',' ',' ',' '},
{' ',' ','X',' ',' ','X','X','X','X','X'},
{' ','X',' ',' ',' ',' ',' ',' ',' ',' '},
{'X',' ',' ',' ',' ',' ',' ',' ',' ',' '},
{' ',' ','X',' ',' ',' ',' ','X',' ',' '},
{'X',' ',' ','X',' ',' ',' ','X',' ','X'},
{'X',' ',' ',' ','X',' ',' ','X','X',' '},
{'X',' ',' ',' ',' ','X',' ','X','X','X'},
{'X',' ',' ',' ',' ',' ','X','X','X',' '},
};

bool buscaLineaVertical(int, int); //Busca lineas verticales
bool buscaLineaHorizontal(int, int); //Busca lineas horizontales
bool buscaLineaDiagonalAscen(int, int); //Busca lineas diagonales ascendentes
bool buscaLineaDiagonalDescen(int, int); //Busca lineas diagonales descendentes

int main()
{
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++) {

if ( i <= 5 && buscaLineaVertical(i, j))
cout << "Encontrada linea VERTICAL en posicion X:" << i << " Y:" << j << "\n";

if (j <= 5 && buscaLineaHorizontal(i, j))
cout << "Encontrada linea HORIZONTAL en posicion X:" << i << " Y:" << j << "\n";

if ( (i <= 5 && j >= 4) && buscaLineaDiagonalAscen(i, j))
cout << "Encontrada linea DIAGONAL ASCENDENTE en posicion X:" << i << " Y:" << j << "\n";

if ( (i <= 5 && j <= 5) && buscaLineaDiagonalDescen(i, j))
cout << "Encontrada linea DIAGONAL DESCENDENTE en posicion X:" << i << " Y:" << j << "\n";
}
system("PAUSE");
}

bool buscaLineaVertical(int x, int y) {
//Buscaremos en vertical hacia abajo, por lo que incrementaremos la x
for (int i = 0; i < 5; i++) {
if (tablero[x + i][y] != 'X') //Si no hay una 'X' es que no hay línea
return false; //así que retornamos false poniendo fín a este método
};
//Si el bucle for a logrado finalizar sin retornar false...
return true; //...es que tenemos una línea de 5, así que retornamos true
}

bool buscaLineaHorizontal(int x, int y) {
//Búsqueda horizontal, incrementaremos la y
for (int i = 0; i < 5; i++) {
if (tablero[x][y + i] != 'X')
return false;
};

return true;
}

bool buscaLineaDiagonalAscen(int x, int y) {
//Se incrementa x, se decrementa y
for (int i = 0; i < 5; i++) {
if (tablero[x + i][y - i] != 'X')
return false;
};

return true;
}

bool buscaLineaDiagonalDescen(int x, int y) {
//Se incrementan x e y
for (int i = 0; i < 5; i++) {
if (tablero[x + i][y + i] != 'X')
return false;
};

return true;
}

809
Si quieres construir un objeto Persona pasándole los 5 valores correspondientes a sus atributos, puedes hacerlo con un constructor como este:

Código: [Seleccionar]
public Personas(String nombrePersona, String apellidoPersona, int edadPersona, boolean casadoPersona, String nDIPersona){
    nombre=nombrePersona;
    apellido=apellidoPersona;
    edad=edadPersona;
    casado=casadoPersona;
    nDI=nDIPersona;
    }

No debería darte error. Si te lo da, la causa será otro motivo.

810
EL problema es que tu clase Persona solo tiene un constructor, el cuál NO puede recibir parámetros:

Código: [Seleccionar]
//constructor
    public Personas(){
    nombre="";
    apellido="";
    edad=0;
    casado=false;
    nDI="";
    }

Pero tú estás intentando crear una Persona, pasándole un parámetro, el nombre en este caso:
Citar
public TaxiYCond (Taxi objetoTaxi, Personas objetoPersonas) {
        vehiculoTaxi = new Taxi (objetoTaxi.getMatricula(), objetoTaxi.getDistrito(),objetoTaxi.getTipoMotor()); //Creamos un objeto Taxi con el constructor general de Taxi
        conductorTaxi = new Personas (objetoPersonas.getNombre()); //Creamos un objeto Persona con el constructor general de Persona
    }

Así que tienes que añadirle a Persona, otro constructor que te acepte ese parámetro:

Código: [Seleccionar]
//constructor
    public Personas(){
    nombre="";
    apellido="";
    edad=0;
    casado=false;
    nDI="";
    }

public Personas(String nombrePersona){
    nombre=nombrePersona;
    apellido="";
    edad=0;
    casado=false;
    nDI="";
    }

Con este segundo constructor, podrías crear una Persona recibiendo su nombre como parámetro.

Y si quisieras, podrías añadir un tercer constructor (puedes tener todos los constructores que creas necesitar) capaz de recibir todos los parámetros necesarios para inicializar todos los atributos.

Código: [Seleccionar]
//constructor
    public Personas(){
    nombre="";
    apellido="";
    edad=0;
    casado=false;
    nDI="";
    }

public Personas(String nombrePersona){
    nombre=nombrePersona;
    apellido="";
    edad=0;
    casado=false;
    nDI="";
    }

public Personas(String nombrePersona, String apellidoPersona, int edadPersona, boolean casadoPersona, String nDIPersona){
    nombre=nombrePersona;
    apellido=apellidoPersona;
    edad=edadPersona;
    casado=casadoPersona;
    nDI=nDIPersona;
    }

811
Hola Juanki.

Sí, te puedes ahorrar esa variable auxiliar sin problemas. De hecho, cuando uno va a aprendiendo y avanzando en programación, poco a poco va descubriendo que hay muchas cosas que nos podemos "ahorrar" y las instrucciones en el código se reducen drásticamente.

Sin embargo, este "ahorro" a veces provoca ( y no es el caso de tu ejercicio) que no sea evidente lo que hace dicho código.
Es decir, a veces querremos que el código tenga algunas instrucciones de más, aunque sean redundantes, porque al leerlo a simple vista queda más evidente lo que hacen esas instrucciones.
Escoger cuando ser redundante y cuando ser ahorrativo, ya depende de cada uno y de las necesidades del momento.
Al compilador de Java le va a dar igual.

Por ejemplo, imagina que nos piden un método que recibe un valor int con una edad, y el método ha de retornar true si es mayor de edad (18 años o mayor) y false si es menor.

Una forma típica de escribir este método, y que queda muy legible y muy claro lo que hace, sería esta:

Código: [Seleccionar]
public boolean esMayorEdad(int edad) {
   
    if (edad >= 18)
        return true;
    else
        return false;
}

Esto en realidad, se puede resumir así:

Código: [Seleccionar]
public boolean esMayorEdad(int edad) {
   
    return edad >= 18;

}

La primera forma es más redundante, pero más fácil de entender el cométido del código. Puede resultar más didáctico.

La segunda forma es más ahorrativa, incluso más eficiente al reducir instrucciones ( y ahorrar quizás algunos nanosegundos jeje ), pero a ojos de alguien que esté aprendiendo a programar, puede resultar confuso.

Escoger una forma u otra, dependerá de si vamos a compartir ese código con alguien, y según con quien lo compartimos.

Volviendo al caso de tu ejercicio, incluso omitiendo el uso de una variable auxiliar queda bastante evidente lo que está haciendo el código, así que puedes ahorrartela sin ningún problema.

812
Hola, la barra se usa para indicar en que directorio ha de buscar dicho archivo, aunque tal y como está puesta en el ejemplo, parece que estaría mal.

Si el archivo .js está exactamente en el mismo directorio donde está el .html que estás creando, puedes referenciarlo de dos maneras:

Una, la que tu has hecho al corregirlo:
<script type="text/javascript" src="functions.js"></script>

La otra, poniendo un punto y una barra, que es quizás la forma que se quería mostrar en el curso:
<script type="text/javascript" src="./functions.js"></script>

En ambos casos se está apuntando a la misma localización, viene a ser exactamente lo mismo.

Si por casualidad tuvieras el archivo .js en otro directorio, que estuviera a "la misma altura" que el directorio donde está el .html, entonces pondrías ../

<script type="text/javascript" src="../js/functions.js"></script>

Ahí, con los dos puntos, le estarías diciendo que ha de salirse del directorio donde está el .html, entrar en el directorio js (que está al mismo nivel que el directorio que contiene el .html) y cargar el archivo functions.js

Si por un casual el directorio js estuviera un nivel más arriba, que el directorio que contiene el html:
<script type="text/javascript" src="../../js/functions.js"></script>

Como podrás intuir, ahí le decimos que salga del directorio donde esta él html, y que ademá suba otro nivel más, y ahora sí encontrará el directorio js con su corrspondiente archivo.

813
Aprender a programar desde cero / Re:Guardar en notepadd
« en: 17 de Abril 2019, 19:55 »
Supongo que te refieres a Notepad++, y si no es este, da igual. La siguiente explicación es aplicable a cualquier editor de texto.

Al guardar el archivo puedes elegir cualquier extensión en el menú de guardado. Si por algún motivo finalmente lo guardas como "All Types", entonces te lo guarda sin ninguna extensión.

Esto en realidad, no presenta ningún problema. Lo único que no podrás abrirlo directamente haciendo doble click porque el sistema operativo, al ser un archivo sin extensión, no sabe a que programa asignarlo.

Pero si le das con click derecho, seguramente te saldrá la opción de abrir con Notepad++ y recuperar tu trabajo.

Es más, si seleccionas tu archivo y pulsa la tecla F2 (si es que estamos bajo SO Windows) podrás cambiar el nombre del fichero y tu misma podrás añadirle la extensión .html para que ahora sí el sistema operativo sepa de que tipo de archivo se trata.

814
Hola!
Buena aportación, pero solo por hacer un apunte yo recomendaría pasar ese "et_" a un "tag_", por ejemplo, así como los propios nombres elegidos, ya que utilizar campos en español puede suponer un problema en caso de que se quiera compartir el código a nivel internacional.
Un saludo!

Cierto.
El idioma inglés manda en este mundo así que no está de más usarlo como norma de cara a internacionalizar nuestro código.

Saludos.

815
Hola.

Los nombres de variables u objetos NO pueden comenzar por un número. Por eso no te admite esos nombres para los JLabel.
Dichos nombres han de comenzar por una letra. También se admite el símbolo dolar $ o el guión bajo _

En cualquier caso, lo recomendable es usar nombres lo más intuitivos posibles, de manera que con solo leerlo tú o cualquiera pueda hacerse una idea fácil de que dato/objeto está representando cada nombre.

Yo por ejemplo, a los JLabel suelo comenzar sus nombres por "et_" ( de etiqueta) o bien "jl_" (de JLabel)
Así con solo leer su nombre ya tengo claro de que dicho objeto se trata de un JLabel.

Y a continuación, un texto descriptivo. Si por ejemplo estoy creando un formulario donde voy a pedir datos como nombre, apellido, teléfono, dni... a los JLabel de los que me voy a valer para esto preferiré nombrarlos:

Código: [Seleccionar]
JLabel et_nombre = new JLabel("Nombre:");
JLabel et_apellido = new JLabel("Apellido:");
JLabel et_telefono = new JLabel("Telefono:");
JLabel et_dni = new JLabel("DNI:");

Lo mismo para otros elementos, por ejemplo los botones:

Código: [Seleccionar]
JButton bt_aceptar = new JButton("Aceptar");
JButton bt_cancelar = new JButton("Cancela");
JButton bt_nuevoReg = new JButton("Crear Nuevo Registro");

Acostumbrarse a utilizar nomenclaturas como esta (cada uno ha de encontrar la que mejor le resulte), ayuda mucho al propio programador.
Muchas veces creamos formularios con multitud de etiquetas, campos de texto, botones....si usamos nombres poco descriptivos podemos acabar perdidos en nuestro propio código.

Es mejor usar nombres descriptivos, buscando cierto equilibrio entre la longitud del nombre escogido y su capacidad descriptiva.
Así el código es más legible.

816
Hola Omar.

El ejercicio pide:
Citar
4) Añadir una canción al disco recibiendo como información para ello el título de la canción y su duración (se añadirá como última canción en el disco. Si el disco tenía por ejemplo 10 canciones, al añadirse una canción pasará a tener 11).

Aquí la acción es AÑADIR una canción. Y para poder añadirla necesitas título y duración, así que lo ideal es indicar esos dos datos en el mismo método.

Realmente no hay una norma obligatoria a seguir, al final el programador decide como hacer las cosas en cada situación y siempre buscando la forma más óptima.

Se podría hacer un método para añadir la canción solo con el nombre. Y luego otro para modificar ese registro recién añadido para ahora sí incluir el tiempo de duración.
Pero, ¿tiene sentido realizar dos acciones cuando se puede obtener el mismo resultado realizando una única acción?

Al final el programa va a funcionar igual, pero es más óptimo y eficiente reducirlo a una sola acción, cuando se trata de algo que esta tán relacionado entre sí. A fin de cuentas, la acción es añadir una canción con sus datos completos, no es añadir un nombre y luego añadirle la duración.

Lo de realizar un método para cada acción se refiere a acciones que no están tan relacionadas entre sí. Entonces sí conviene "modular" el código y separarlo en varios métodos.

Imagina un programa que ha de pedir datos de un alumno, comprobar que el DNI es válido, recuperar sus notas de una base de datos, calcular la nota media y por último imprimir en pantalla sus notas indicando si está aprobado o suspenso.

¿Tendría sentido hacer un método llamado: ?

Procedimiento pedirDatosALumnoComprobandoDniRecuperaNotasdeBaseDatosCalculaNotaMediaImprimeNotasEnPantallaIndicandoSiAprobadoOSuspenso();

Pufff... no solo es el nombre más horrible jamás escrito para un método, sino que a parte de eso, este método hace demasiadas cosas "distintas".
Indudablemente hay que modular, de hecho, hay cosas que solo hará si se cumplen ciertas condiciones.
Por ejemplo, si por error nos han dado un DNI que no es válido, ya no se va a buscar nada en la base de datos, ni se van a calcular medias, ni nada..

Habrá que separar en métodos:
  • void pedirDatosALumno();
  • boolean compruebaDNIesValido(String dni);
  • float[] recuperaNotasdeBaseDatos(String dni);
  • float calculaNotaMedia(float[] arrayDeNotas);
  • void imprimeNotasPantalla(float[] arrayDeNotas, float notaMedia);

Este último método por ejemplo, se podría hacer en dos métodos: uno para imprimir las notas y otro para a continuacion imprimir solo la nota media e indicando si está aprobado o no.
Y sería perfectamente válido.
Pero al ser cosas que sí están más relacionadas, todo tiene que ver con las notas del alumno, seguramente el programador va a preferir hacerlo todo junto en un único método.

817
Sí, si es un problema.
Si añades o eliminas elementos de un List o derivados (como ArrayList) mientras "iteras", el Iterador se quejará.

Se podría subsanar este problema creando sublistas temporales, una con elementos para añadir, otra con elementos para eliminar... y tras finalizar la iteración consultamos estas sublistas para actualizar el ArrayList principal añadiendo y quitando los elementos que correspondan y así la próxima vez que creemos el Iterator los cambios ya estarán hechos.

O bien, tras cada cambio realizado, volver a instanciar el Iterador para que este actualizado al momento. Esto cuando vayas aprendiendo a separar tu programa en subprogramas (métodos) que se encarguen de pequeñas tareas concretas, será más fácil de lo que parece.
Además normalmente preferirás dar opciones específicas al usuario:
1º Añadir Producto..
2º Eliminar Producto...
3º Mostrar listado de Productos actual...

De modo que no te verás en la tesitura de "Añadir un Producto" durante el proceso de "Mostrar listado", ya que serán subprocesos distintos y para "Añadir Producto" no necesitas iterar, tan solo pedir datos, crear un objeto Producto y añadirlo al ArrayList.
Luego cuando el usuario eliga opcion 3 "Mostrar Listado", en ese momento podrás crear un Iterador tranquilamente porque dentro de esta opción no vas a dar la posibilidad de añadir o eliminar productos.


Por otra parte, he de decir que no soy programador profesional ni por asomo. Soy poco más que un aprendiz algo avanzadillo...
Pero en realidad, nunca he necesitado usar iteradores para recorrer los ArrayList.

Suelo usar indices si van a haber modificaciones o si solo necesito recorrerlo para mostrar y computar datos, como es el caso de tu programa, uso un cómodo "for each" y listo.


En definitiva, no te agobies con este "limitación" del Iterator, no solo hay formas de subsanarla, sino que en realidad posiblemente muy pocas veces necesites usar un iterador para moverte por los ArrayList.


818
Hola.

El problema está en que tú primero creas el Iterador y luego añades Productos.

Esto implica que el Iterador no tiene constancia de estos nuevos Productos que has añadido, él mismo lo detecta y por lo tanto te lanza esa excepción de "Modificación Concurrente"... que viene a significar algo así como que estás modificando al mismo tiempo que estás iterando..

Lo que tienes que hacer es añadir primero los productos y DESPUES creas el Iterador.


Código: [Seleccionar]
public class Testeje3 {

public static void main(String[] args) {
ArrayList<Producto> superm = new ArrayList<>();

double finalP=0;
Producto prod;

superm.add(new Producto("Leche", 2, 1.79));
superm.add(new Producto("Galle", 4, 1.29));
superm.add(new Producto("Zumo", 1, 1.52));

Iterator<Producto> it = superm.iterator();

while(it.hasNext()) {
prod = it.next();
System.out.print(prod.getNombre()+ "          ");
System.out.print(prod.getCantidad()+ "        ");
System.out.print(prod.precioFinal());
System.out.println();
finalP+= prod.precioFinal();
}
System.out.println("Precio final" + finalP);

}

}

819
Hola.
El problema se debe a una peculiaridad que tiene la clase Scanner y que hace que siempre que en un mismo programa queramos leer datos numéricos como un int y texto en un String, tendremos problemas seguro....

El problema se debe a que los métodos de la clase Scanner que usamos para recoger datos numéricos: nextInt(), nextDouble(), nextFloat(), etc... solo recogen la parte numérica de lo que hemos tecleado.
Es decir, si yo tecleo el número 52 y pulso enter, en realidad lo que he introducido es:
52\r
Ese último carácter, el \r lo genera la tecla enter, es el símbolo llamado "retorno de carro" y, en este caso, sirve para decirle al objeto Scanner que ya hemos terminado de teclear.

Pues bién, si eso se lo pasamos al método nextLine(), lo cogerá COMPLETO y generará un String. Coge también el \r, aunque no lo vemos porque es "invisible".
En fín, en este caso no hay problema.

Pero si esa entrada se la pasamos a por ejemplo el método nextInt(), este método no cogerá el \r porque no es un valor numérico, SOLO cogerá el 52 y generará un int.

Pero el \r que nextInt() ha ignorado, no desaparece, se queda en el "stream" de entrada de datos por teclado, tal que así:
\r

¿Qué pasa entonces? Pues que si tras leer un valor con nextInt(), luego queremos leer otro con un nextLine().... el nextLine() se va a encontrar con que hay un \r en el "stream" de entrada.
Y erróneamente va a pensar que es que el usuario ya ha pulsado enter, por lo tanto dará por finalizada la entrada de datos y generará un String vacío.... cuando en realidad el usuario no ha tenido la posibilidad de teclear nada.

Esto es lo que te está pasando a tí. Tu primero lees un entero para preguntar cuantos usuarios se van a introducir:
Código: [Seleccionar]
System.out.println("Ingrese la cantidad de alumnos");
cantidadDeAlumnos=en.nextInt();

Esto te deja un \r abandonado en el stream de entrada, por lo tanto, tu primer intento de leer un String, va a fracasar:
Código: [Seleccionar]
System.out.println("Ingrese el nombre de los alumnos: ");
       for(int i=0;i<=nombreAlumnos.length-1;i++){
       
           alumno=en.nextLine();
           nombreAlumnos[i]=alumno;
           
       }
Solo fallará el primero, el resto irán bien porque los nextLine() no dejan \r abandonados...

En fin, vamos a lo importante, ¿cómo solucionar esto?

Por suerte es fácil, de hecho, hay dos formas.

Una, la más sencilla, pero muy poco elegante. Es invocar un nextLine() justo después de haber leido el dato int.
Este nextLine() no se asigna a ninguna variable, simplemente "limpiará" el stream de entrada de cualquier \r que pueda haber.
Como digo, es fácil, pero no es elegante, porque queda un poco raro ir poniendo nextLine() sin asignar en distintas partes del código.
Aunque se puede usar un comentario para aclarar el motivo:
Código: [Seleccionar]
System.out.println("Ingrese la cantidad de alumnos");
cantidadDeAlumnos=en.nextInt();
en.nextLine(); //Para limpiar stream de entrada y poder leer datos String a continuacion


La segunda opción, es solo un poquito más complicada, pero es más elegante y de hecho es la más recomendable por dos motivos que indicaré después.
Consiste en usar SIEMPRE nextLine() para leer datos, tanto si queremos un String como si queremos un dato numérico.
La diferencia es que si queremos un dato numérico, tendremos que "parsearlo" (convertirlo) segun nuestra necesidad.

En este caso, lo haríamos así:
Código: [Seleccionar]
System.out.println("Ingrese la cantidad de alumnos");
cantidadDeAlumnos=Integer.parseInt(en.nextLine());

O si quisieramos leer un dato numérico con decimales:
Código: [Seleccionar]
System.out.println("Ingrese el area del rectángulo: ");
double areaRectan=Double.parseDouble(en.nextLine());

¿Por qué es la opción más recomendable?
  • Como ya hemos dicho, es más elegante. No hay que aclarar nada con comentarios, es evidente con solo leer el código que estamos recogiendo un valor int, o double, o byte o lo que sea...a pesar de que usamos un nextLine()

  • Cuando avances más en tu aprendizaje en Java y comiences a crear ventanitas, botones, formularios con campos de texto, etc... estos formularios SIEMPRE nos van a devolver los valores introducidos por el usuario como String, y SIEMPRE tendremos que "parsearlos" si deseamos un dato numérico.
    Así que mejor ir cogiendo ya la costumbre de este proceso.

  • Otros lenguajes como C#, lenguaje muy similar a Java y que seguramente algún dia querrás/tendrás que meterle mano, realiza la lectura de datos de este mismo modo: pidiendo un String al usuario para luego "parsearlo".
    Así que de nuevo resultará muy útil estar acostumbrado a esta mecánica.

820
Hola.

El "error" es que tu seteas valores al objeto miTaxi, que es un objeto de la clase Taxi.
Pero este seteo de valores no afecta para nada al objeto miConductor, quien tiene como atributo otro objeto de la clase Taxi, que no tiene nada que ver con el objeto miTaxi que tu has creado.

Por eso, cuando invocas al método:
Código: [Seleccionar]
miConductor.getDatosTaxiCond();
Lo que te va a mostrar son los datos del objeto Taxi que hay "dentro" de miConductor, no del que tú has creado "fuera".
Y como el Taxi que hay dentro de miConductor no ha sido seteado, te sale el mensaje de "desconocido"

Se que es un poco lioso, pero resumiendo, el problema es que en realidad en tu código hay dos objetos de la clase Taxi:
- el Taxi que tú has creado y llamado miTaxi, a quién sí has seteado valores.
- el Taxi que en realidad es un atributo de la clase TaxiCond, que está dentro del objeto llamado miConductor

Recuerda como es el código de TaxiCond:

Código: [Seleccionar]
/* Ejemplo - aprenderaprogramar.com */

//Ejemplo de clase que utiliza tipos definidos en otras clases (usa otras clases)
public class TaxiCond {

    private Taxi vehiculoTaxi;
    private Persona conductorTaxi;

    //Constructor
    public TaxiCond () {
        vehiculoTaxi = new Taxi (); //Creamos un objeto Taxi con el constructor general de Taxi
        conductorTaxi = new Persona (); //Creamos un objeto Persona con el constructor general de Persona
    }


Ese primer atributo, llamado vehiculoTaxi, es quien solo ha recibido el seteo de valores para la matricula, nada más, y por eso te sale "desconocido" en los demas valores cuando llamas al método getDatosTaxiCond()

Has de setearle todos los valores a este objeto Taxi, pero ahora mismo no vas a poder porque la clase TaxiCond no está completa, no tiene ningún método que permita setear dichos valores a este atributo.
De hecho, es una de las tareas que el ejercicio propone llevar a cabo:
Citar
Para completar la comprensión de la relación de uso entre clases, utiliza los métodos disponibles para el objeto TaxiCond que has creado: establece distintos valores de matrícula con el método setMatricula y visualiza los datos del objeto con el método getDatosTaxiCond. Crea además nuevos métodos que te permitan establecer el distrito y el tipo de motor de los objetos TaxiCond. Te planteamos otra reflexión: al igual que hemos definido un tipo TaxiCond que tiene dos objetos como campos, podemos definir tipos que tengan cinco, diez, quince o veinte objetos como campos


Así que piensa en como modificar la clase TaxiCond para disponer de métodos que te permita setear valores al Taxi que tenemos como atributo de clase TaxiCond.

Has de conseguir algo similar a lo que te permite hacer el método setMatricula(), pero para los datos de "distrito" y "tipo de motor".

Inténtalo y si no lo consigues, pide ayuda por aquí que te la daremos encantados.

Un saludo.

Páginas: 1 ... 36 37 38 39 40 [41] 42 43 44 45 46 ... 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".