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 ... 13 14 15 16 17 [18] 19 20 21 22 23 ... 50
341
Hola.
Nunca he programado en Small Basic (ni sabía que existía)

He curioseado un poco y mira, te escrito este código de ejemplo donde se piden 10 productos con sus precios (precio de costo).
Se puede ver como se indexan en una matriz y como se accede luego a cada dato para mostrarlo en pantalla.

Básicamente solo faltaría aplicarle a cada precio de costo el aumento del 30% para calcular y mostrar el precio final.

A ver si consigues hacerlo tú. Cualquier problema, vuelve a pedir ayuda por aquí.

Código: [Seleccionar]
TextWindow.WriteLine("FLORERIA SMALL BASIC")
TextWindow.WriteLine("--------------------")
TextWindow.WriteLine("")
For f = 1 To 10
    TextWindow.Write("Nombre Producto: ")
    nombre = TextWindow.Read()
    TextWindow.Write("Precio Costo: ")
    precio = TextWindow.ReadNumber()
    productos[f]["nombre"] = nombre
    productos[f]["costo"] = precio
EndFor
TextWindow.WriteLine("")
TextWindow.WriteLine("     --- MOSTRANDO LISTADO DE PRODUCTOS---")
TextWindow.WriteLine("")
For f = 1 To 10
    TextWindow.Write("Nombre: " + productos[f]["nombre"])
    TextWindow.WriteLine(" - Precio: " + productos[f]["costo"])
EndFor

342
Pues a ver... porque no es fácil de explicar el Counting Sort....

Counting Sort es un algoritmo de ordenación muy útil cuando se trata de valores numéricos.
Normalmente las ordenaciones se hacen comparando un valor con otro, a ver cuál es mayor o menor..
Esto es fácil de entender y aplicar, pero requiere muchos ciclos de computación y por mucho que se optimice el código, siempre se van a repetir comparaciones innecesarias, pero inevitables.

Counting Sort es más eficaz porque no hace comparaciones. Lo que hace es crear un arreglo que representa TODOS los valores posibles dentro de una secuencia YA ORDENADA.
Cada elemento del arreglo hará la función de contador.
La secuencia siempre ha de ser entre 0 y un valor límite, que se ha de conocer de antemano.
Luego coge la lista de valores SIN ORDENAR y hace un recuento de cuántas veces aparece un determinado valor.

De esta manera, en el arreglo de contadores ordenados, ya sabe qué valores de la lista sin ordenar aparecen, y cuántas veces.

No se entiende un pijo, ¿verdad?  :-\


Vamos a probar de otra manera. Mira, este método sería el algoritmo de ordenación Counting Sort

Código: [Seleccionar]
private static void countingSort(int[] valores, int limite) {

//Creamos array de contadores
int[] contadores = new int[limite + 1];

//Recorremos valores y los contamos
//Cada valor nos dice que contador hemos de incrementar
//Si por ejemplo el valor es 1, hay que incrementar el contador [1], etc...
for (int valor: valores)
contadores[valor]++;

//Ordenamos el array de valores, según lo contado para cada valor
int indice = 0;
for (int i = 0; i < contadores.length; i++) {
while (0 < contadores[i]) {
valores[indice] = i;
indice++;
contadores[i]--;
}
}

}

Como mi explicación no se ha entendido, el código tampoco se va a entender.
Pero ahora vamos a intentar hacer una representación visual de cada línea de código de ese algoritmo.

Por ejemplo, tenemos esta lista SIN ORDENAR:
Citar
3, 2, 5, 1, 3, 5

Ya vemos que son valores entre 0 y 5(límite)

El algoritmo lo primero que va a hacer es crear un array de 6 contadores (limite + 1):
Código: [Seleccionar]
//Creamos array de contadores
int[] contadores = new int[limite + 1];
Así que en memoria tendríamos algo como esto:


El siguiente paso del algoritmo es recorrer los valores sin ordenar, y para cada valor incrementar el contador correspondiente.
Es decir, el primer número de la lista es el 3
Pues el contador en posición [3] se incrementa en  +1

Luego viene el 2, pues incrementamos el contador [2]

Luego viene el 5, el 1, otra vez el 3 y otra vez el 5.

Pues tras incrementar todos los contadores correspondientes, el array ahora quedaría así:


¿Lo ves? En este array ya tenemos todo lo que necesitamos para recrear la lista anterior, pero ordenada.
Sabemos que no hay ningún 0 en la lista, ni tampoco ningún 4, porque sus contadores no se han incrementado.

Sabemos que hay un 1, un 2, dos 3 y dos 5.
Es decir, la lista ordenada sería:
Citar
1, 2, 3, 3, 5, 5
Se ha conseguido ordenar sin hacer ninguna comparación, tan solo usando contadores.

Ahora falta un último paso, modificar el array de los valores desordenados, colocando los valores de forma ordenada, a partir del array de contadores.
Código: [Seleccionar]
//Ordenamos el array de valores, según lo contado para cada valor
int indice = 0;
for (int i = 0; i < contadores.length; i++) {
while (0 < contadores[i]) {
valores[indice] = i;
indice++;
contadores[i]--;
}
}
Esta parte del código es la que más cuesta entender.
El bucle for, utiliza la i para recorrer el array de contadores.
El bucle while, añade al array de valores, los nuevos valores ordenados, según lo que se ha contado en el contador al que apunta la i

Si en una posición no se ha contado nada (contadores[ i ] es igual a 0), como ocurre con el 0 y el 4 en este ejemplo, pues el bucle while no hace nada y se pasa al siguiente contador.

Cuando sí se ha contado algo en una posición, el bucle while se repite tantas veces como indique el valor de ese contador.
Y, usando un índice que vamos a incrementar manualmente, añade al array de valores, el valor que tenga la i del bucle for.
Y entonces decrementa el contador hasta que llegue a 0, para que el while termine y pasemos al siguiente contador.

Es decir, teniendo este array de contadores:


Para la posición [ 0 ], el contador es 0, el while no va a hacer nada.

En la posición [1], el contador es 1, así que el while va añadir un 1 a la lista de valores ordenados.
Decrementará este contador, alzando el valor 0 y por tanto el while termina

En la posición [2], se ha contado 1, así que se añadirá un 2.
De nuevo decrementa el contador, alcanzando 0, por lo que el while cierra su ciclo.

En [3], se han contado 2.
Se añadirá primero un 3 y se decrementa el contador. Ahora tiene valor 1, así que el while repite el ciclo agregando otro 3 a la lista de valores.
Se decrementa el contador y ahora sí alcanza valor 0, así que while se termina.

En [4], el contador es 0, así que el while no interviene y se pasa al siguiente contador.

En [5], se han contado 2. Así que se añadirá un 5 y luego otro 5 más hasta agotar el contador con sendos decrementos.



Y ya tendríamos la lista completa y ordenada.

Espero que haya quedado más o menos claro. Hay cosas que son simples, pero algo difíciles de explicar.

A continuación te dejo un programa completo para poner a prueba este algoritmo:

Código: [Seleccionar]
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;

public class CountingSort {

public static void main(String[] args) {

Scanner teclado = new Scanner(System.in);

System.out.print("¿Cuántos valores quieres crear?: ");
int numV = teclado.nextInt();
System.out.println("Se crearán valores entre 0 y un límite que tú decides.");
System.out.print("Valor límite: ");
int limite = teclado.nextInt();

int[] valoresAzar = crearValores(numV, limite);

System.out.println("\nValores sin ordenar");
System.out.println(Arrays.toString(valoresAzar));

countingSort(valoresAzar, limite);

System.out.println("\nValores ordenados mediante algoritmo Counting Sort");
System.out.println(Arrays.toString(valoresAzar));

System.out.println("\n\t\tFIN DE PROGRAMA");
teclado.close();
}

private static int[] crearValores(int nV, int lmt) {

Random azar = new Random();

int[] v = new int[nV];
for (int i = 0; i < nV; i++)
v[i] = azar.nextInt(lmt+1);

return v;
}

private static void countingSort(int[] valores, int limite) {

//Creamos array de contadores
int[] contadores = new int[limite + 1];

//Recorremos valores y los contamos
//Cada valor nos dice que contador hemos de incrementar
//Si por ejemplo el valor es 1, hay que incrementar el contador [1], etc...
for (int valor: valores)
contadores[valor]++;

//Ordenamos el array de valores, según lo contado para cada valor
int indice = 0;
for (int i = 0; i < contadores.length; i++) {
while (0 < contadores[i]) {
valores[indice] = i;
indice++;
contadores[i]--;
}
}

}

}

Al ejecutarlo, en pantalla veremos que funciona correctamente:
Citar
¿Cuántos valores quieres crear?: 15
Se crearán valores entre 0 y un límite que tú decides.
Valor límite: 50

Valores sin ordenar
[45, 2, 29, 44, 34, 33, 34, 9, 24, 35, 42, 27, 37, 20, 30]

Valores ordenados mediante algoritmo Counting Sort
[2, 9, 20, 24, 27, 29, 30, 33, 34, 34, 35, 37, 42, 44, 45]

      FIN DE PROGRAMA


Si quedan dudas, vuelve a preguntar.
Un saludo.

343
Hola Miguel.

Hablamos de este ejercicio

¿Cuál es la duda?

Fijándote en el ejercicio anterior de las clases Profesor, se puede desarrollar este ejercicio de los Productos, pero si no sabes por donde empezar, te podemos dar algunas indicaciones.

El enunciado dice que hay tres tipos de productos:
frescos, refrigerados y congelados.

