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 ... 30 31 32 33 34 [35] 36 37 38 39 40 ... 50
681
A ver, que he rascado algo más de tiempo.
Podemos comenzar a meterle mano ya a la GUI, así vamos concretando algunas ideas de la "Vista" para saber mejor que necesitamos del "Controlador" y del "Modelo" (la clase BattleShip)

La primera pantalla que ha de mostrar el programa es un formulario de login.
O sea, dos campos para nombre y password y por ejemplo tres botones:
Login, Nuevo Usuario y Cerrar Programa.

Podemos crear una clase que herede de JPanel y modelar este formulario.
Lo haremos sencillo, sin demasiadas florituras. Solo conseguir que los elementos queden más o menos alineados.

Le daremos dos métodos básicos en todo formulario. Uno para limpiar los campos y otro para retornar los valores introducidos por el usuario.
Este último comprobará que los campos tienen datos.
Si los tiene, los retornará juntos en un array de dos String: nombre y password.
Si falta alguno, mostrará un aviso al usuario y retornará valor null.

Código: [Seleccionar]
public class PanelLogin extends JPanel{

private JTextField campoNombre;
private JTextField campoPass;
public JButton botonLogin;
public JButton botonNuevo;
private JButton botonSalir;

public PanelLogin() {
campoNombre = new JTextField(10);
campoPass = new JTextField(10);
botonLogin = new JButton("Login");
botonNuevo = new JButton("Nuevo Usuario");
botonSalir = new JButton("Cerrar Programa");
botonSalir.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0); //Esto cierra el programa
}
});

setLayout(new BorderLayout());
add(new PanelCentro(), BorderLayout.CENTER);
add(new PanelSur(), BorderLayout.SOUTH);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
//Paneles que componen el panel principal
private class PanelCentro extends JPanel {

public PanelCentro() {
JPanel datos = new JPanel();
datos.setLayout(new GridLayout(2,2,5,5));

JPanel nombreLabel = new JPanel();
nombreLabel.setLayout(new FlowLayout(FlowLayout.RIGHT));
nombreLabel.add(new JLabel("Nombre: "));
JPanel nombreCampo = new JPanel();
nombreCampo.setLayout(new FlowLayout(FlowLayout.LEFT));
nombreCampo.add(campoNombre);

JPanel passLabel = new JPanel();
passLabel.setLayout(new FlowLayout(FlowLayout.RIGHT));
passLabel.add(new JLabel("Password: "));
JPanel passCampo = new JPanel();
passCampo.setLayout(new FlowLayout(FlowLayout.LEFT));
passCampo.add(campoPass);

datos.add(nombreLabel);
datos.add(nombreCampo);
datos.add(passLabel);
datos.add(passCampo);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(datos);
JPanel boton = new JPanel();
boton.add(botonLogin);
add(boton);

setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10),
BorderFactory.createTitledBorder("Datos Login")));
}
}

private class PanelSur extends JPanel {
public PanelSur() {
JPanel nuevo = new JPanel();
nuevo.add(botonNuevo);
JPanel salir = new JPanel();
salir.add(botonSalir);

setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(nuevo); add(salir);
}
}

//Métodos de la clase
public void resetFormulario() {
campoNombre.setText(null);
campoPass.setText(null);
}

/**
* Recupera los datos del formulario y los retorna juntos en un array
* de dos elementos: nombre y password.
* @return Array String[] con los dos datos del formulario.
*/
public String[] getDatosLogin() {
String nombre = campoNombre.getText();
String password = campoPass.getText();

if (nombre.isEmpty()) {
JOptionPane.showMessageDialog(null, "El campo Nombre no puede estar vacío",
"Login Player", JOptionPane.ERROR_MESSAGE);
return null;
}

if (password.isEmpty()) {
JOptionPane.showMessageDialog(null, "El campo Password no puede estar vacío",
"Login Player", JOptionPane.ERROR_MESSAGE);
return null;
}
//Tenemos datos, los devolvemos en un array
return new String[] {nombre, password};
}
}

Este, y otros paneles que iremos haciendo, los mostraremos en un JFrame.
Este JFrame lo crearemos en la clase main, la principal. Haremos que herede de JFrame y de atributos tendrá la clase BattleShip, el "Modelo" y los distintos paneles que iremos creando, la "Vista".
Por lo tanto, esta clase equivaldrá al "Controlador", es decir, será quien ponga en comunicación la "Vista" con el "Modelo".
Estas tareas de Controlador las realizará mediante distintas clases internas de ActionListener que se asignarán a los botones de cada panel.

Por ejemplo, ya podemos incluir en esta clase main el ActionListener correspondiente al botón de validar los datos del login.
Recogerá los datos que retorna la clase PanelLogin y se los pasará a la clase BattleShip para que busque un Player que coincida con esos datos.
De momento, solo mostrará avisos indicando si el login es válido o no.

Esta sería la clase principal Main, donde ponemos como atributo un objeto de PanelLogin, lo inicializamos en el constructor, le agregamos al boton Login el ActionListener escrito al final del código.
Establecemos como contenedor del JFrame el objeto PanelLogin para que sea visible en pantalla.
Código: [Seleccionar]
public class Main extends JFrame{

private BattleShip batalla;
private PanelLogin panelLogin;

public Main() {
batalla = new BattleShip();
panelLogin = new PanelLogin();
panelLogin.botonLogin.addActionListener(new AccionLogin());

setContentPane(panelLogin);

setTitle("BattleShip");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setResizable(false);
setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Main();
}
});
}