Así que ya sabemos que tenemos que modelar las clases para estas tres entidades.
Dichas entidades, TODAS ellas son productos.
Esto significa que tienen algunas características (atributos) propias de cada una, pero también van a tener algunas que son comunes a todas ellas.
Estos atributos comunes son: fecha de caducidad y número de lote

En casos como este, para no replicar tres veces esos mismos atributos en cada una de las tres clases, es más óptimo crear una superclase con dichos atributos.
Así solo hay que escribir el código de estos atributos una sola vez y podrán ser usados en las clases hijas que hereden de esta superclase, ya sean tres, treinta, o treinta millones...

Así pues, tendríamos esta superclase, con dos atributos:

Producto
- fechaCaducidad
- numLote


Las clases hijas, serían:

Citar
Los productos frescos deben llevar la fecha de envasado y el país de origen.

ProductoFresco
- fechaEnvasado
- paisOrigen



Citar
Los productos refrigerados deben llevar el código del organismo de supervisión alimentaria.

ProductoRefrigerado
- codigoSupervision



Citar
Los productos congelados deben llevar la temperatura de congelación recomendada.

ProductoFresco
- tempCongelacion




Bien, pues escribe el código de esas 4 clases, con sus atributos, sus constructores, sus getter y sus setter.

Recuerda que hay una relación de herencia:
Código: [Seleccionar]
public ProductoFresco extends Producto {

}

Cuando las tengas. Haz una última clase, con método main(), para crear objetos de estas clases y comprobar que funcionan bien.

No importa si no lo consigues, si te quedan mal, si te atascas en algún punto...
Haz hasta donde puedas, luego lo compartes aquí en el foro y te ayudamos a completar y corregir.

Un saludo.

344
La idea es evaluar el tipo de compra con un if, ya que solo hay dos posibilidades: productos o millas
Dentro de cada posibilidad, ya sí se piden los demás datos y se evalúa con switch, si se desea.
Así se evita anidar un switch dentro de otro.

Algo como:

Código: [Seleccionar]
if (lCompra.equals("producto")) {
    //Código para gestionar venta de productos
    //Pedir importe, medio de pago, evaluar con switch, etc..
}
else {
    //Código para gestionar venta de millas
    //Pedir importe, medio pago, evaluar con switch...
    //Como para millas solo hay dos medio de pago posibles,
    //también se podría evaluar con if else.
}

345
Yo lo que cambiaría sería lo de anidar switchs dentro de otros. Es difícil de leer y en ocasiones Java puede equivocarse y relacionar un case con el switch equivocado.

Además como la primera disyuntiva solo tiene dos posibilidades: producto o millas, esta la habría hecho con un if else.
Ya luego dentro del if si habría usado switch para evaluar los medios de pago.

346
Más o menos.

Digamos que hay dos tipos de datos:
- los primitivos, que son muy básicos, ya que la única información que contienen es su propio valor.
Estos datos, en Java, son: byte, int, float, double, char(en realidad es un int) y boolean.

- Los objetos de clase, son mucho más avanzados. No solo contienen su propio valor, de hecho, pueden contener muchos valores distintos al mismo tiempo, pero además incorporan funcionalidades a través de sus "métodos".
Un objeto de clase, es prácticamente un programa autónomo, que podemos diseñar para que sea todo lo sencillo, o todo lo complejo que queramos.
Este tipo de dato "nació" cuando se desarrolló la POO(Programación Orientada a Objetos)

Los array(o arreglos, o vectores, o como queramos llamarlos...), en este ejercicio, almacena el tipo primitivo int.
Sin embargo, también pueden almacenar objetos de clase, podría hacerse un array de Integer.

Los ArrayList, así como el resto de colecciones de Java (los List, los Map,...) solo pueden trabajar con objetos de clase, no aceptan tipos primitivos.

Bueno, en realidad si los aceptan, lo que pasa es que los transforman en objetos sin que nosotros lo veamos.

Por ejemplo, en esta línea:
Código: [Seleccionar]
lista1.add(miArray1[i]);
Al ArrayList lista1, que es de hecho un objeto de clase ArrayList, le estamos pasando un valor int primitivo (porque es lo que lo tiene el array) a través de su método add().
Este método, coge el int primitivo, y sin que lo veamos, construye a partir de él un objeto Integer para poder almacenarlo en el ArrayList.

Eso no ocurre por arte de magia, alguien escribió el código del método add() para que haga ese proceso y así la clase ArrayList es capaz de aceptar ints primitivos, transformándolos automáticamente en objetos Integer.

Eso es lo maravilloso de la POO, cada objeto es como un programa individual que contiene y ejecuta sus propios algoritmos de forma ajena al programa principal.

Un saludo.

347
Hola y bienvenido.
En programación, hasta el ejercicio más simple puede tener más de una forma de solucionarse.

Por cierto, ¿la respuesta a estas preguntas?  ::)

Citar
¿Qué tipo de datos almacena el array? ¿Qué tipo de datos almacena el ArrayList?

Aunque no lo parezca, tiene su importancia tener claras las respuestas a estas preguntas.

348
Hola.
Una LinkedList es casi lo mismo que un ArrayList, solo que tiene mejor rendimiento insertando elementos, pero peor rendimiento haciendo búsquedas entre sus elementos.

Más info aquí

El programa te pide algo así.

Primero una clase Ubicacion, que sea capaz de compararse mediante sus coordenadas para ordenarse de forma ascendente:
Código: [Seleccionar]
package ubicacionLinkedList;

public class Ubicacion implements Comparable<Ubicacion>{

private int coordX;
private int coordY;

public Ubicacion(int cX, int cY) {
coordX = cX;
coordY = cY;
}

public int getCoordX() {
return coordX;
}

public int getCoordY() {
return coordY;
}

@Override
public String toString() {
return String.format("[X: %d / Y: %d]", coordX, coordY);
}

@Override
public int compareTo(Ubicacion otraUbicacion) {
if (coordX != otraUbicacion.coordX)
return Integer.compare(coordX, otraUbicacion.coordX);
else
return Integer.compare(coordY, otraUbicacion.coordY);
}

}

Luego, simplemente hay que añadir Ubicaciones a una LinkedList y mantenerlas ordenadas.
Finalmente buscar cuál es la que tiene mayor valor en la coordenada Y.

Lo pide con GUI, no tengo tiempo ahora, pero en modo consola vendría a ser algo como esto:
Código: [Seleccionar]
public class Test {

public static void main(String[] args) {

var ubicaciones = new LinkedList<Ubicacion>();
var teclado = new Scanner(System.in);
char continuar = 's';

while (continuar == 's') {
System.out.println("Nueva Ubicacion....");
System.out.println("Indique coordenada X: ");
int cX = Integer.parseInt(teclado.nextLine());
System.out.println("Indique coordenada Y: ");
int cY = Integer.parseInt(teclado.nextLine());
//Agregamos Ubicacion y las ordenamos
ubicaciones.add(new Ubicacion(cX, cY));
ubicaciones.sort(null);
//Las mostramos
System.out.println("\nUbicaciones registradas:");
for (Ubicacion ubi: ubicaciones)
System.out.println(ubi);

System.out.println("\n¿Continuar?[s/n]");
continuar = teclado.nextLine().toLowerCase().charAt(0);
}

//Buscamos coordenada con mayor Y
//Para comparar comenzamos con el mínimo valor posible para Y
Ubicacion mayorY = new Ubicacion(0, Integer.MIN_VALUE);

for (Ubicacion ubi: ubicaciones) {
if (ubi.getCoordY() > mayorY.getCoordY()) {
mayorY = ubi;
}
}

System.out.println("\nUbicacion con mayor Y:\n" + mayorY);

System.out.println("\n\n\t\tFIN DE PROGRAMA");
teclado.close();

}

}

En pantalla veremos que las Ubicaciones se van ordenando correctamente, y que al final muestra cuál tiene mayor valor Y

Citar
Nueva Ubicacion....
Indique coordenada X:
5
Indique coordenada Y:
5

Ubicaciones registradas:
[X: 5 / Y: 5]

¿Continuar?[s/n]
s
Nueva Ubicacion....
Indique coordenada X:
3
Indique coordenada Y:
3

Ubicaciones registradas:
[X: 3 / Y: 3]
[X: 5 / Y: 5]

¿Continuar?[s/n]
s
Nueva Ubicacion....
Indique coordenada X:
8
Indique coordenada Y:
8

Ubicaciones registradas:
[X: 3 / Y: 3]
[X: 5 / Y: 5]
[X: 8 / Y: 8]

¿Continuar?[s/n]
s
Nueva Ubicacion....
Indique coordenada X:
3
Indique coordenada Y:
9

Ubicaciones registradas:
[X: 3 / Y: 3]
[X: 3 / Y: 9]
[X: 5 / Y: 5]
[X: 8 / Y: 8]

¿Continuar?[s/n]
s
Nueva Ubicacion....
Indique coordenada X:
8
Indique coordenada Y:
1

Ubicaciones registradas:
[X: 3 / Y: 3]
[X: 3 / Y: 9]
[X: 5 / Y: 5]
[X: 8 / Y: 1]
[X: 8 / Y: 8]

¿Continuar?[s/n]
n

Ubicacion con mayor Y:
[X: 3 / Y: 9]


      FIN DE PROGRAMA

Y ya está. Según entiendo, esto es lo que se pide, pero mediante una GUI.

Un saludo.

349
Parece que cumple con lo que se pide.
Solo comentar que puedes ahorrar alguna líneas haciendo la inicialización de las variables al mismo tiempo que las declaras:

Código: [Seleccionar]
int anoNto = 0;
int edadPs = 0;
int edadMayor = 0;
int anoActual = 0;
String mesa = "";
String jurado = "";

350
Vale, creo que entiendo lo que pides.

A ver, esta sería mi clase Preguntas
Es un array con los String de cada pregunta.
Uso una variable como  índice para apuntar a la pregunta que actualmente se estará mostrando en la interfaz.
Dispone de unos métodos para apuntar a la pregunta siguiente o a la anterior, siempre controlando que el índice se mantenga dentro de los límites.
Otro método retorna la pregunta a la que se está apuntando actualmente.

Código: [Seleccionar]
public class Preguntas {

private final String[] PREGUNTAS = {
"1. Torpe o entumecido", "2. Acalorado", "3. Con temblor en las piernas",
"4. Incapaz de relajarse", "5. Con temor a que ocurra lo peor","6. Mareado, o que se le va la cabeza",
"7. Con latidos del corazón fuertes y acelerados","8. Inestable","9. Atemorizado o asustado",
"10. Nervioso","11. Con sensación de bloqueo","12. Con temblores en las manos",
"13. Inquieto, inseguro","14. Con miedo a perder el control","15. Con sensación de ahogo",
"16. Con temor a morir","17. Con miedo","18. Con problemas digestivos",
"19. Con desvanecimientos","20. Con rubor facial","21. Con sudores, frios o calientes"
};

public int actual; //Índice de la pregunta que actualmente se estará mostrando

public Preguntas() {
actual = 0; //Comienza por la primera pregunta
}

public void siguiente() {
//Incrementamos índice
actual++;
//Comprobamos que no hemos rebasado el límite del array de PREGUNTAS
if (actual == PREGUNTAS.length)
actual--;
}

public void anterior() {
//Decrementamos índice
actual--;
//Comprobamos que no estamos en índice negativo
if (actual < 0)
actual = 0;
}

public String getActual() {
return PREGUNTAS[actual];
}
}

Luego he creado una clase llamada PanelInventario que hereda de JPanel.
Va a modelar la interfaz que se ve en pantalla, pero además va a llevar todo el peso de la aplicación.
Así que entre sus atributos va a tener un objeto de la clase Preguntas que se encargará de suministrar las preguntas a un JLabel.
Tendrá también un Stack<Integer> para almacenar las respuestas que el usuario vaya dando en el JTextField.

Al JTextField, le he añadido un KeyListener para que haga un filtrado de lo que se teclea. Está programado para aceptar solo un dígito, y solo uno, entre 0 y 3.
Cualquier otro carácter será ignorado y NO se podrá introducir dos o más caracteres, solo uno.
De esta manera nos aseguramos que el Stack solo recibirá respuestas válidas.

Los botones de Regresar y Avanzar son los que hacen pop() y push(), respectivamente.
Cuando se pulsa Avanzar se hace push() con el valor introducido y se pasa a la siguiente pregunta.
Si se pulsa Regresar, se hace pop() para sacar el último valor introducido y se retrocede a la pregunta anterior.
En ambos casos se comprueba que botones conviene que se activen o desactiven.

Por ejemplo, si ya estamos en la última pregunta, el botón Avanzar se desactiva y se activa el botón Terminar, pero el de Regresar permanece activo.
Si regresamos, el botón Avanzar se reactiva y el de Terminar vuelve a quedar desactivado.

El botón de Terminar lo que hace es "popear" todos los valores del Stack y sumarlos para calcular un promedio que se mostrará en pantalla.
Tras esto, el inventario queda reseteado para poder repetir de nuevo el cuestionario.

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

private final String[] RESPUESTAS = {"[0]En Absoluto", "[1]Levemente",
"[2]Moderadamente","[3]Severamente"};

private Preguntas preguntas;
private Stack<Integer> respuestas;

private JLabel jlPregunta;
private JTextField jtRespuesta;
private JButton btRegresar;
private JButton btAvanzar;
private JButton btTerminar;

public PanelInventario() {
iniciarComponentes();

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Inventario de Ansiedad de Beck(BAI)"),
BorderFactory.createEmptyBorder(25, 25, 25, 25)));

JPanel pnPregunta = new JPanel();
pnPregunta.setLayout(new FlowLayout(FlowLayout.LEFT));
pnPregunta.add(jlPregunta);

JPanel pnRespuestas = new JPanel();
pnRespuestas.setLayout(new GridLayout(1, 4, 20, 0));
for (String resp: RESPUESTAS)
pnRespuestas.add(new JLabel(resp));
pnRespuestas.setBorder(BorderFactory.createEmptyBorder(10, 25, 10, 0));

JPanel pnRespuesta = new JPanel();
pnRespuesta.add(new JLabel("Responde [0-3]: "));
pnRespuesta.add(jtRespuesta);

JPanel pnSeleccion = new JPanel();
pnSeleccion.setLayout(new GridLayout(1,2));
JPanel pnReg = new JPanel();
pnReg.add(btRegresar);
JPanel pnAva = new JPanel();
pnAva.add(btAvanzar);
pnSeleccion.add(pnReg);
pnSeleccion.add(pnAva);

JPanel pnTer = new JPanel();
pnTer.add(btTerminar);

add(pnPregunta);
add(new JSeparator());
add(pnRespuestas);
add(new JSeparator());
add(pnRespuesta);
add(pnSeleccion);
add(pnTer);
}

private void iniciarComponentes() {
preguntas = new Preguntas();
respuestas = new Stack<Integer>();
jlPregunta = new JLabel(preguntas.getActual());
jlPregunta.setFont(new Font("Verdana", Font.BOLD, 20));
jtRespuesta = new JTextField(4);
jtRespuesta.addKeyListener(new SoloNumeros());
btRegresar = new JButton("<< Regresar");
btRegresar.addActionListener(new AccionRegresar());
btRegresar.setEnabled(false);
btAvanzar = new JButton("Avanzar >>");
btAvanzar.addActionListener(new AccionAvanzar());
btTerminar = new JButton("Terminar Test");
btTerminar.addActionListener(new AccionTerminar());
btTerminar.setEnabled(false);
}

/*
* Hace que el campo de texto únicamente pueda aceptar
* un único digito entre 0 y 3
*/
private class SoloNumeros implements KeyListener{
@Override
public void keyTyped(KeyEvent e) {
char caracter = e.getKeyChar();
switch (caracter) {
case '0':
case '1':
case '2':
case '3':
//Aceptable, pero solo si el campo esta vacío
if (!jtRespuesta.getText().isEmpty())
e.consume(); //Cosumimos, no queremos más caracteres.
else
jtRespuesta.setText(String.valueOf(caracter)); //Dígito aceptado
default:
e.consume(); //Consumimos, no es un dígito entre 0 y 3
}
}
@Override
public void keyPressed(KeyEvent e) {}
@Override
public void keyReleased(KeyEvent e) {}
}

private class AccionRegresar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Extraemos última respuesta y la colocamos en pantalla
jtRespuesta.setText(respuestas.pop().toString());
//Recuperamos pregunta anterior
preguntas.anterior();
jlPregunta.setText(preguntas.getActual());
//Comprobamos que el boton avanzar queda activado
btAvanzar.setEnabled(true);
//El botón terminar queda obligatoriamente desactivado
btTerminar.setEnabled(false);
//El boton regresar, se desactiva si estamos en la primera
//pregunta, es decir, si el stack esta vacío
btRegresar.setEnabled(!respuestas.isEmpty());
jtRespuesta.requestFocus();
}
}

private class AccionAvanzar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Recogemos respuesta, si es que la hay
if (jtRespuesta.getText().isBlank())
//No hay
JOptionPane.showMessageDialog(null, "Ha de dar una respuesta",
"Responder", JOptionPane.WARNING_MESSAGE);
else {
//Sí hay respuesta, la guardamos en el Stack
respuestas.push(Integer.parseInt(jtRespuesta.getText()));
//Comprobamos si el stack ya está completo
if (respuestas.size() == 20) {
//Completo, se desactiva el botón avanzar y se activa terminar
btAvanzar.setEnabled(false);
btTerminar.setEnabled(true);
btTerminar.requestFocus();
}
else {//No está completo
//Siguiente pregunta
preguntas.siguiente();
jtRespuesta.setText(null);
jlPregunta.setText(preguntas.getActual());
//Nos aseguramos que el botón regresar está activo
btRegresar.setEnabled(true);
jtRespuesta.requestFocus();
}
}

}
}

private class AccionTerminar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Calculamos el promedio
int suma = 0;
//Vamos vaciando el stack y sumando sus valores
while(!respuestas.isEmpty())
suma += respuestas.pop();

float promedio = suma / 21f;

//Mostramos
JOptionPane.showMessageDialog(null, String.format("Promedio: %.2f",promedio),
"Terminar Test", JOptionPane.INFORMATION_MESSAGE);
//Reinicia panel
preguntas.actual = 0;
jlPregunta.setText(preguntas.getActual());
jtRespuesta.setText(null);
btTerminar.setEnabled(false);
btAvanzar.setEnabled(true);
btRegresar.setEnabled(false);
jtRespuesta.requestFocus();
}
}

}

Por último, una clase Main, que no tiene nada de especial.
Tan solo modela el JFrame principal, muestra un objeto de PanelInventario, que es quien hace todo el trabajo importante, y pone la aplicación en marcha.