//Clases ActionListener para PanelLogin
private class AccionLogin implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {

String[] datos = panelLogin.getDatosLogin();
if (datos != null) {
if (batalla.validarLogin(datos))
JOptionPane.showMessageDialog(null, "Login Aceptado");
else
JOptionPane.showMessageDialog(null, "Login Rechazado");
}

}
}
}

En esa clase ActionListener, pasamos los datos de login a un método boolean de la clase BattleShip, que aún no está escrito.
Pues vamos a escribírselo:

Código: [Seleccionar]
/**
* Recibe nombre y password para comprobar si existe un Player registrado
* con estos datos.<br>Si existe, este Player queda logueado.
* @param datos Array String[] con nombre y password.
* @return <i>True</i> si los datos son válidos, <i>False</i> en caso contrario.
*/
public boolean validarLogin(String[] datos) {
//Recorremos jugadores y buscamos mismo nombre, y mismo password
for (Player player: jugadores)
if (player.getNombre().equals(datos[0]) && player.getPassword().equals(datos[1])) {
//Login valido
jugador1 = player;
return true;
}
//Finalizado bucle for sin retornar true, es que el login no es válido
return false;
}

Es sencillo, recibe el array con los dos String, nombre y password.
Recorre los Players registrados y si encuentra coincidencia, marca a ese Player como logueado y retorna true.
De lo contrario, retorna falso.

Con todo esto, podemos probar a ver como va la interfaz.


Si probamos a loguearnos:


Login rechazado.
Claro, nuestra lista de Players esta vacía. Aún no hemos registrado Jugadores.
Tenemos que dotar de funcionalidad para poder hacer registros mediante el botón "Nuevo Usuario".
¿Que hacemos cuando el usuario pulse este botón?

Mostrar un nuevo formulario para pedirle nombre y password es redundante, podemos usar el mismo PanelLogin. Así, con los mismos datos, el usuario podrá loguearse con el botón "Login" o bien registrarse con el botón "Nuevo Usuario".

Para ello, volvemos a la clase Main y creamos un nuevo ActionListener para esta funcionalidad.
Haremos que BattleShip reciba un nuevo Player con los datos obtenidos del PanelLogin y si todo va bien, quedará registrado.
A Main le añadimos esta clase interna:

Código: [Seleccionar]
private class AccionNuevoUsuario implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String[] datos = panelLogin.getDatosLogin();
if (datos != null) {
//Con los datos obtenidos, creamos un nuevo Player
if (batalla.addPlayer(new Player(datos[0], datos[1])))
JOptionPane.showMessageDialog(null, "Registro aceptado",
"Nuevo Usuario", JOptionPane.INFORMATION_MESSAGE);
}

}
}
Al botón correspondiente, le añadimos esta nueva acción:
Código: [Seleccionar]
public Main() {
batalla = new BattleShip();
panelLogin = new PanelLogin();
panelLogin.botonLogin.addActionListener(new AccionLogin());
panelLogin.botonNuevo.addActionListener(new AccionNuevoUsuario());

Por último, el método de la clase BattleShip que recibe nuevos jugadores, lo vamos a retocar para que cuando el registro sea aceptado, este nuevo usuario quede ya logueado.
Código: [Seleccionar]
/**
* Recibe un Player para añadir al listado. El nuevo Player quedará logueado<br>
* El Player será rechazado si ya existe otro con el mismo nombre.
* @param jugador Objeto Player que queremos registrar.
* @return <i>True</i> si se admitó el registro,
* <i>False</i> si ha sido rechazado.
*/
public boolean addPlayer(Player jugador) {
if (jugadores.contains(jugador)) {
JOptionPane.showMessageDialog(null, "Este Jugador ya está registrado", "Nuevo Jugador",
JOptionPane.WARNING_MESSAGE);
return false; //Ya existe este Player, lo rechazamos
}
else {
jugadores.add(jugador);
jugador1 = jugador; //El nuevo usuario queda logueado
return true;
}
}

Y ahora ya podemos registrar nuevos jugadores.

682
La clase Barco entonces, tendría un atributo String para guardar su código como propone el enunciado.
Y tendría un ArrayList de objetos PuntoXY para guardar las coordenadas que le componen.

Se me ocurren por ahora un par de métodos, uno que reciba las coordenadas de un disparo y decida si "toca" o no al Barco.
Y otro para indicar si el Barco está hundido o no.

Código: [Seleccionar]
public class Barco {

private String codigo;
/*
* Portaaviones 5 PA
* Acorazado 4 AZ
* Submarino 3 SM
* Destructor 2 DT
*/
public ArrayList<PuntoXY> coordenadas;

public Barco(String codigo) {
this.codigo = codigo;
coordenadas = new ArrayList<PuntoXY>();
}

public String getCodigo() {
return codigo;
}

public void addCoordenada(PuntoXY coord) {
coordenadas.add(coord);
}

/**
* Evalúa si un disparo ha tocado a este Barco.
* @param disparo Objeto PuntoXY con las coordenadas del disparo
* @return <i>True</i> si ha sido tocado, <i>False</i> en caso contrario.
*/
public boolean evaluaDisparo(PuntoXY disparo) {
for (PuntoXY coordenada: coordenadas)
if (coordenada.equals(disparo)) {
coordenada.setTocado(true);
return true;
}
//Ninguna coordenada ha coincidido con el disparo
return false;
}

/**
* Indica si este Barco ha sido hundido.<br>
* Un Barco está hundido cuando todos sus PuntosXY
* han sido "tocados".
* @return <i>True</i> si está hundido, <i>False</i> en caso contrario.
*/
public boolean esHundido() {
for (PuntoXY coordenada: coordenadas)
if (!coordenada.esTocado()) //Al menos una coordenada no ha sido tocada
return false; //Barco no está hundido :-)
//Si durante el bucle for no se ha devuelto false, es que todas las coord. han sido tocadas
return true; //Barco hundido :-(
}

}


Con esto, con Barcos compuestos de PuntosXY, ya podemos comenzar una clase Tablero, que seguramente su código irá creciendo según avance el programa y nos surjan necesidades:

Código: [Seleccionar]
public class Tablero {

/*
* El tablero será una matriz 8x8 de tipo int.
* 0 -> Casilla sin desvelar
* 1 -> Barco
* 2 -> Barco Tocado
* 3 -> Agua/Disparo fallido
*/
private int[][] tablero;
private ArrayList<Barco> barcos;

public Tablero() {
tablero = new int[8][8];
barcos = new ArrayList<Barco>();
}

/**
* Agrega un Barco a la lista de Barcos.<br>
* Además actualiza los valores del tablero para
* representar la posición del Barco.
* @param barco Objeto Barco que añadimos al tablero.
*/
public void addBarco(Barco barco) {
barcos.add(barco);
//Modificamos tablero según coordenadas nuevo Barco
for (PuntoXY coord: barco.coordenadas)
tablero[coord.x][coord.y] = 1;
}

/**
* Recibe un disparo (un objeto PuntoXY) y comprueba
* si coincide con las coordenadas de algún barco de este
* tablero.<br>Si coincide, es que un Barco ha sido tocado.
* De lo contrario, el disparo ha fallado.<br>
* Los valores del tablero se actualizan según lo que haya ocurrido.
* @param disparo Objeto PuntoXY con las coordenadas donde se ha disparado.
* @return <i>True</i> si se ha tocado un Barco, <i>False</i> en caso contrario.
*/
public boolean evaluarDisparo(PuntoXY disparo) {
//De entrada consideramos el disparo como fallido
tablero[disparo.x][disparo.y] = 3;
/*
* Ahora recorremos los barcos y comprobamos si
* alguno tiene coordenada coincidente con
* el disparo.
* Si coincide, corregimos el valor del tablero
* para la coordenada del disparo
*/

for (Barco barco: barcos) {
if (barco.evaluaDisparo(disparo)) {
tablero[disparo.x][disparo.y] = 2; //El disparo ha tocado barco
return true;
}
}
//Si el bucle no ha retornado true, el que el disparo se ha confirmado como fallido
return false;
}

}

Ya tenemos Players y Tablero con Barcos.

También podemos comenzar la clase BattleShip, que también irá aumentando según avance el programa.

Código: [Seleccionar]
public class BattleShip {

private ArrayList<Player> jugadores;
private Player jugador1;
private Player jugador2;
private int dificultad;//1-EASY, 2-NORMAL, 3-EXPERT, 4-GENIUS
private int modo; //1-TUTORIAL, 2-ARCADE
private Tablero tablero1;
private Tablero tablero2;

public BattleShip() {
jugadores = new ArrayList<Player>();
jugador1 = null;
jugador2 = null;
dificultad = 2; //Dificultad por defecto
modo = 1; //Modo de juego por defecto
tablero1 = new Tablero();
tablero2 = new Tablero();
}


/**
* Recibe un Player para añadir al listado.<br>
* El Player será rechazado si ya existe otro con el mismo nombre.
* @param jugador Objeto Player que queremos registrar.
* @return <i>True</i> si se admitó el registro,
* <i>False</i> si ha sido rechazado.
*/
public boolean addPlayer(Player jugador) {
if (jugadores.contains(jugador)) {
JOptionPane.showMessageDialog(null, "Este Jugador ya está registrado", "Nuevo Jugador",
JOptionPane.WARNING_MESSAGE);
return false; //Ya existe este Player, lo rechazamos
}
else
return jugadores.add(jugador);
}



}

De momento solo tiene un método para añadir jugadores.

Lo siguiente sería darle métodos como por ejemplo comprobar si un login es aceptado o no.

Pero no tengo más tiempo por ahora, a ver cuando puedo retomar.
Comprueba el código que he escrito, cambia lo que quieras y pregunta lo que no te quede claro.

683
Vamos a pensar un poco en la clase BattleShip.
Será sin duda la más importante porque albergará casi toda la lógica del programa, será el "Modelo".

Tendrá como atributo un ArrayList de tipo Player, donde se irán guardando los jugadores que se den de alta en el sistema.
Por lo tanto tendrá métodos para añadir nuevo Player, eliminarlo, comprobar el password para el login....

EL login, para dar comienzo a todo se ha de loguear un jugador. Y luego para jugar se puede loguear un segundo Player.
Hay que controlar que jugador/es están logueados y para ellos podemos usar dos atributos de tipo Player.
Cuando un jugador u otro se loguea, los pasamos a estos atributos para tener constancia de que estan logueados.
Cuando hagan logout, les pasamos valor null para saber que no hay nadie logueado.

Nos puede interesar otro atributo para indicar que nivel de dificultad se ha activado, hay cuatro niveles, podemos representarlos con un simple int que vaya de 1 a 4:
1-EASY, 2-NORMAL, 3-EXPERT, 4-GENIUS

Lo mismo con el modo de juego, otro int para los dos posibles modos:
1-TUTORIAL, 2-ARCADE


Otro objeto importante que ha de tener esta clase es el Tablero, quien merece ser modelado con una clase propia.
De hecho, BattleShip tendrá dos Tableros, uno para cada Player.


Vamos a dejar aparcado de momento a BattleShip y vamos a pensar en Tablero.

Un objeto Tablero tendrá indudablemente una matriz de 8x8.
¿De qué tipo?
Pues de momento me parece que puede ser de tipo int y usar números para representar el posible valor de cada casilla del tablero, como:
0 -> Casilla sin desvelar
1 -> Barco
2 -> Barco Tocado
3 -> Agua/Disparo fallido


Insisto en que todo esto puede variar según vaya avanzando en el programa.
Y que tú, si lo crees necesario, lo adaptes como mejor te parezca.
Todo esto es como se me está ocurriendo a mi hacerlo sobre la marcha..., sin saber si llegará "a buen puerto este barco"  ;D

Creo, que puede facilitarnos las cosas que el Tablero NO se limite a tener una matriz de enteros y ya.
Quizás nos interese modelar una clase Barco, para que cada objeto Barco guarde las coordenadas (posiciones que ocupa en la matriz) por sí mismo.
Y por sí mismo, nos diga si está sano, si está tocado, si está hundido, cuantas casillas/coordenadas mide (ya que hay barcos de distinto tamaño).

Así por ejemplo, la clase Tablero puede tener un ArrayList de objetos Barco.
Y si le pasamos las coordenadas donde se ha disparado una bomba, el Tablero puede recorrer sus Barcos y que cada Barco le diga si las coordenadas de ese disparo le afecta o no.

Otra cosa, las coordenadas están representados por dos valores int. Un Barco que mida 5 casillas, significa que va a tener 5 pares de int representando esas coordenadas.
Puede que nos interese modelar otra clase para representar cada coordenada, esto nos facilitaría más compararlas para saber si dos coordenadas son iguales.
Si son iguales podemos saber cuando ha habido un impacto o cuando un Barco se está intentando colocar encima de otro.

En Java existe una clase llamada Point de la librería AWT con dos atributos X e Y para representar un "punto" en la pantalla gráfica.
Se podría usar esa clase, pero no me parece correcto coger una clase destinada para tareas con la GUI (interfaz gráfica) y usarla en otra cosa distinta.
Además, es muy sencilla, podemos modelar la nuestra propia y adaptarla a lo que necesitemos.

Podemos llamarla Punto, o PuntoXY, como prefieras.
Dos atributos serán dos int para X e Y, que vienen a indicar en que fila y columna (coordeandas) de la matriz representa este punto.

Como los Barcos van a estar "compuestos" de estos PuntosXY, nos puede interesar un tercer atributo de tipo boolean para indicar si este punto está "tocado" por un disparo o no.
Así un Barco podrá "recordar" en cuáles de sus coordenadas ha recibido disparos o no.

También le podemos poner un método equals(), así fácilmente sabremos cuando dos coordenadas son iguales.

Los atributos X e Y, debido a su sencillez, los podemos dejar como public, y así nos ahorramos los getter y setters. Pero vamos, tú hazlo como prefieras.

Esta podría ser la clase PuntoXY

Código: [Seleccionar]
public class PuntoXY {

public int x;
public int y;
private boolean tocado;

public PuntoXY(int x, int y) {
this.x = x;
this.y = y;
tocado = false;
}

public boolean esTocado() {
return tocado;
}

public void setTocado(boolean tocado) {
this.tocado = tocado;
}

@Override
public boolean equals(Object objeto) {
if (objeto instanceof PuntoXY) {
PuntoXY otroPunto = (PuntoXY)objeto;
//Son iguales si coincide la X y la Y
return (x == otroPunto.x && y == otroPunto.y);
}
else
return false;
}

}

684
Hola.
Me parece interesante desarrollar este ejercicio. Y ya puestos, intentar hacerlo con Swing.
Aunque no se hasta donde podría llegar je je.
Además por desgracia mi tiempo libre es muy limitado.

Si te parece, puedo ir mostrando como lo resolvería yo, y tu en base a eso lo vas adaptando a tu manera o bien a lo que creas que se ajusta mejor a lo que pide el enunciado.

Supongo que debemos empezar por lo básico, la clase Player.
En principio tendría 4 atributos: nombre, password, puntos acumulados el "histórico".

Para el histórico se pide guardar el resultado de sus últimas 10 partidas. El enunciado habla de utilizar un arreglo de Strings, pero para no tener que añadir código extra con el que comprobar en cuál posición del arreglo hay que insertar cada nueva entrada, me parece más cómodo usar un ArrayList para guardar Strings. Tu usa lo que creas conveniente.

Habrá un método para insertar una nueva entrada en el histórico. Puesto que solo son 10, habrá que controlar el tamaño del ArrayList.
Si es menor que 10, no pasa nada, se agrega la nueva entrada y ya está.
Pero si ya tiene 10, hay que hacer sitio a la nueva entrada y eliminar la más antigua. Esto podemos hacerlo moviendo todas las entradas una posición.
La que está en posición [1] pasa a
  • , y así ya queda eliminada la más antigua.

La [2] pasa a la [1], la [3] a la [2],....la [9] a la [8] y la nueva entrada la colocamos en la [9]

Otro método sería para mostrar el Histórico, para mostrarlo podemos construir un String con todas las entradas. Así este String podemos mostrarlo tanto por consola como en algún componente Swing, según queramos.

Otro método importante será sobreescribir el método equals() para que Java sepa como comparar objetos Player y decidir si son iguales o no.
El enunciado nos pide evitar que en la lista de Players existan usuarios con el mismo nombre, por tanto, ese será el atributo decisivo para decidir si dos objetos Player son "equivalentes" o no.

Este podría ser el código de esta clase. Según avancemos en el programa podría cambiar.

Código: [Seleccionar]
public class Player {

private String nombre;
private String password;
private int puntos;
private ArrayList<String> historico;

public Player(String nombre, String password) {
this.nombre = nombre;
this.password = password;
puntos = 0;
historico = new ArrayList<String>();
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public int getPuntos() {
return puntos;
}

/**
* Aumenta los puntos del player.<br>
* La puntuacion aumenta en 3 cuando se gana una partida.
*/
public void aumentarPuntos() {
puntos += 3;
}

/**
* Añade una nueva anotación al histórico del Player.<br>
* Existe un límite de 10 anotaciones, por lo que al alcanzar
* este límite se eliminarán las anotaciones más antiguas para
* dar cabida a las más recientes.
* @param anotacion String con la anotación que queremos anotar.
*/
public void anotarHistorico(String anotacion) {
if (historico.size() == 10) { //Alcanzado límite de 10 anotaciones
/*
* En este caso se han de desplazar todas las anotaciones
* una posición, eliminando así la más antigua (posición 0).
* La nueva anotación queda como la más reciente (posición 9).
*/
for (int i = 1; i < 9; i++)
historico.set((i-1), historico.get(i));

historico.set(9, anotacion);
}
else //Aun no tenemos 10 anotaciones, añadimos sin más.
historico.add(anotacion);
}

/**
* Muestra el histórico de resultados de las partidas
* jugadas por el Player.
* @return String con todas las anotaciones del histórico.
*/
public String mostrarHistorico() {
StringBuilder sb = new StringBuilder("\t\tHISTÓRICO");
sb.append("\t\t---------\n");
for (String anotacion: historico)
sb.append(anotacion + "\n");

return sb.toString();
}


@Override
public boolean equals(Object objeto) {
if (objeto instanceof Player) { //Es un objeto Player
Player otroPlayer = (Player)objeto;
//Dos Player son iguales si tienen mismo nombre
return nombre.equals(otroPlayer.nombre);
}
else
return false; //Ni siquiera es un objeto Player
}

}

685
Hola Diana.

Comienza el programa, llega hasta donde puedas y te vamos guiando.

Puedes hacerte un "guión" de los pasos a seguir en el programa.

Por ejemplo:

  • JOptionPane con mensaje de entrada, tipo "Bienvenido al Sistema de Gestión de Notas"

  • Pedir los tres cortes de notas, indicando para cada uno el porcentaje que representan en la nota final. Las notas puedes guardarlas en tres variables distintas, o mejor aún, en un array de tres elementos.
    Puesto que son notas, el tipo de dato debería ser float o double, pero también puedes hacerlo con int.
    Hay que tener en cuenta que JOptionPane te va a devolver un String, así que ese String habrá que parsearlo al tipo de dato que elijas para las notas. Si eliges float, pues el String que te da el JOptionPane lo parseas con el método Float.parseFloat(String datoAParsear)

  • Otro JOptionPane para pedir nombre. Se guarda en un String y listo

  • Otro JOptionPane para pedir código asignatura. En este caso se puede usar un JOptionPane.showOptionDialog() el cuál nos permite definir los botones que va a tener para que elija el usuario.
    Estos botones los definimos con un arreglo de tipo String que contenga las distintas opciones. En este caso son tres opciones, que son los códigos de asignaturas: "2019", "2014" y "2015".
    Con otro String le decimos que mensaje queremos mostrar, en el cuál indicaremos al usuario a que asignatura pertenece cada código, para que sepa que es lo que está escogiendo.
    Este JOptionPane retorna un int que representa la opción escogida. Es decir, si el usuario escoge el primer botón (código 2019) el JOptionPane retorna un 0.
    Si escoge el segundo (código 2014) retorna un 1.
    Etc.
    Este valor retornado lo tenemos que guardar en un int

  • Calcula promedio ponderado. Inténtalo, si no sabes cómo ya te lo mostraré.
    Pero intenta tú escribir algo de código.

  • Por último, evaluar el int para saber que asignatura se ha puntuado. Esto podemos hacerlo con un switch.
    Según la asignatura, ahora evaluamos en que rango está la nota final que hemos calculado con el promedio ponderado.
    Y según la asignatura y rango de notas, mostramos un JOptionPane informando del nombre, si ha reprobado, aprobado con suerte o con honores, que asignatura y con cuál nota final.

  • Un último JOptionPane indicando que el programa ha termiando.

Y más o menos estos 7 pasos son los que habría que seguir.
Insisto, comienza y llega hasta donde puedas. Luego te ayudamos con el resto.

686
Yo lo haría así
Código: [Seleccionar]
para a < - 0 hasta n-2 hacer
    para b <- a+1 hasta n-1 hacer
        si datos[a] + datos[b] = numN entonces
            Escribir "Verdadero"," Puesto que ",datos[a]," + ", datos[b], " = ", numN;
        finsi
    finpara
finpara

El primer bucle recorre desde el primer valor, hasta el penúltimo.
El segundo bucle, comienza por el siguiente valor al que está apuntando actualmente el primer bucle, hasta el final.
Así se evitan comprobaciones redundantes

Es decir, la primera ejecución se cogería el valor en la posición [ 0 ], el segundo bucle comenzaría por el [1] hasta el final.
Luego el primer bucle coge el [1], y el segundo bucle el [2], y de nuevo hasta el final.
El segundo bucle no pasará por el valor[ 0 ], porque ya se han probado sus posibles combinaciones en la primera ejecución.

En la tercera ejecución, primer bucle se posiciona en [2] y el segundo bucle en [3], y a probar combinaciones hasta el final...

Y así hasta comprobar todas las combinaciones.

Lo he probado transcribiendolo a Java y parece que funciona bien.


Tan solo hay dos detalles que no se han tenido en cuenta.
- Solo hay mensaje para cuando es VERDADERO, no estamos controlando que pasa cuando es FALSO.
- Tal cuál está escrito, se mostrarían en pantalla todas las posibles combinaciones que sumen numN. Es decir, podría mostrarse varias veces el mensaje de VERDADERO.
Esto no es malo per se, pero posiblemente queramos que solo se muestre una vez, o sea, cuando encuentre una combinación válida, que indique VERDADERO y deje de seguir probando otras combinaciones.

Ambos detalles, podrían controlarse usando un boolean que adopte valor TRUE cuando se encuentre una combinación.
De ese modo, sabríamos cuando poner fin a los bucles y además luego al final de todo sabríamos si hay que mostrar el mensaje de FALSO o no.

En cualquier caso, en un ejercicio de pseudocódigo no se si es exigible controlar estos detalles.

Inténtalo si quieres y si tienes dudas pregunta por aquí.

687
Hola.
Si accedemos al directorio donde están las imagenes que has subido:
http://acsebas.byethost32.com/images/

No hay ninguna imagen llamada avatar1.jpg, que es lo que has puesto en el código HTML.

Sí existe una llamada avatar.png, quizás era esta la que querías visualizar y erraste al poner el nombre en el HTML



EDITO:

A ver, en el HTML que has compartido aquí en el foro, si está puesto avatar.png.

Pero en la web que has subido no,:


688
Hola.
El método length() ya te proporciona cuántos caracteres tiene el String, no necesitas recorrer los caracteres con el bucle para contarlos.

Sin embargo, si pretendes que cada tres cifras/caracteres se inserte un espacio en blanco, la lógica que estás siguiendo me parece que no te servirá cuando tengas 6 números o más.

Me ha parecido interesante tu propuesta y he probado a ver que solución se me ocurría.
Y se me ha ocurrido una.

He hecho una pequeña interfaz más sencilla que la tuya, tan solo dos campos de texto, uno para mostrar los números, otro para introducirlos por teclado, y un botón para enviar lo tecleado al campo de texto que lo muestra.



Como puedes ver en la imagen, da igual la cantidad de números que se introduzcan. Cada tres cifras se insertar un espacio en blanco cuando se envía al campo superior.

Para conseguirlo lo que hago es recoger el texto que se ha introducido.
Y a partir de este texto, construyo un nuevo String (me apoyo en la clase StringBuilder que es más óptima para estas cosas).

Con un bucle recorro cada carácter del String original.
Y voy añadiendo carácter a carácter al nuevo String.
Cada tres caracteres que añado, entonces añado además un espacio en blanco.

Para saber cuándo llevo tres caracteres añadidos, podría haber usado un contador que al llegar a 3 se reinicie a 0 y empiece de nuevo.
Pero me ha parecido más rápido consultar si el indice del bucle que va recorriendo los caracteres, es un múltiplo de 3.
Los múltiplos de 3 son 3, 6, 9, 12, 15, etc...
De ese modo, cada posición 3, 6, 9...se insertará el espacio en blanco.

Te pongo aquí el código completo, coloreo el código de la clase ActionListener que añado al botón enviar, que es quién se encarga de construir el nuevo String como he explicado.
A ver si te resulta útil. Cualquier duda, solo tienes que preguntarla. Un saludo.

Citar
public class Separar extends JFrame{

   private JTextField display;
   private JTextField entrada;
   private JButton btEnviar;

   public Separar() {
      display = new JTextField(30);
      display.setEditable(false);
      display.setHorizontalAlignment(JTextField.CENTER);
      entrada = new JTextField(15);
      btEnviar = new JButton("Enviar");
      btEnviar.addActionListener(new AccionEnviar());

      JPanel panelDisplay = new JPanel();
      panelDisplay.add(display);
      JPanel panelEntrada = new JPanel();
      panelEntrada.add(entrada);
      JPanel panelEnviar = new JPanel();
      panelEnviar.add(btEnviar);
      
      JPanel principal = new JPanel();
      principal.setLayout(new GridLayout(3, 0, 10, 10));
      principal.add(panelDisplay);
      principal.add(panelEntrada);
      principal.add(panelEnviar);
      
      add(principal);
      setTitle("Separar de 3 en 3");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      pack();
      setLocationRelativeTo(null);
      setVisible(true);
   }

   private class AccionEnviar implements ActionListener  {

      @Override
      public void actionPerformed(ActionEvent e) {

         String texto = entrada.getText();
         
         StringBuilder numeros = new StringBuilder();

         //Iremos añadiendo los caracteres recibidos y cada 3 pondremos un espacio
         for (int ix = 0; ix < texto.length(); ix++) {
            //Si el indice ix es multiplo de 3, es que ya llevamos 3 caracteres, ó 6, ó 9...
            if (ix % 3 == 0)
               numeros.append(" ");//Así que insertamos espacio en blanco
            
            //Añadimos carácter
            numeros.append(texto.charAt(ix));
            
            
         }
         //Tenemos un string con los caracteres separados de 3 en 3.
         //Los pasamos al display

         display.setText(numeros.toString());

      }
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         @Override
         public void run() {
            new Separar();
         }
      });
   }

}




689
Hola,
en principio sí se puede hacer.

Yo alguna vez he hecho algo similar, reaprovechar un mismo formulario para ambas funcionalidad, mostrar y registrar datos.
Y lo que me ha ayudado ha sido incluir un boolean en su constructor para indicar que comportamiento voy a requerir
Así, según el valor de ese boolean, pues al construir el formulario decido qué elementos (campos, botones, etc...) quiero que estén activos, cuáles no, cuáles quiero que sean visibles...

690
Comunidad / Re:Presentación
« en: 08 de Junio 2020, 18:59 »
Bienvenido.
Cualquier cosa que puedas aportar siempre será de agradecer.

Un saludo.

691
Comunidad / Re:Presentación
« en: 05 de Junio 2020, 18:45 »
Bienvenido,

en la web principal tienes cursos para aprender cosas nuevas o reforzar conocimientos ya adquiridos.

Un saludo.  ;)

692
La línea donde haces la suma, debería ir dentro del ciclo while:

main(){
   
   float precio=0, total=0;
   
   printf("Ingresa el precio:");
   scanf("%f", &precio);
   
    while (precio>0 ){   
   printf("Ingresa el precio:");
   scanf("%f", &precio);
   total=+precio;
   }
   
     
   printf("\nLa compra total es de:%.2f", total);
}