Código: [Seleccionar]
public class Main extends JFrame{

public Main() {

JPanel pnPrincipal = new JPanel();
pnPrincipal.add(new PanelInventario());
pnPrincipal.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
setContentPane(pnPrincipal);
setTitle("Inventario con Stack");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}

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

No he hecho ninguna clase Respuestas. Podría haberse hecho, y que gestionara ella el Stack de respuestas.
Pero requiere de tan poca funcionalidad (hacer push y pop) que lo he puesto directamente todo en la clase PanelInventario, para ir más rápido.
Habría quedado más elegante, eso sí.


Creo que con los comentarios que tiene el código se entiende. Cualquier duda solo tienes que preguntar.
O si hay algo que debiera ser distinto, coméntalo por aquí.

Un saludo.

351
En este caso se necesitarán tres arreglos: uno de String para los nombres, otro para el sexo que puede ser char (también podría ser String) y un int para las edades.

Habrá que pedir estos datos a 5 usuarios y repartirlos en el arreglo que corresponda.
Según se piden los datos, se pueden computar para ir contando los hombres y mujeres que son menores y mayores de edad.

Una vez se tienen todos los datos, iniciamos un nuevo bucle para mostrar los datos registrados, de forma que cada nombre salga acompañado de su sexo y de edad.
Y luego se muestran los contadores.

Aquí hay algo con lo que tener cuidado.
Cuando en un ejercicio vamos a pedir datos numéricos y también tipo String, es mejor usar nextLine() para hacer TODAS las lecturas.
De lo contrario, tendremos problemas 100% seguro.

nextLine() nos da un String. Cuando necesitemos un dato int, podemos convertirlo haciendo un parseo.

Es decir, en lugar de pedir así la edad:
Código: [Seleccionar]
edades[i] = leer.nextInt();Mejor la vamos a pedir así:
Código: [Seleccionar]
edades[i] = Integer.parseInt(leer.nextLine());
Este podría ser un código para resolver lo que se pide:
Código: [Seleccionar]
    public static void main(String[] args) {
        Scanner leer = new Scanner(System.in);
        //Arreglos para guardar los datos
        String[] nombres = new String[5];
        char[] sexos = new char[5];
        int[] edades = new int[5];
        //Contadores
        int contHombreMayor = 0, contHombreMenor = 0;
        int contMujerMayor = 0, contMujerMenor = 0;
       
        //Petición de datos
        for (int i = 0; i < 5; i++) {
            System.out.println("\nDatos usuario #" + (i+1));
            System.out.print("Nombre: ");
            nombres[i] = leer.nextLine();
            System.out.print("Sexo (H-Hombre / M-Mujer: ");
            sexos[i] = leer.nextLine().toUpperCase().charAt(0);
            System.out.print("Edad: ");
            edades[i] = Integer.parseInt(leer.nextLine());
           
            //Computamos Contadores
            if (sexos[i] == 'H') {
                if (edades[i]>=18)
                    contHombreMayor++;
                else
                    contHombreMenor++;
            }
            else {
                if (edades[i]>=18)
                    contMujerMayor++;
                else
                    contMujerMenor++;
            }
        }
       
        //Datos registrados y computados. Mostramos resultados
        System.out.println("\n\n\tDATOS REGISTRADOS");
        System.out.println("\t----- -----------");
        for (int i = 0; i < 5; i++) {
            System.out.print("- " + nombres[i] + "  --  ");
            System.out.print(sexos[i]=='H'?"Hombre":"Mujer");
            System.out.println(" -- " + edades[i]);
        }
       
        System.out.println("\nHombres mayores de edad: " + contHombreMayor);
        System.out.println("Hombres menores de edad: " + contHombreMenor);
        System.out.println("Mujeres mayores de edad: " + contMujerMayor);
        System.out.println("Mujeres menores de edad: " + contMujerMenor);
    }

Revísalo y asegúrate de que lo entiendes todo.
Si algo se te escapa, solo tienes que preguntarlo.

Cuando lo tengas claro, si quieres, experimenta haciendo la petición de la edad con nextInt()

Código: [Seleccionar]
            System.out.print("Edad: ");
            edades[i] = leer.nextInt();

Verás como tras introducir la primera edad, no podrás introducir el siguiente nombre y directamente saltará a la petición del sexo.

Esto siempre ocurre cuando se piden datos de distinto tipo.
Lo mejor para evitarlo es pedirlo todo con nextLine(), y ya luego convertir al tipo de dato que se pueda necesitar.

Un saludo.

352
Hola.
Lo primero, cuando peguéis código en un mensaje, no intentéis darle ningún tipo de formato.
No va a quedar bien, especialmente cuando en el código se usan arreglos con el índice [ i ] , porque ese índice se escribe exactamente igual que la etiqueta para dar formato al texto en cursiva(itálica) y entonces el motor del foro se hace un lío, no aplica bien el formato y del código desaparece ese índice del arreglo.

Lo ideal es poner el código entre las etiquetas [code  ]...[ /code]. He editado tu mensaje para que quede de esta manera.


Dicho esto. Sobre tu código.
Te falta hacer la sumatoria, de los pares, de los impares y de todos los números.

Sobre separar los números en dos arreglos distintos para pares e impares.
No es necesario hacerlo. Se puede hacer y parece que has resuelto bien la forma de hacerlo al reutilizar las variables de conteo como índices separados para cada uno de los arreglos.
Pero como digo, no es necesario. Todos los conteos y sumatoria de números se puede hacer al mismo tiempo que se van ingresando los datos.

Con este código, se cumple lo que pide el enunciado:
Código: [Seleccionar]
    public static void main(String[] args) {
        Scanner entrada = new Scanner (System.in);
        int arreglo[] = new int[10];
        //Para conteo de pares/impares
        int conteoP=0, conteoI=0;
        //Para suma de pares/impares
        int sumaP=0, sumaI=0;
        //Sumatoria total
        int sumaT=0;
     
        System.out.println("Ingrese 10 números enteros");
        for (int i=0;i<10;i++){
            System.out.print((i+1)+". Digite un numero: ");
            //Guardamos números
            arreglo[i] = entrada.nextInt();
            //Añadimos a la sumaria tota
            sumaT += arreglo[i];
            //Distinguimos entre pares e impares para contar y sumar cada tipo
            if (arreglo[i] % 2==0){
                conteoP++;
                sumaP += arreglo[i];
            }
            else {
                conteoI++;
                sumaI += arreglo[i];
            }
        }
        //Mostramos datos en pantalla
        System.out.print("Los números almacenados en el vector: ");
        for (int i = 0; i < 10; i++)
            System.out.print(arreglo[i] + " ");
           
        System.out.println("\nLa cantidad de números pares ingresados: " + conteoP);
        System.out.println("La cantidad de números impares ingresados: " + conteoI);
       
        System.out.println("Sumatoria de números pares: " + sumaP);
        System.out.println("Sumatoria de números impares: " + sumaI);
        System.out.println("Sumatoria total de números: " + sumaT);
    }

Sin embargo, puedes dejar como añadido extra lo que has hecho de separar pares e impares en sendos arreglos y así mostrar también estas dos listas de números al final.

Un saludo.

353
Hola.
Te falta almacenar los números introducidos en un arreglo.
Luego, no te pide la suma de números positivos y negativos, te pide que los cuentes y que los muestres. Y para mostrarlos, necesitarás el arreglo, ya que habrá que recorrerlo buscando positivos y negativos.

Podría quedar así:
Código: [Seleccionar]
    public static void main(String[] args) {
        Scanner lea = new Scanner(System.in);
        int[] listaNumeros = new int[10];
        int conPos = 0, conNeg = 0, conCeros = 0;
        //Pedimos números y contamos positivos, negativos y ceros
        for (int i = 0; i < 10; i++){
          System.out.print("Ingrese un numero[" + (i+1) + "]= ");
          listaNumeros[i] = lea.nextInt();

         if (listaNumeros[i] == 0)
            conCeros++;
         else if (listaNumeros[i] > 0)
            conPos++;
         else
            conNeg++;
        }
        //Mostramos datos
        System.out.println("\nCantidad de No. Positivos: " + conPos);
        System.out.print("Numeros positivos ingresados: ");
        for (int i = 0; i < 10; i++)
            if (listaNumeros[i] > 0) //Buscamos positivos en la lista y los mostramos
                System.out.print(listaNumeros[i] + " ");
       
        System.out.println("\nCantidad de No. Negativos: " + conNeg);
        System.out.print("Numeros negativos ingresados: ");
        for (int i = 0; i < 10; i++)
            if (listaNumeros[i] < 0) //Buscamos negativos en la lista y los mostramos
                System.out.print(listaNumeros[i] + " ");
       
        System.out.println("\nCantidad de No. Igual a Ceros: " + conCeros);
    }

En pantalla da este resultado:
Citar
Ingrese un numero[1]=
0
Ingrese un numero[2]=
2
Ingrese un numero[3]=
-5
Ingrese un numero[4]=
7
Ingrese un numero[5]=
-2
Ingrese un numero[6]=
9
Ingrese un numero[7]=
-1
Ingrese un numero[8]=
6
Ingrese un numero[9]=
-6
Ingrese un numero[10]=
0

Cantidad de No. Positivos: 4
Numeros positivos ingresados: 2 7 9 6
Cantidad de No. Negativos: 4
Numeros negativos ingresados: -5 -2 -1 -6
Cantidad de No. Igual a Ceros: 2



354
Hola.
Si interpretamos bien el enunciado, las notas a introducir han de ser números naturales con decimales (double o float), no números enteros(int).

Entonces, haciendo este cambio y añadiendo un bucle para mostrar las notas introducidas tal y como pide el enunciado, tendríamos este código:
Código: [Seleccionar]
    public static void main(String[] args) {
       
        double notas[] = new double[5];
        double promedio = 0;
        double acumulador = 0;
        Scanner lea = new Scanner(System.in);
       
        for (int i = 0; i < notas.length; i++) {
            System.out.print("Ingrese la nota No. " + (i+1) + " : ");
            notas[i] = lea.nextDouble();
           
            acumulador = acumulador + notas[i];
        }
       
        //Mostramos notas
        System.out.print("Notas ingresadas: ");
        for (int i = 0; i < notas.length; i++)
            System.out.print(notas[i] + " ");
       
        //Calculamos promedio
        promedio = acumulador / 5;
        System.out.println("\nEl promedio de las notas es: " + promedio);

Pero no está completo, falta encontrar la nota más alta y la más baja.
Es más, incluso habría que asegurarnos de solo aceptar valores entre 1.0 y 5.0.

Para lograr estas cosas, es conveniente usar métodos, o sea, porciones de código que se dediquen a una tarea concreta.

Por ejemplo, podemos hacer un método que se encargue de pedir la nota. Y repita la petición hasta recibir una nota aceptable. Solo entonces, retornará dicha nota y podremos insertarla en el arreglo de notas.

Código: [Seleccionar]
    public static void main(String[] args) {
       
        double notas[] = new double[5];
        double promedio = 0;
        double acumulador = 0;
       
        for (int i = 0; i < notas.length; i++) {
            System.out.print("Ingrese la nota No. " + (i+1) + " : ");
            notas[i] = pedirNota();
           
            acumulador = acumulador + notas[i];
        }
       
        //Mostramos notas
        System.out.print("Notas ingresadas: ");
        for (int i = 0; i < notas.length; i++)
            System.out.print(notas[i] + " ");
       
        //Calculamos promedio
        promedio = acumulador / 5;
        System.out.println("\nEl promedio de las notas es: " + promedio);
   
    }
   
    private static double pedirNota() {
        Scanner leer = new Scanner(System.in);
        double nota;
        do {
            nota = leer.nextDouble();
        } while(nota < 1.0 || nota > 5.0);
        return nota;
    }

Ahora nos faltaría encontrar la nota más alta y la más baja.
Para esto también haremos dos métodos separados, que recibirán el arreglo de notas y buscarán la nota adecuada.
El programa final quedaría así:
Código: [Seleccionar]
    public static void main(String[] args) {
       
        double notas[] = new double[5];
        double promedio = 0;
        double acumulador = 0;
       
        for (int i = 0; i < notas.length; i++) {
            System.out.print("Ingrese la nota No. " + (i+1) + " : ");
            notas[i] = pedirNota();
           
            acumulador = acumulador + notas[i];
        }
       
        //Mostramos notas
        System.out.print("Notas ingresadas: ");
        for (int i = 0; i < notas.length; i++)
            System.out.print(notas[i] + " ");
       
        //Calculamos promedio
        promedio = acumulador / 5;
        System.out.println("\nEl promedio de las notas es: " + promedio);
        //Buscamos nota más alta y más baja
        System.out.println("\nLa nota más alta es: " + buscarNotaAlta(notas));
        System.out.println("La nota más baja es: " + buscarNotaBaja(notas));
    }
   
    private static double pedirNota() {
        Scanner leer = new Scanner(System.in);
        double nota;
        do {
            nota = leer.nextDouble();
        } while(nota < 1.0 || nota > 5.0);
        return nota;
    }
   
    private static double buscarNotaAlta(double[] notas) {
        double alta = notas[0];//Tomamos como referencia la primera nota, para luego ir comparando con las demás
        for (int i = 1; i < notas.length; i++)
            if (notas[i] > alta)
                alta = notas[i];
       
        return alta;
    }
   
    private static double buscarNotaBaja(double[] notas) {
        double baja = notas[0];//Tomamos como referencia la primera nota, para luego ir comparando con las demás
        for (int i = 1; i < notas.length; i++)
            if (notas[i] < baja)
                baja = notas[i];
       
        return baja;
    }

Y al ejecutarlo, en pantalla podremos ver como si se introducen notas fuera de rango se insiste en volver a pedirla de nuevo.
Y veremos que se cumplen el resto de peticiones del enunciado:
Citar
Ingrese la nota No. 1 :
2.5
Ingrese la nota No. 2 :
4.8
Ingrese la nota No. 3 :
3.1
Ingrese la nota No. 4 :
-3
0.2
1.1
Ingrese la nota No. 5 :
9
4.9
Notas ingresadas: 2.5 4.8 3.1 1.1 4.9
El promedio de las notas es: 3.28

La nota más alta es: 4.9
La nota más baja es: 1.1

355
Mmhhh.. para hacer lo que dices...

El problema es que tal y como yo he diseñado la batalla, los Soldados no pueden saber a quién se están enfrentando.
El que ataca genera un valor de daño, y este valor se lo enviamos al que defiende para que evalúe si es suficiente para producirle daño o no.
Código: [Seleccionar]
int ataqueH = heroe.atacar();
bestia.recibirAtaque(ataqueH);
Pero no hay comunicación directa entre ellos, no saben si están atacando a un Orco, a un Goblin, o que...

Pero bueno, podría modificarse para que el método atacar(), exija recibir entre paréntesis al enemigo que se está atacando.
Y ahora, en lugar de retornar el valor de ataque en un int, dicho valor se aplicará directamente al enemigo
Comenzamos indicando esta exigencia en la declaración abstracta de este método, en la clase Soldado.
Marco los cambios en negrita
Citar
//Este método lo han de sobreescribir Heroe y Bestia, porque será distinto para cada uno
   public abstract void atacar(Soldado enemigo);

Al hacer este cambio, ahora Java nos obliga a que, al menos, las clases Heroe y Bestia se adapten a esta exigencia.
Lo que haremos será cambiar el código para que ya no se retorne ningún valor, si no que el daño se aplicará al "enemigo" recibido entre paréntesis.

La clase Heroe queda con estos cambios:

Citar
import java.util.Random;

public class Heroe extends Soldado {

   public Heroe(String nombre, int puntosVida, int nivelResistencia) {
      super(nombre, puntosVida, nivelResistencia);
   }

   @Override
   public void atacar(Soldado enemigo) {
      // El ataque será el mejor lanzamiento entre dos dados de 0 a 100
      Random dado = new Random();
      int tirada1 = dado.nextInt(101);
      int tirada2 = dado.nextInt(101);
      System.out.println("Primer dado: " + tirada1);
      System.out.println("Segundo dado: " + tirada2);
      int maximo =  Math.max(tirada1, tirada2);
      enemigo.recibirAtaque(maximo);

   }

}

Y la clase Bestia queda así:

Citar
import java.util.Random;

public class Bestia extends Soldado{

   public Bestia(String nombre, int puntosVida, int nivelResistencia) {
      super(nombre, puntosVida, nivelResistencia);
   }

   @Override
   public void atacar(Soldado enemigo) {
      //Único lanzamiento de un dado entre 0 y 90
      Random dado = new Random();
      int tirada = dado.nextInt(91);
      System.out.println("Resultado del dado es: " + tirada);
      enemigo.recibirAtaque(tirada);
   }

}

Y por último modificamos ligeramente el método de la clase Batalla.
Ahora ya no capturamos el daño generado para pasárselo al enemigo a ver si le hemos hecho pupa, todo esto ya ocurre dentro del método atacar() de cada Soldado.
Es decir, las líneas que indiqué al principio:
Código: [Seleccionar]
int ataqueH = heroe.atacar();
bestia.recibirAtaque(ataqueH);
Ahora se reducen a esto:
Código: [Seleccionar]
heroe.atacar(bestia);
Así que la clase Batalla queda así:

Citar
public class Batalla {
   
   private static Scanner sc = new Scanner(System.in);
   
   public static void batallar(Ejercito heroes, Ejercito bestias) {
      
      //Mientras ningun ejército haya sido derrotado....
      while(!heroes.esDerrotado() && !bestias.esDerrotado()) {

         //Calculamos el total de turnos, según el ejército más grande
         int turnosTotal;
         if (heroes.soldados.size() >= bestias.soldados.size())
            turnosTotal = heroes.soldados.size();
         else
            turnosTotal = bestias.soldados.size();
         
         //Comienza una ronda de turnos
         for (int turno = 0; turno < turnosTotal; turno++) {
            //Seleccionamos combatientes
            Heroe heroe = (Heroe) heroes.getSoldado(turno);
            Bestia bestia = (Bestia) bestias.getSoldado(turno);
            //Comprobamos que ninguno sea null
            if (heroe == null && bestia == null)
               //¿Ambos son null?Entonces esta ronda de turnos ha terminado
               break;
            else if (heroe == null)
               //No hay Heroe, Bestia queda en guardia
               System.out.println(bestia.getNombre() + " queda en guardia");
            else if (bestia == null)
               //No hay Bestia, Heroe queda en guardia
               System.out.println(heroe.getNombre() + " queda en guardia");
            else {
               //Ninguno es null, comienza el combate
               System.out.println("Lucha entre " + heroe + " y " + bestia);
               //Turno heroe
               System.out.println("Turno de " + heroe.getNombre());
               heroe.atacar(bestia);
               System.out.println("Datos Actualizados de " + bestia);
               if (bestia.estaMuerto())
                  System.out.println(bestia.getNombre() + " ha muerto.");
               else {
                  //Turno bestia
                  System.out.println("Turno de " + bestia.getNombre());
                  bestia.atacar(heroe);
                  System.out.println("Datos Actualizados de " + heroe);
                  if (heroe.estaMuerto())
                     System.out.println(heroe.getNombre() + " ha muerto.");
               }
            }
            //Turno combate finalizado, ejercitos actualizan sus filas
            heroes.comprobarEjercito();
            bestias.comprobarEjercito();
            pausa();
            //Y se inicia el siguiente turno
         }
      }
      
      //Las rondas de turnos han finalizado porque algún ejército ha sido derrotado. Comprobamos
      if (heroes.esDerrotado())
         System.out.println("Han ganado las Bestias. Soldados restantes: " + bestias.soldados.size());
      else
         System.out.println("Han ganado los Heroes. Soldados restantes: " + heroes.soldados.size());
   }

   private static void pausa() {
      System.out.println("\n\t\tPulse INTRO para continuar...\n");
      sc.nextLine();
   }
   
}


Si ahora, con estos cambios, ejecutamos el programa. Va a funcionar exactamente igual que antes.
Pero ahora sí hemos conseguido que el Soldado que ataca, pueda saber a quién está atacando.
Y esto abre la puerta a conseguir lo que tu pedías, poder añadir reglas específicas de combate según la subclase de cada Soldado.

Por ejemplo: Queremos que un Elfo aumente su ataque al enfrentarse un Orco

Bien, ahora mismo, las clases Elfo, Orco, Humano, etc... son muy simples. No aportan nada.

Código: [Seleccionar]
public class Elfos extends Heroe {

public Elfos(String nombre, int puntosVida, int nivelResistencia) {
super(nombre, puntosVida, nivelResistencia);
}

}

Pero podemos pedirle que sobreescriban el método atacar() para cambiar las reglas de ataque.

Por ejemplo, podemos hacer que un Elfo incremente su ataque un 50% (1.5 veces) si se enfrenta a un Orco.


Citar
public class Elfos extends Heroe {

   public Elfos(String nombre, int puntosVida, int nivelResistencia) {
      super(nombre, puntosVida, nivelResistencia);
   }

   @Override
   public void atacar(Soldado enemigo) {
      if (enemigo instanceof Orcos) {
         //Regla específica cuando un Elfo ataca un Orco
         Random dado = new Random();
         int tirada1 = dado.nextInt(101);
         int tirada2 = dado.nextInt(101);
         System.out.println("Primer dado: " + tirada1);
         System.out.println("Segundo dado: " + tirada2);
         int maximo =  Math.max(tirada1, tirada2);
         System.out.println("*****¡¡El odio élfico hacia los Orcos incrementa el ataque en 1.5x!!*****");
         maximo *= 1.5;
         System.out.println("Valor de ataque resultante: " + maximo);
         enemigo.recibirAtaque(maximo);
         
      }
      else //Si no es Orco, se aplica la regla general de los Heroes
         super.atacar(enemigo);
   }

}

Entonces ahora, al combatir, veremos como Légolas puede hacer ataques letales al enfrentarse con Orcos:
Citar
Lucha entre Legolas (Vida=53 Armadura=30) y Shagrat (Vida=31 Armadura=50)
Turno de Legolas
Primer dado: 17
Segundo dado: 95
*****¡¡El odio élfico hacia los Orcos incrementa el ataque en 1.5x!!*****
Valor de ataque resultante: 142
Datos Actualizados de Shagrat (Vida=0 Armadura=50)
Shagrat ha muerto.

En cambio si se enfrenta a un Goblin, atacará como cualquier otro Heroe
Citar
Lucha entre Legolas (Vida=150 Armadura=30) y Uglúk (Vida=120 Armadura=30)
Turno de Legolas
Primer dado: 21
Segundo dado: 74
Datos Actualizados de Uglúk (Vida=76 Armadura=30)
Turno de Uglúk
Resultado del dado es: 30
Datos Actualizados de Legolas (Vida=150 Armadura=30)

Y de esta manera, podemos personalizar las reglas de ataque según cada Heroe y cada Bestia  ;)

356
Bien, tenemos la clase Ejercito.

Veamos la clase Soldado.
Esta será una superclase, que hará de nexo común entre Heroes y Bestias.
Será abstracta, es decir, no podremos crear un Soldado. Se podrán crear Heroes y Bestias (que son Soldados), pero no un Soldado que no pertenezca a un bando o al otro.

Tendrá los atributos comunes: nombre, vida y resistencia.
Tendrá los métodos comunes: getNombre(), getResistencia(), toString()....

Tendrá el método que indica como gestionar recibir el daño de un ataque, porque esto es igual tanto para Heroes como para Bestias.
Pero NO tendrá el método que gestiona como producir el daño de ataque, ya que esto es distinto para Heroes(mejor de dos dados) y para Bestias(un solo dado)

Si tendrá la "firma abstracta" de dicho método, es decir, no tendrá el código. Pero si "obligará" a que sus clases hijas, Heroes y Bestias, tengan que implementar y sobreescribir este método

Código: [Seleccionar]
public abstract class Soldado {

private String nombre;
private int puntosVida;
private int nivelResistencia;

public Soldado(String nombre, int puntosVida, int nivelResistencia) {
this.nombre = nombre;
this.puntosVida = puntosVida;
this.nivelResistencia = nivelResistencia;
}

public String getNombre() {
return nombre;
}

public boolean estaMuerto() {
return puntosVida <= 0;
}

public int getNivelResistencia() {
return nivelResistencia;
}

public void recibirAtaque(int ataque) {
if (ataque > nivelResistencia)
puntosVida -= ataque - nivelResistencia;

if (puntosVida < 0)
puntosVida = 0; //Evitamos valores negativos
}

@Override
public String toString() {
return String.format("%s (Vida=%d Armadura=%d)", nombre, puntosVida, nivelResistencia);
}

//Este método lo han de sobreescribir Heroe y Bestia, porque será distinto para cada uno
public abstract int atacar();

}

Ahora vamos a ver la clase Heroe.
Esta clase hereda de Soldado.
Un Heroe es un Soldado. ¿Tiene sentido decir eso? Sí lo tiene, así que aprobamos la "relación de herencia"  ;)