693
Comunidad / Re:Saludos
« en: 01 de Junio 2020, 11:39 »
Bienvenido.
Esperamos que te sientas a gusto y participes en el foro.

Un saludo.

694
Sí, al usar printf, se complica imprimir el carácter % por ser precisamente el carácter comodín que utiliza printf.

Prueba a no imprimirlo directamente, sino pasándolo como un parámetro string para que sea formatedo por el comodín ->  %s
Algo como esto. Marco en negrita los cambios.

Citar
printf("\n %d %s  %d= %d", valor1, "%", valor2, modulo);

A ver si así te funciona.

695
Hola.
Quizás no está recibiendo correctamente el dato de precio y al querer parsearlo a Double se produce la excepción.

Los parseos de cadenas String a valores numéricos siempre son "arriesgados", así que hay que poner medidas de control para decidir que hacer en caso de que no sea posible parsear y evitar que el programa se interrumpa porque no sabe que hacer.

Puedes usar try catch

Código: [Seleccionar]
double e;
try {
    e = Double.parseDouble(precio);
} catch (Exception ex) {
    e = 0d; //Parseo ha fallado, damos un valor double a e, aunque sea 0, para que el programa continúe
}

Ahí en el catch, hacemos que al menos la variable e obtenga un valor double válido.
Así el programa podrá continuar y se creará un objeto libro, con un precio de 0, pero al menos el programa continúa y puedes comprobar si el resto del código está funcionando bien.

En el catch puedes hacer lo que quieras, puedes pedirle que te muestre el valor del String precio, para ver por qué no ha sido posible parsearlo a double.

696
El atributo color es para modificar el color del texto

Puesto que la etiqueta <hr>(separador) no muestra texto, ese atributo le es indiferente.
Por eso no aprecias ningún cambio, a <hr> solo le afectaría el atributo background-color, por eso lo seguías viendo naranja.

No todos los atributos son aplicables a todas las etiquetas. Ya lo irás viendo cuando te metas en CSS.

Un saludo.

697
Aprender a programar desde cero / Re:Arreglos con String
« en: 19 de Mayo 2020, 18:31 »
Hola.

Si te fijas, cada String del arreglo auxiliar contiene 4 datos. Están juntos en el mismo String, pero separados por un ;

Bien, la clase String tiene un método llamado split() al cuál podemos pedirle que separe un String a partir de un carácter o una cadena.
Entonces, si le pedimos que haga split(";") , dividirá cada uno de esos String en 4 String separados y los devolverá en un arreglo de 4 posiciones.

Si tenemos 10 String, y de cada uno de ellos podemos obtener 10 arreglos de 4 posiciones, pues ya podemos construir la matriz de [10,4].

Entonces, la mecánica a seguir es usar un bucle para recorrer las 10 posiciones del arreglo auxiliar.
Por cada String que contiene, usamos split(";") y obtenemos un arreglo de 4 posiciones, con los 4 datos ya separados.
Este arreglo de 4 posiciones, lo insertamos en la matriz, en la misma posición que hemos usados para leer el arreglo auxiliar.
Y el bucle se repite hasta completar las 10 posiciones.