Al heredar de Soldado, esta clase estará obligada a sobreescribir el método atacar(), siendo esto lo único que le va a distinguir de la clase Bestia
Código: [Seleccionar]
import java.util.Random;

public class Heroe extends Soldado {

public Heroe(String nombre, int puntosVida, int nivelResistencia) {
super(nombre, puntosVida, nivelResistencia);
}

@Override
public int atacar() {
// El ataque será el mejor lanzamiento entre dos dados de 0 a 100
Random dado = new Random();
int tirada1 = dado.nextInt(101);
int tirada2 = dado.nextInt(101);
System.out.println("Primer dado: " + tirada1);
System.out.println("Segundo dado: " + tirada2);
return Math.max(tirada1, tirada2);
}

}

Ahora la clase Bestia, que viene a ser lo mismo que Heroe, solo varía el código del método que se usa para atacar()
Código: [Seleccionar]
import java.util.Random;

public class Bestia extends Soldado{

public Bestia(String nombre, int puntosVida, int nivelResistencia) {
super(nombre, puntosVida, nivelResistencia);
}

@Override
public int atacar() {
//Único lanzamiento de un dado entre 0 y 90
Random dado = new Random();
int tirada = dado.nextInt(91);
System.out.println("Resultado del dado es: " + tirada);
return tirada;
}

}

Luego vendrían las subclases Humano, Elfo, Orco.... y todas las que queramos imaginar.
No vale la pena que las ponga aquí todas, simplemente lo que han de hacer es heredar de Heroe, o de Bestia, según corresponda:
Código: [Seleccionar]
public class Trasgo extends Bestia {

public Trasgo(String nombre, int puntosVida, int nivelResistencia) {
super(nombre, puntosVida, nivelResistencia);
}

}

Bien, pasamos a lo importante.
La clase Batalla.
Siguiendo un poco el enfoque que tú le diste, este clase tendrá un método estático que recibirá los dos Ejercitos que se van a enfrentar.
Cada Ejercito tiene su propio ArrayList de Soldados Heroes o Soldados Bestia, así que no se necesita declarar ningún otro ArrayList, ni array primitivo, ni nada...

El proceso de batalla sería que, mientras ningún ejercito haya sido derrotado...
... pues hacemos una ronda de turnos.
La duración de esta ronda depende del tamaño del ejército más grande. Los ejércitos cambiarán de tamaño durante la ejecución del programa, así que tras cada ronda de turnos, se vuelve a calcular su duración.

En cada turno, se le pide a cada Ejercito un Soldado que ocupen la misma posición.
Puede ocurrir que algún Ejercito no tenga un Soldado disponible en esa posición, entonces no hay combate y el Soldado que sí está disponible "queda en guardia".

Puede ocurrir que no haya soldado disponible en ninguno de los dos ejércitos, en ese caso, simplemente se pone fin a esta ronda de turnos.

Y si tenemos la suerte de dispone de ambos soldados, pues comienza el combate.
Primero ataca el Heroe. Si la Bestia sobrevive, pues hace su turno de ataque.

Tras esto, cada ejercito actualiza sus filas, es decir, comprueba si hay algún muerto que eliminar de su ArrayList.
Y tras esto, se pasa al siguiente turno con los siguientes soldados

Al terminar los turnos, se inicia una nueva ronda, cuya duración se calcula de nuevo según el ejército con más soldados.

Todo esto terminará cuando alguno de los Ejercitos, haya sido derrotado

Para poder ver paso a paso que ocurre en pantalla, uso un Scanner para pausar la ejecución del programa hasta que se pulse la tecla INTRO.

Código: [Seleccionar]
import java.util.Scanner;