Este podría ser un código que cumpliera con esto.
Luego al final se muestra en pantalla los datos de la matriz para comprobar que se han obtenido los datos.
Pruébalo, asegúrate de que lo comprendes y no dudes en preguntar y repreguntar lo que sea.
Un saludo.

Código: [Seleccionar]
public class Main {

public static void main(String[] args) {

String[] auxiliar = new String[10];

        auxiliar[0] = "16.125.690-0;CLAUDIO ANTONIO HONORATO DE LA FUENTE;240000;PJE. ESTERO AZUL N 1742";
        auxiliar[1] = "16.107.855-7;BARBARA FABIOLA DELGADO SANCHEZ;216800;PJE. SCHEAT 8587 - VILLA ESTRELLA SUR";
        auxiliar[2] = "16.082.439-5;PABLO ANDRES HENRIQUEZ LEON;353657;AURORA 8964";
        auxiliar[3] = "16.030.010-8;JORGE ARIEL CARTES JARA;478604;AMUNATEGUI N 630 BARRIO STA ANA";
        auxiliar[4] = "15.822.860-2;CESAR ALEJANDRO LIGUENO ROJAS;901209;CATEDRAL 1450 DPTO 108";
        auxiliar[5] = "15.798.385-7;JUAN PABLO ESCANILLA CORREA;525000;HERALDICA 8861";
        auxiliar[6] = "15.797.263-4;DOMINGO HERNAN DIAZ MORALES;380000;AV. FRESIA 2375";
        auxiliar[7] = "15.775.088-7;NICOLAS BENJAMIN ANDAUR MOREIRA;240000;SAN IGNACIO 268 PJE. INTERIOR 2 - CASA 191";
        auxiliar[8] = "15.767.949-K;BEATRIZ IDAMIA ORTIZ CESPEDES;1250000;PSJE SAN MARTIN 958";
        auxiliar[9] = "15.754.871-9;CHRISTOPHER JONATHAN OLGUIN ALVARADO;755000;LA LLARETA 9073";
       
        String[][] matriz = new String[10][4];
       
        /*
         * Cada String del arreglo auxiliar contiene 4 datos separados por ;
         * Estos String se pueden descomponer en un arreglo de 4 String donde
         * almacenar esos 4 datos por separado.
         * Para ello, podemos usar el método split() de la clase String, indicándole
         * que separe el String original allá donde encuentre un ;
         * Este método nos dará un arreglo String con los 4 datos ya separados,
         * con los cuáles construiremos la matriz 10,4
         */
        for (int i = 0; i < auxiliar.length; i++) {
        //Con split(), dividimos cada String en un arreglo de 4 String
        String[] datos = auxiliar[i].split(";");
        //Este arreglo de 4 datos, lo insertamos en la matriz
        matriz[i] = datos;
        }
       
        //Mostramos la matriz con el resultado final
        for (int i = 0; i < matriz.length; i++)
        System.out.println(Arrays.toString(matriz[i]));

}

}

698
Con ese import, ha de funcionar, lo acabo de probar y puedo crear un objeto Gerente sin problemas:
Código: [Seleccionar]
package consulta.empleados;

import abstacto.empleados.*;

public class consultarEmpleados {


public static void main (String[]args){

Gerentes ger = new Gerentes("");

}

}

¿Qué error te marca? ¿Qué dice exactamente?

Por cierto, si tiene algo que ver con este método que has puesto:
Código: [Seleccionar]
    public void setDatos(String grupoEmpleados, String Gerentes) {
        grupoEmpleados= Gerentes;
        System.out.println("El grupo de empleados es: Gerentes");
    }

Ahí no estás trabajando con esas clases. Lo de ese método son Strings

699
Comparte el código que quieras, el foro está a tu disposición.
Un saludo.

700
Disculpa, pero no me queda claro cuál es el problema que te ha surgido.
Si pudieras concretarlo, a ver si podemos echarte una mano.

Un saludo.

Páginas: 1 ... 30 31 32 33 34 [35] 36 37 38 39 40 ... 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".