public class Batalla {

private static Scanner sc = new Scanner(System.in);

public static void batallar(Ejercito heroes, Ejercito bestias) {

//Mientras ningun ejército haya sido derrotado....
while(!heroes.esDerrotado() && !bestias.esDerrotado()) {

//Calculamos el total de turnos, según el ejército más grande
int turnosTotal;
if (heroes.soldados.size() >= bestias.soldados.size())
turnosTotal = heroes.soldados.size();
else
turnosTotal = bestias.soldados.size();

//Comienza una ronda de turnos
for (int turno = 0; turno < turnosTotal; turno++) {
//Seleccionamos combatientes
Heroe heroe = (Heroe) heroes.getSoldado(turno);
Bestia bestia = (Bestia) bestias.getSoldado(turno);
//Comprobamos que ninguno sea null
if (heroe == null && bestia == null)
//¿Ambos son null?Entonces esta ronda de turnos ha terminado
break;
else if (heroe == null)
//No hay Heroe, Bestia queda en guardia
System.out.println(bestia.getNombre() + " queda en guardia");
else if (bestia == null)
//No hay Bestia, Heroe queda en guardia
System.out.println(heroe.getNombre() + " queda en guardia");
else {
//Ninguno es null, comienza el combate
System.out.println("Lucha entre " + heroe + " y " + bestia);
//Turno heroe
System.out.println("Turno de " + heroe.getNombre());
int ataqueH = heroe.atacar();
bestia.recibirAtaque(ataqueH);
System.out.println("Datos Actualizados de " + bestia);
if (bestia.estaMuerto())
System.out.println(bestia.getNombre() + " ha muerto.");
else {
//Turno bestia
System.out.println("Turno de " + bestia.getNombre());
int ataqueB = bestia.atacar();
heroe.recibirAtaque(ataqueB);
System.out.println("Datos Actualizados de " + heroe);
if (heroe.estaMuerto())
System.out.println(heroe.getNombre() + " ha muerto.");
}
}
//Turno combate finalizado, ejercitos actualizan sus filas
heroes.comprobarEjercito();
bestias.comprobarEjercito();
pausa();
//Y se inicia el siguiente turno
}
}

//Las rondas de turnos han finalizado porque algún ejército ha sido derrotado. Comprobamos
if (heroes.esDerrotado())
System.out.println("Han ganado las Bestias. Soldados restantes: " + bestias.soldados.size());
else
System.out.println("Han ganado los Heroes. Soldados restantes: " + heroes.soldados.size());
}

private static void pausa() {
System.out.println("\n\t\tPulse INTRO para continuar...\n");
sc.nextLine();
}

}


Y listo.
Ahora solo queda hacer una clase Main, declarar dos Ejercitos, reclutar algunos Soldados.., y hacer que se maten entre ellos.. ::)
Código: [Seleccionar]
public class Main {

    public static void main (String args[]){
   
        Ejercito heroes = new Ejercito();
        Ejercito bestias = new Ejercito();

        heroes.reclutarSoldado(new Elfos("Legolas", 150, 30));
        heroes.reclutarSoldado(new Humano("Aragorn", 150, 50));
        heroes.reclutarSoldado(new Humano("Boromir",100, 60));
        heroes.reclutarSoldado(new Humano("Gandalf",300, 10));
        heroes.reclutarSoldado(new Hobbits("Frodo", 20, 10));

        bestias.reclutarSoldado(new Orcos("Lurtz", 200, 60));
        bestias.reclutarSoldado(new Orcos("Shagrat", 220, 50));
        bestias.reclutarSoldado(new Trasgo("Uglúk", 120, 30));
        bestias.reclutarSoldado(new Trasgo("Mauhúr", 100, 30));

        Batalla.batallar(heroes, bestias);

    }
}

Si algo no ha quedado claro, por favor, no dudes en preguntar, y repreguntar.

Un saludo.

357
Hola.
Veo varias inconsistencias:

Aquí al método vida(), le pasa un List<Heroes>, pero si te fijas no estás haciendo nada con él.
Citar
    public boolean vida(List<Heroes> heroes){
        boolean vidas = getPuntosVida()<=0;
        if(!vidas);
        System.out.println(getNombre()+" ha sido eliminado");
        return vidas;
    }

Si lo quitas, verás que todo funciona exactamente igual, por tanto es innecesario.
Código: [Seleccionar]
    public boolean vida(){
        boolean vidas = getPuntosVida()<=0;
        if(vidas);
        System.out.println(getNombre()+" ha sido eliminado");
        return vidas;
    }

En la clase Batalla ocurre algo parecido.
Declaras como atributos dos Ejercitos
Citar
public class Batalla {

    private static Heroes[] ejHero;
    private static Bestias[] ejeBestia;


    public Batalla() {
        ejHero = new Heroes[5];
        ejeBestia = new Bestias[4];
    }

Pero luego no se usan para nada, porque el único método que tiene esta clase, trabaja con unos List<> que recibe por argumentos. No hace nada con estos atributos declarados en la clase:
Citar
    public static void batalla(List<Heroes> heroes, List<Bestias> bestias) {

        Heroes[] he = new Heroes[heroes.size()];
        he = heroes.toArray(he);

        Bestias[] be = new Bestias[bestias.size()];
        be = bestias.toArray(be);

        do {

            System.out.println(he[0].toString() + be[0].toString());
            System.out.println(he[0].atacar(be[0]));
            System.out.println(be[0].atacarBestias(he[0]));


            System.out.println(he[1].toString() + be[1].toString());
            System.out.println(he[1].atacar(be[1]));
            System.out.println(be[1].atacarBestias(he[1]));

            System.out.println(he[2].toString() + be[2].toString());
            System.out.println(he[2].atacar(be[2]));
            System.out.println(be[2].atacarBestias(he[2]));

            System.out.println(he[3].toString() + be[3].toString());
            System.out.println(he[3].atacar(be[3]));
            System.out.println(be[3].atacarBestias(he[3]));

            System.out.println(he[4].toString() + " se queda en guardia");


        } while (!he[0].vida() || !be[0].vida());

    }
Luego, en ese método, la condición del while no me queda clara:
Código: [Seleccionar]
while (!he[0].vida() || !be[0].vida())
Citar
Hacer Mientras el primer Heroe no tenga vida o la primera Bestia no tenga vida

¿No sería mientras tengan vida?
¿Y por qué solo primer Heroe o primera Bestia?(los que ocupan posición [0 ])
Supongo que esto lo haces por este punto del enuciado:
Citar
En el momento en que un personaje llegue a un nivel de vida igual o inferior a cero se producirá su muerte por lo que se eliminará de su posición y se desplazarán todos sus compañeros en posiciones posteriores para cubrir la baja
En teoría, mientras van muriendo combatientes, se van desplazando de forma que la posición [0 ] siempre está ocupada, hasta que ya no quede nadie.
Pero en tu código este desplazamiento no está contemplado, así que esa condición para el bucle no se cumplirá correctamente.
Además, tu código está pensado para ejércitos de un tamaño fijo.
La "batalla" ha de adaptarse para poder recibir desde el principio ejércitos de diferentes tamaños y tener en cuenta que los ejércitos verán alterado este tamaño durante el combate.

Creo que hay que volver al principio y reformular todo el concepto.
De hecho, lo primero que he visto y me ha chirriado ha sido esto:
Código: [Seleccionar]
public class Heroes extends Ejercito¿Heroes y Bestias han de ser hijas(herederas) de Ejercito?
¿Eso tiene sentido?

En POO es muy habitual cometer el error de usar herencia cuando no corresponde. Y en realidad es fácil evitar este error. Basta con hacerse la pregunta adecuada.

Cuando decimos que una clase hereda de otra, estamos diciendo que esa clase "es una"... lo que sea la otra clase.

Ejemplos.
Si yo digo:
Código: [Seleccionar]
public class Alumno extends PersonaLo que estoy diciendo, es que un Alumno es una Persona
¿Tiene sentido esa afirmación? Sí la tiene, por tanto la herencia es correcta.

Si yo digo:
Código: [Seleccionar]
public class Perro extends AnimalLo que estoy diciendo, es que un Perro es un Animal
¿Tiene sentido esa afirmación? Totalmente, así que la herencia está justificada.

Si yo digo:
Código: [Seleccionar]
public class Heroes extends EjercitoLo que estoy diciendo es que un Heroe (o Bestia), es un Ejército
¿Tiene sentido esa afirmación?
Pues no, un Héroe no es un Ejército.
Un Ejército está compuesto de Héroes, eso sí es cierto. Pero un Héroe, no es un Ejército.

Por lo tanto, aquí una "relación de herencia" no es aplicable.
Lo que se puede aplicar es una "relación de composición".
Un Ejército se compone de uno o varios Héroes o Bestias.
Eso suena mucho mejor, ¿verdad?
¿Y cómo se hace una "relación de composición"?

Pues en este caso hay que reformular la clase Ejército para que sea ella quien tenga como atributo una colección de Héroes o Bestias.
Que sea ella quien controle si en sus filas todavía quedan guerreros con vida o no.
Que sea ella quien se encargue de hacer que los guerreros desplacen sus posiciones para ocupar el puesto de sus compañeros caídos (esto es automático si usamos un ArrayList).

Yo lo haría de este modo:
Código: [Seleccionar]
import java.util.ArrayList;

public class Ejercito {

public ArrayList<Soldado> soldados;

public Ejercito() {
soldados = new ArrayList<Soldado>();
}

public void reclutarSoldado(Soldado soldado) {
soldados.add(soldado);
}

public Soldado getSoldado(int pos) {
try {
return soldados.get(pos);
}
catch(Exception e) {
return null; //No hay soldado en esa posición
}
}

public void comprobarEjercito() {
int soldadoMuerto = -1; //Posicion de posible soldado muerto
//Comprobamos si hay alguna baja
for (int pos = 0; pos < soldados.size(); pos++)
if (soldados.get(pos).estaMuerto()) //Baja confirmada
soldadoMuerto = pos; //Guardamos posicion
/*
* Para evitar inconsistencias, hay que eliminar al soldado
* muerto DESPUÉS del bucle for.
* Si lo eliminasemos DENTRO del bucle for, mientras aún se está
* recorriendo, se podría producir una excepcion porque el indice
* que usa el bucle FOR podría ser inconsistente con el nuevo
* tamaño del ArrayList tras eliminar al soldado.
*/
if (soldadoMuerto != -1) //Se encontró una baja, hay que eliminar
soldados.remove(soldadoMuerto);
//Al eliminar del ArrayList, automáticamente suben una posición los soldados posteriores
}

public boolean esDerrotado() {
//Si ya no quedan soldado, el ejercito ha sido derrotado
return soldados.size() == 0;
}
}

Un Ejercito tiene un grupo de Soldados en un ArrayList.
Necesitamos una clase común entre Heroes y Bestias, para que Ejercito pueda trabajar tanto con unos como con otros..., porque en realidad trabajará con Soldados.

Así que Ejercito gestionará un ArrayList de Soldados. Métodos
- para reclutar Soldados, es decir, insertar Soldados en el ArrayList
- otro para retornar un Soldado de una posición en concreto, esto se usará en los combates por turnos. Como es posible que nos soliciten una posición donde no queda un soldado vivo, controlamos esta excepción y retornaremos null
- otro método comprobará si hay algún soldado muerto y lo eliminará de la lista
- por último, un método que indica si el ejército ha sido derrotado, es decir, ya no quedan soldados en sus filas.

Continuo en el siguiente mensaje.

358
Hola.
Por lo que indica el error, parece que alguno/s de estos Double.parseDouble() recibe un String vacío, y que por tanto no se puede parsear..

Código: [Seleccionar]
        double radio = Double.parseDouble(txtradio.getText());
        System.out.println("El radio es" + radio);
        double lado = Double.parseDouble(txtlado.getText());
        double ladoCubo = Double.parseDouble(txtladoCubo.getText());
        double base = Double.parseDouble(txtbase.getText());
        double altura = Double.parseDouble(txtaltura.getText());
        double radioEsfera = Double.parseDouble(txtRadioEsfera.getText());
        double arista = Double.parseDouble(txtarista.getText());

No se como es el resto de tu programa ni tu GUI, así que solo puedo hacer suposiciones.
Y una suposición es que quizá el problema sea que tú coges los datos de TODAS las figuras, pero quizá el usuario en la GUI solo ha seleccionado una figura y es a esta a la que ha puesto unos valores.
Si el resto de figuras no reciben valores en sus campos de texto (tienen String vacío) y tú intentas recoger y parsear esos campos vacíos, pues entonces se produce esa excepción que te sale en pantalla.

Quizás no deberías coger los datos de TODAS las figuras, solo los de la figura seleccionada.
Puesto que en ese mismo código luego preguntas cuál es la figura seleccionada, pues s entonces cuando deberías recoger el dato necesario.

Por ejemplo:
Citar
if (rbtCirculo.isSelected()) {
            figuras[contador] = new Circulo(Double.parseDouble(txtradio.getText()));
}
if (rbtCuadrado.isSelected()) {
            figuras[contador] = new Cuadrado(Double.parseDouble(txtlado.getText()));
}
etc....


Incluso, para mayor seguridad, antes de coger el dato puedes comprobar que realmente tiene un valor introducido y solo entonces intentas el parseo y creación de la figura

Citar
if (rbtCirculo.isSelected()) {
            if (txtradio.getText().isBlank())
                        JOptionPane.showMessageDialog(null, "Se necesita valor del radio para crear Circulo");
            else
                        figuras[contador] = new Circulo(Double.parseDouble(txtradio.getText()));
}
if (rbtCuadrado.isSelected()) {
            if (txtlado.getText().isBlank())
                        JOptionPane.showMessageDialog(null, "Se necesita valor del lado para crear Cuadrado");
            else
                        figuras[contador] = new Cuadrado(Double.parseDouble(txtlado.getText()));
}
etc....

359
Bufff... nunca me acostumbraré a las GUI autogeneradas por NetBeans, cientos de líneas de código que solo una máquina entiende... para hacer lo que se podría hacer con unas decenas de líneas legibles y escritas por un ser humano.


A ver, creo que el problema es que usas un objeto Empleado

Citar
public class GUIEmpleado extends javax.swing.JFrame {
    Empleado e1;

Citar
private void btnGuardarActionPerformed(java.awt.event.ActionEvent evt) {                                           
        // TODO add your handling code here:
         
       int numSeguro=Integer.parseInt(txtNumerodeSeguro.getText());
        e1=new Empleado(txtNombre.getText(), txtApellido.getText(),numSeguro);//En esta línea quiero llamar al metdo calcularsueldoSemanal

        txaInformacion.setText(e1.toString());
       
   
    }

La clase Empleado no tiene ningún método calcularSueldoSemanalPorHora()

Es método corresponde a la clase hija EmpleadoPorHora
Así que esa es la clase que tienes que instanciar:

Citar
public class GUIEmpleado extends javax.swing.JFrame {
    EmpleadoPorHora e1;

Citar
private void btnGuardarActionPerformed(java.awt.event.ActionEvent evt) {                                           
        // TODO add your handling code here:
         
       int numSeguro=Integer.parseInt(txtNumerodeSeguro.getText());
        e1=new EmpleadoPorHora(txtNombre.getText(), txtApellido.getText(),numSeguro);//En esta línea quiero llamar al metdo calcularsueldoSemanal

        txaInformacion.setText(e1.toString());
       
   
    }

360
Hola.

Se supone que en la GUI, tendrás o podrás crear un objeto EmpleadoPorHora con los datos que recojas de la interfaz.
Una vez creado, puedes llamar a su método y mostrar su resultado en un JLabel, o un JTextField, o donde quieras...

No se como has diseñado tu GUI, pero suponiendo que tengas unos campos de texto y un botón para solicitar la acción de calcular sueldo, será en el código del ActionListener de este botón donde se crea el empleado, se calcula el sueldo y se muestra.

Dejo un ejemplo muy rápido y sencillo a continuación.
Fíjate que en la clase ActionListener es donde se hace la creación del empleado, calculo de sueldo y publicación en un JLabel de la GUI.


Código: [Seleccionar]
public class EjemploGUI extends JFrame{

private JTextField jtNombre;
private JTextField jtApellido;
private JTextField jtNumSeguro;
private JSpinner jsHoras;
private JLabel jlSueldo;
private JButton btCalcular;

public EjemploGUI() {
iniciarComponentes();

setLayout(new BorderLayout());
add(new PanelCentral(), BorderLayout.CENTER);
add(new PanelSur(), BorderLayout.SOUTH);

setTitle("Ejemplo Empleado");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}

private void iniciarComponentes() {
jtNombre = new JTextField(10);
jtApellido = new JTextField(10);
jtNumSeguro = new JTextField(10);
jsHoras = new JSpinner(new SpinnerNumberModel(10,1,Integer.MAX_VALUE,1));
jsHoras.setPreferredSize(new Dimension(60,20));
jlSueldo = new JLabel();
jlSueldo.setForeground(Color.BLUE);
btCalcular = new JButton("Calcular Sueldo");
btCalcular.addActionListener(new AccionCalcular());
}

private class PanelComponente extends JPanel {
public PanelComponente(JComponent componente, int flotacion) {
setLayout(new FlowLayout(flotacion));
add(componente);
}
}

private class PanelCentral extends JPanel {

public PanelCentral() {
setLayout(new GridLayout(5,2,8,4));
add(new PanelComponente(new JLabel("Nombre:"), FlowLayout.RIGHT));
add(new PanelComponente(jtNombre, FlowLayout.LEFT));
add(new PanelComponente(new JLabel("Apellidos:"), FlowLayout.RIGHT));
add(new PanelComponente(jtApellido, FlowLayout.LEFT));
add(new PanelComponente(new JLabel("Nº Seguro:"), FlowLayout.RIGHT));
add(new PanelComponente(jtNumSeguro, FlowLayout.LEFT));
add(new PanelComponente(new JLabel("Horas:"), FlowLayout.RIGHT));
add(new PanelComponente(jsHoras, FlowLayout.LEFT));
add(new PanelComponente(new JLabel("Sueldo:"), FlowLayout.RIGHT));
add(new PanelComponente(jlSueldo, FlowLayout.LEFT));

setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(20, 25, 10, 25),
BorderFactory.createRaisedSoftBevelBorder()));
}
}

private class PanelSur extends JPanel {

public PanelSur() {
add(btCalcular);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(10, 25, 20, 25),
BorderFactory.createLoweredSoftBevelBorder()));
}
}

private class AccionCalcular implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Capturamos datos para crear empleado, obviando validaciones previas por ser un ejemplo
var empleado = new EmpleadoPorHora(jtNombre.getText(), jtApellido.getText(),
jtNumSeguro.getText(), (int)jsHoras.getValue());
//Calculamos y mostramos sueldo en la GUI
Double sueldo = empleado.calcularSueldoSemanalPorHora();
jlSueldo.setText(sueldo.toString());
}
}

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

En pantalla tenemos una interfaz para meter datos y calcular el sueldo mediante el botón de acción.

Páginas: 1 ... 13 14 15 16 17 [18] 19 20 21 22 23 ... 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".