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 ... 40 41 42 43 44 [45] 46 47 48 49 50
881
Lo que quiero es me lean una línea entera de lo que tengo en el archivo ejemplo en el tengo 12345 - juana-sanchez-ojeda-13-delantero-disponible- femenino|
Le tengo "|" eso para que sepa que ahí terminar la línea completa

Entonces sí. Lo puedes hacer usando .nextLine() para el objeto Scanner y así vas cogiendo líneas completas.

Y si la búsqueda la haces usando el valor "12345", utiliza el método .startsWith() para identificar la linea que comience por ese valor.

Sobre lo de "|"...
No es necesario, y además no sirve. El Scanner considera que una linea termina cuando se encuentra el símbolo de "retorno de carro" \r o el símbolo de nueva línea \n (son símbolos que no podemos ver y se añaden cuando al escribir un texto pulsamos intro para terminar la linea y empezar una nueva).

Así que el Scanner considera que una linea termina al encontrar el \r, o el \n o bién cuando ha llegado al final del fichero.
No hace falta indicarle cuál es el final de línea de ningún modo.

882
Hola.
Nunca he usado la clase Scanner para leer ficheros, siempre he usado la calse BufferedReader.
Sin embargo, la mecánica viene a ser la misma.

Vamos por partes.

1.
Usas un JOptionPane para que el usuario introduzca el dato a buscar. ESto significa que ya no necesitas usar el Scanner para leer el dato a buscar, te lo proporciona directamente el JOptionPane si recoges el String que te está devolviendo.
Así que todo eso lo puedes hacer en una única linea. Te tacho las que no necesitas:
Citar
Scanner lector;
      lector = new Scanner(System.in);
      String datoAbuscar =  JOptionPane.showInputDialog("Dato a buscar:");
      datoAbuscar = lector.nextLine();

2.
SIEMPRE, pero SIEMPRE..... cuando queremos leer/escribir ficheros, estaremos obligados a controlar posibles excepciones (errores) que puedan ocurrir al acceder a estos ficheros.
No es opcional, Java nos obliga. Y además, es lo deseable.

Esto significa que la creacion del objeto Scanner para leer fichero las lectura a realizar, han de ir dentro de un try {}.....
seguido de un catch(){} donde le diremos que ha de hacer en caso de que ocurrar el posible error de no poder acceder al archivo, por ejemplo mostrar una ventana explicando el error.

Te destaco en verde el codigo que va dentro del try{} y en rojo el catch
Citar
try {
          Scanner lector = new Scanner(file);
         while (lector.hasNextLine()) {
            String datoBuscado = lector.nextLine();
            
            if (datoBuscado.startsWith(datoAbuscar)) {
                  JOptionPane.showMessageDialog(null,"Dato buscado\n" + datoBuscado);
                           }
                 while(datoBuscado!=("|"));
                 
               }
      }
catch (FileNotFoundException e) {
         JOptionPane.showMessageDialog(null, "No se ha encontrado el fichero " + file.getAbsolutePath());
         e.printStackTrace();//Muestra por consola la "traza" del error
      }

3.
Centrémonos en el código que hay dentro del try{}
Ahora mismo, con el código que pusiste, prácticamente ya estaríamos funcionando correctamente.
Solo comentar dos cosas:
- La linea:
Código: [Seleccionar]
while(datoBuscado!=("|"));No sirve para nada, excepto para provocar un bucle de duración infinito y bloquear el programa para toda la eternidad.
Elimínala. No se qué es lo que pretendías hacer en ese punto del código, pero sea lo que sea, esa línea no te sirve, ya que solo consigue bloquear el programa, ya que datoBuscado SIEMPRE será distinto de "|", excepto que el usuario haya indicado que quiere buscar ese caracter.

-Por último.
Si usamos los métodos .hasNextLine() y nextLine(), estaríamos leyendo lineas completas del archivo de texto.
Además estamos usando el método .startsWith() que nos dirá si la linea tiene al principio el mismo dato que estamos buscando.

Puede que eso sea lo que queramos. Pero tal vez queramos ser más precisos en las lecturas y en lugar de leer lineas enteras, queramos leer palabra por palabra.

Supon que el archivo txt donde estamos buscando, contiene este texto:
Citar
rojo azul verde amarillo
barcelona madrid granada
perro gato marmota

Con los métodos que estamos usando ahora mismo. Podríamos encontrar los datos "rojo", "barcelona" y "perro". Porque son los datos con los que comienzan las lineas y es lo que encontrará el método .startsWith()

Pero no seríamos capaces de encontrar el resto de datos: "azul", "granada", "marmota", etc... como no están al principio de la linea, el método .startsWith() no sabrá encontrarlos.

Esto podemos solucionarlo, usando el método contains(), en lugar de .startsWith()
Sustituimos lo tachado:
Citar
if (datoBuscado.startsWith(datoAbuscar)) {
                  JOptionPane.showMessageDialog(null,"Dato buscado\n" + datoBuscado);
                           }
Por lo marcado en verde:
Citar
if (datoBuscado.contains(datoAbuscar)) {
                  JOptionPane.showMessageDialog(null,"Dato buscado\n" + datoBuscado);
                           }

Ahora sí, ya sí podríamos encontrar cualquiera de esos datos.  Y ya estamos cumpliendo con lo que pide el ejercicio. Todo resuelto  ;)

 Peeeero..., aún podemos ser más precisos.
Ahora mismo estamos leyendo lineas enteras porque usamos los métodos .hasNextLine() y nextLine()

Usemos este texto:
Citar
rojo azul azul azul
barcelona madrid granada
perro gato marmota

Supongamos que queremos que nuestro programa lanze un aviso cada vez que encuentra el dato que buscamos. Es decir, que si está repetido, nos lance un aviso para cada repetició.
Si buscamos la palabra "azul, ahora mismo nuestro programa se equivocaría, y diría que la palabra "azul" solo está 1 vez.
Porque lo que hace es leer la línea completa, comprueba si contiene la palabra "azul" -->(.contains("azul")), lanza un aviso y pasa a la siguiente linea, ignorando que la palabra "azul" esta repetida más veces en la primera línea.

Para evitar esto, podemos hacer que el Scanner, en lugar de lineas, que lea palabra por palabra con los métodos .hasNext() y next();
Quedaría así:
Citar
try {
          Scanner lector = new Scanner(file);
         while (lector.hasNext()) {
            String datoBuscado = lector.next();
            
            if (datoBuscado.contains(datoAbuscar)) {
                  JOptionPane.showMessageDialog(null,"Encontrado dato\n " + datoBuscado);
                           }
                 while(datoBuscado!=("|"));
                 
               }

Con esto ya debería funcionar, pruébalo y pregunta cualquier duda que puedas tener

883
El problema es que al llamar al método.setNumeroTeles de la clase salaCasa, has de pasarle directamente la variable valorNumeroTeles, sin indicarle que es un int
Esto:
Código: [Seleccionar]
public void setNumeroTeles(int valorNumeroTeles)
{
    salaCasa.setNumeroTeles(int valorNumeroTeles);
}

Ha de hacerse así:
Código: [Seleccionar]
public void setNumeroTeles(int valorNumeroTeles)
{
    salaCasa.setNumeroTeles(valorNumeroTeles);
}

Lo mismo con el otro método, no hace falta indicarle que le pasamos un String.

Los métodos, hay que indicarles el tipo de dato del argumento que va a recibir solo cuando se están declarando y/o definiendo.

Una vez declarados/definidos, ya saben qué tipo de dato van a recibir y al llamarlos en el código para que actuen, basta con indicarle el nombre de la variable u objeto que le pasamos como argumento. No es necesario indicarle también el tipo o clase.

Y si por error le pasamos un dato que no corresponde con el tipo/clase esperado, el compilador ya te avisará.

884
Hola amigos que tal saben soy nuevo en el mundo de la PROGRAMACION >/> y quisiera que puedan chequear este ejercicio que no entiendo muy bien sobre arreglos
GRACIAS MAESTROS...

Crear un programa para almacenar los resultados de las últimas elecciones del
rector de una universidad. Los datos deben almacenarse en una matriz donde
cada fila corresponde a una sede y cada columna corresponda a un candidato.
Se debe mostrar el nombre de las sedes y los nombres de los candidatos y cada
uno de los resultados, también se debe mostrar el candidato ganador.

Hola y bienvenido.

Lo primero, comentar que habría sido preferible que creases un tema nuevo en el foro, para que sea específico para tu consulta y no usar un tema de otra persona que no tiene nada que ver con tu consulta.

Lo segundo, quizás deberías pedir a tu profesor que concretase mejor que es lo que pide el ejercicio, pues la verdad es que el enunciado es muy parco en detalles.
¿Cuántas sedes hay?
¿Cuántos candidatos?

¿Qué tipo de dato ha de albergar la matriz? ¿Enteros numéricos? Pues supongo que lo que hay que almacenar son las puntuaciones que cada sede ha dado cada uno de los candidatos.

Una vez tengamos esas puntuaciones, habrá que sumar los valores numéricos totales de cada columna. Y la columna con mayor puntuación, será el candidato que habrá ganado.

También dice de mostrar el nombre del candidato, pero no dice de donde obtenemos esos nombres.

Supongo que lo ideal es crear también un array con los nombres de los candidatos.

Así, si la columna de la matriz con más puntuación es por ejemplo la columna con el indice número 4, pues el nombre del ganador será el que hay almacenado en la posición 4 del array de nombres.


En realidad aquí la "dificultad" está en ver como hacer para recorrer la matriz sumando los datos de las columnas, guardando cual es la mayor puntuación y a que numero de columna corresponde, para determinar quien es el ganador.

Aquí ya tienes algo con lo que empezar a escribir el código. Empieza por crear un array de nombres y una matriz de puntuaciones.
Las dimensiones no nos las dan, así que decidelas tú.
Lo único a tener en cuenta es que el numero de columnas de la matriz ha de ser el mismo que el número de candidatos.

Si por ejemplo decides que habrán 5 sedes y 10 candidatos

Pues el array de nombres de candidatos ha de tener una longitud de 10.
Y la matriz de puntuaciones ha de tener 5 filas y 10 columnas.

Las puntuaciones puedes ponerlas tu mismo a mano en el código al declarar la matriz.
O bien escribir un algoritmo que genere puntuaciones al azar, entre un rango concreto que tu decidas: entre 0 y 10, entre 0 y 100, etc..

885
Supongo que te refieres a cómo evitar que salgan estos comentarios automatizados cuando creas un nuevo fichero y no tener que borrarlo manualmente cada vez.

Esto has de hacerlo desde las opciones del programa editor que estés utilizando y el propio comentario te indica donde debes dirigirte, prueba en uno de estos dos sitios:

 --> License Headers in Project Properties
 --> Tools > Templates

Desde ahí deberías poder eliminar para que no se autogenere ningún comentario o bien modificarlo para que se genere con el texto que tú quieras.

886
Segundo:

El programa de Lugares.
Hablas de un programa donde hay 105 lugares disponibles, que tendrían dos estados posibles: "Libre" u "Ocupado".
Para pasar de un estado a otro nos servimos de un boton que posee cada uno de los 105 lugares y además contamos con unos contadores para tener en pantalla la cantidad de lugares libres y ocupados.

Eso he creído entender. Y más o menos, simplificandolo un poco, yo lo he representado así:



Para complicar el código lo menos posible, está todo escrito en un único archivo .java que contiente todos los métodos y subclases necesarias.

Ahora lo pongo completo, listo para ser copiado, compilado y ejecutado.
Pero luego vamos a ir comentándolo por partes:

Código: [Seleccionar]
package ocupados;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public final class LugaresOcupados {

private PanelLugares lugares = new PanelLugares();//Panel central con los botones para elegir Lugares
private PanelContador contador = new PanelContador();//Panel superior que informa de la cantidad de Lugares ocupados

public LugaresOcupados()
{
try {
SwingUtilities.invokeAndWait(new Runnable()
{
@Override
public void run()
{
JFrame ventana = new JFrame("Lugares Ocupados");
ventana.setLayout(new BorderLayout());
ventana.add(contador, BorderLayout.NORTH);//Colocamos el Panel del Contador en parte superior de la ventana
ventana.add(lugares, BorderLayout.CENTER);//Colocamos en Panel de Lugares en parte central de la ventana
ventana.pack();
ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ventana.setLocationRelativeTo(null);
ventana.setResizable(false);
ventana.setVisible(true);
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}


public static void main(String[] args) {

new LugaresOcupados();
}

/**
* Esta clase crea un panel que representa un Lugar.
* Cuenta con un boton para marcar el lugar como "ocupado" o "libre"
*/
private final class Lugar extends JPanel{

private JButton boton;
private JLabel etiqueta;
private boolean libre = true;//Para saber si el Lugar esta libre o no
private int numLugar;

public Lugar(int nLugar)
{
numLugar = nLugar;
boton = new JButton("Libre");
boton.addActionListener(new PulsarBoton());
boton.setPreferredSize(new Dimension(85, 26));//Como el texto del boton cambiará, le damos un tamaño suficiente para que quepa
setBorder(BorderFactory.createLoweredBevelBorder());
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
etiqueta = new JLabel("Lugar #" + numLugar);
add(etiqueta);
add(boton);
setBackground(Color.GREEN);
}

/*
* Esta clase es para definir que ocurre cuando se pulsa el boton de un Lugar
*/
private class PulsarBoton implements ActionListener
{
@Override
public void actionPerformed(ActionEvent arg0) {
if (libre)
{
libre = false;
setBackground(Color.BLUE);
etiqueta.setForeground(Color.WHITE);//Cambiamos color texto etiqueta para que sea visible sobre el fondo azul
boton.setText("Ocupado");
}
else
{
libre = true;
setBackground(Color.GREEN);
etiqueta.setForeground(Color.BLACK);//Color texto etiqueta recupera color original
boton.setText("Libre");
}

contador.actualizarContador(lugares.calcularOcupados());//Actualizamos el contador de lugares ocupados

JOptionPane.showMessageDialog(null, "Se ha seleccionado el " + etiqueta.getText() +
"\nSu estado ahora es: " + boton.getText());
}
}
}

/**
* Esta clase es para definir el Panel central que albergará los 105 Lugares disponibles.
*/
private final class PanelLugares extends JPanel{

private Lugar[] lugares = new Lugar[105];//Array para agrupar los 105 objetos de la clase Lugar

public PanelLugares()
{
setLayout(new GridLayout(15, 7, 10, 10));//15 filas, 7 columnas = 105 celdas para colocar "Lugares"
//Los valores 10, 10 establece la separacion en pixeles entre los 105 paneles Lugar

//Creamos los 105 lugares y los vamos añadiendo al array y tambien al panel central
for (int i = 0; i < 105; i++)
{
lugares[i] = new Lugar(i);//Añadimos al array
add(lugares[i]);// Añadimos al Panel
}
}

/*
* Este metodo recorre todo el array preguntando a cada Lugar si esta libre o no.
* Si no lo está, es decir, que está ocupado, lo contará y luego devuelve el total de
* Lugares ocupados.
*/
public int calcularOcupados()
{
int ocupados = 0;
for (int i = 0; i < lugares.length; i++)
{
if (lugares[i].libre == false)
ocupados++;
}

return ocupados;
}

}

/**
* Esta clase crea el Panel superior donde estará el contador de lugares ocupados.
* Este contador se irá actualizando cada vez que se pulse un boton.
*/
private final class PanelContador extends JPanel{

private JLabel contadorLugares;

public PanelContador()
{
JLabel texto = new JLabel("Lugares ocupados: ");
texto.setFont(new Font("Tahoma", Font.PLAIN, 40));//Aumentamos tamaño del texto para mayor visibilidad
contadorLugares = new JLabel("0");
contadorLugares.setFont(new Font("Tahoma", Font.PLAIN, 40));
contadorLugares.setForeground(Color.RED);
add(texto);
add(contadorLugares);
}

/*
* Este metodo recibe el numero de lugares ocupados actualmente y
* con este valor actualiza la etiqueta que usamos como contador.
*/
public void actualizarContador(int valor)
{
contadorLugares.setText(String.valueOf(valor));
}

}
}

Esa ventana (JFrame) esta dividida en dos paneles (JPanel).
El panel superior es el "contador", que son tan solo dos etiquetas en la que una se irá actualizando cada vez que se pulse un boton indicando la cantidad de lugares ocupados.

El panel de abajo, ocupa practicamente toda la ventana y en realidad contiene 105 subpaneles, cada uno con su etiqueta y botón.

Cada uno de ellos es una clase llamada Lugar que hereda de JPanel.
Esta es la clase más importante del programa, ya que es donde ocurre toda "la acción" del programa.

Código: [Seleccionar]
private final class Lugar extends JPanel{

private JButton boton;
private JLabel etiqueta;
private boolean libre = true;//Para saber si el Lugar esta libre o no
private int numLugar;

public Lugar(int nLugar)
{
numLugar = nLugar;
boton = new JButton("Libre");
boton.addActionListener(new PulsarBoton());
boton.setPreferredSize(new Dimension(85, 26));//Como el texto del boton cambiará, le damos un tamaño suficiente para que quepa
setBorder(BorderFactory.createLoweredBevelBorder());
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
etiqueta = new JLabel("Lugar #" + numLugar);
add(etiqueta);
add(boton);
setBackground(Color.GREEN);
}

/*
* Esta clase es para definir que ocurre cuando se pulsa el boton de un Lugar
*/
private class PulsarBoton implements ActionListener
{
@Override
public void actionPerformed(ActionEvent arg0) {
if (libre == true)
{
libre = false;
setBackground(Color.BLUE);
etiqueta.setForeground(Color.WHITE);//Cambiamos color texto etiqueta para que sea visible sobre el fondo azul
boton.setText("Ocupado");
}
else
{
libre = true;
setBackground(Color.GREEN);
etiqueta.setForeground(Color.BLACK);//Color texto etiqueta recupera color original
boton.setText("Libre");
}

contador.actualizarContador(lugares.calcularOcupados());//Actualizamos el contador de lugares ocupados

JOptionPane.showMessageDialog(null, "Se ha seleccionado el " + etiqueta.getText() +
"\nSu estado ahora es: " + boton.getText());
}
}
}

Tiene 4 atributos:
Una etiqueta con el número del Lugar.
Un boton para realizar la accion de "Ocupar" o "Liberar"
Un boolean para que este panel pueda indicarnos si actualmente esta Libre o no.
Un int con su numero correspondiente, que puede ir del 0 al 104 (105 posiciones)

Su contructor recibirá el numero de Lugar que le corresponda y lo guardará en su atributo
numLugar
Despues inicializa el botón con el texto "Libre" ya que de inicio todos los Lugares estarán libres.
Le agrega un ActionListener, declarado un poco más abajo, que contiene el código que se ha de ejecutar cuando se pulse el boton.
Además le establece al boton un tamaño "Preferido". Esto es porque al ocupar un Lugar, cambiaremos el texto del boton de "Libre" a "Ocupado". El boton, al arrancar el programa, su panel adopta un tamaño adecuado para el texto "Libre", pero luego el boton no tendrá sitio en su panel para crecer y que quepa el texto "Ocupado".
Si previamente le establecemos un tamaño adecuado, reservará espacion para poder crecer cuando el texto cambie a "Ocupado"

Al panel le ponemos un Borde, esto no es importante, es puramente estético.

Luego le indicamos el Layout, es decir, como queremos que se repartan los objetos dentro del panel. EL layout que le estamos indicando es que los coloque en vertical, es decir, primero la etiqueta y debajo el boton.

Despues inicializamos la etiqueta, incluyendo en su texto el numero de posición que hemos recibido por el contructor de la clase.
Añadimos los dos elementos al panel y listo.

Luego escribimos el código del ActionListener.
En tu codigo usabas el metodo isSelected() para preguntar en cada acción, a todos los botones si estan seleccionados o no.

Yo no lo he hecho así, aquí directamente al pulsar un boton, le preguntamos a su panel si esta libre, valiéndonos del atributo booleano.
Si está "libre", es que ha de cambiar a "ocupado", por lo cuál cambiará su color, cambiará el texto del botón, hará que el contador (el contador pertenece a otra clase) se actualice y mostrará un mensaje en pantalla.
Si está "ocupado", cambiará a "libre", haciendo los cambios necesarios para ello.


Bien, la siguiente clase que encontramos es PanelLugares, que básicamente lo que hace es albergar en formar de cuadrícula, los 105 paneles correspondientes a la clase Lugar

Código: [Seleccionar]
private final class PanelLugares extends JPanel{

private Lugar[] lugares = new Lugar[105];//Array para agrupar los 105 objetos de la clase Lugar

public PanelLugares()
{
setLayout(new GridLayout(15, 7, 10, 10));//15 filas, 7 columnas = 105 celdas para colocar "Lugares"
//Los valores 10, 10 establece la separacion en pixeles entre los 105 paneles Lugar

//Creamos los 105 lugares y los vamos añadiendo al array y tambien al panel central
for (int i = 0; i < 105; i++)
{
lugares[i] = new Lugar(i);//Añadimos al array
add(lugares[i]);// Añadimos al Panel
}
}

/*
* Este metodo recorre todo el array preguntando a cada Lugar si esta libre o no.
* Si no lo está, es decir, que está ocupado, lo contará y luego devuelve el total de
* Lugares ocupados.
*/
public int calcularOcupados()
{
int ocupados = 0;
for (int i = 0; i < lugares.length; i++)
{
if (lugares[i].libre == false)
ocupados++;
}

return ocupados;
}

}

Aqui hace aparicion el array.
Es el único atributo de esta clase, un array de 105 elementos para los 105 paneles.
Lo útil de tenerlo en un array, como veremos luego, es que para actualizar el contador podemos recorrer el array y contar los paneles que indican que NO están libres (libre == false), es decir, que ESTAN OCUPADOS y una vez contados, actualizar el contador con este dato.
Esto podría haberse hecho sin usar una array, bastaría con incrementar o decrementar una variable int y habría sido más eficiente de hecho. Pero como es un ejercicio e interesa practicar con un array, pues aqui es donde mejor viene utilizarlo.

El constructor lo primero que hace es aplicar un Layout que divide el panel en 105 celdas, repartidas en 15 filas de 7 columnas. Con esta distribución conseguimos que todas las filas tengan el mismo numero de paneles.
Otra división valida sería 5 filas de 21 columnas, pero queda demasiado ancho y la ventana se saldría de los límites de la mayoría de pantallas de ordenador.
Este layout además establece una separacion de 10 pixeles, tanto en horizontal como en vertical, entre cada panel. Esto también es una decisión estética.

Despues, el constructor usa un bucle for para recorrer el array y crear un nuevo panel "Lugar", con su correspondiente numero de posición, y lo guarda en el array al mismo tiempo que lo añade a nuestro panel "PanelLugares".

Luego tenemos un método que como dije antes, mediante un bucle revisa que paneles "Lugar" están "ocupados, los cuenta y devuelve el valor.
Este valor lo recibirá el PanelContador, que es la clase que comentamos ahora:

Código: [Seleccionar]
private final class PanelContador extends JPanel{

private JLabel contadorLugares;

public PanelContador()
{
JLabel texto = new JLabel("Lugares ocupados: ");
texto.setFont(new Font("Tahoma", Font.PLAIN, 40));//Aumentamos tamaño del texto para mayor visibilidad
contadorLugares = new JLabel("0");
contadorLugares.setFont(new Font("Tahoma", Font.PLAIN, 40));
contadorLugares.setForeground(Color.RED);
add(texto);
add(contadorLugares);
}

/*
* Este metodo recibe el numero de lugares ocupados actualmente y
* con este valor actualiza la etiqueta que usamos como contador.
*/
public void actualizarContador(int valor)
{
contadorLugares.setText(String.valueOf(valor));
}

}

Consta de dos etiquetas, una con un texto que no cambia nunca. La otra es la que muestra el valor numérico de espacios ocupados e irá cambiando cada vez que se pulse un boton.
En el constructor he aumentado el tamaño de su fuente para que sea más visible.

Luego cuenta con un pequeño método que es el que se encarga de recibir el valor de lugares ocupados (del cual informa la clase PanelLugares) y modifica la etiqueta con el nuevo valor.



Estas tres clases que hemos comentado, son "clases anidadas" en la clase principal LugaresOcupados
Están anidadas, es decir, declaradas dentro de la clase principal y no por separado, para facilitar la comunicación entre ellas.
Lo elegante sería escribirlas por separado, pero entonces tendríamos ciertas dificultades que habría que complicar un poco el código para solventarlos y ahora no merece la pena.

La clase LugaresOcupados:
Código: [Seleccionar]
public final class LugaresOcupados {

private PanelLugares lugares = new PanelLugares();//Panel central con los botones para elegir Lugares
private PanelContador contador = new PanelContador();//Panel superior que informa de la cantidad de Lugares ocupados

public LugaresOcupados()
{
try {
SwingUtilities.invokeAndWait(new Runnable()
{
@Override
public void run()
{
JFrame ventana = new JFrame("Lugares Ocupados");
ventana.setLayout(new BorderLayout());
ventana.add(contador, BorderLayout.NORTH);//Colocamos el Panel del Contador en parte superior de la ventana
ventana.add(lugares, BorderLayout.CENTER);//Colocamos en Panel de Lugares en parte central de la ventana
ventana.pack();
ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ventana.setLocationRelativeTo(null);
ventana.setResizable(false);
ventana.setVisible(true);
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}


public static void main(String[] args) {

new LugaresOcupados();
}

Es muy sencilla. Tiene dos atributos:
- un objeto de la clase PanelLugares (que a su vez contiene los 105 objetos de la clase Lugar)
- un objeto de la clase PanelContador

Su contructor crea la ventana (JFrame) principal y le da un Layout un tanto especial.
Este layout digamos que crea una zona central llamada CENTER rodeada de 4 zonas de menor tamaño en cada punto cardinal NORTH, SOUTH, EAST y WEST.
En este caso uso la zona NORTE para colocar el panelContador ya que necesita poco espacio.
La zona CENTRO que es la de mayor tamaño, colocamos el panel de Lugares.
EL resto de zonas (SUR, ESTE y OESTE) no van a contener nada, así que no aparecerán en la ventana.

Luego le decimos a la ventana que calcule el tamaño necesario para albergar todos los paneles:
Código: [Seleccionar]
ventana.pack();Le decimos que cierre el programa por completo cuando se pulse el boton X de la ventana:
Código: [Seleccionar]
ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);Le decimos que muestre la ventana centrada en la pantalla:
Código: [Seleccionar]
ventana.setLocationRelativeTo(null);Bloqueamos el tamaño de la ventana para que el usuario no lo modifique:
Código: [Seleccionar]
ventana.setResizable(false);Y hacemos la ventana visible:
Código: [Seleccionar]
ventana.setVisible(true);

Luego su metodo main() no hace nada especial, tan solo instanciar la clase principal para que la ventana y todo su contenido se ponga en marcha.

Lamento hacer posts taaaan laaarrgos. Hay casi más explicaciones que código, no te preocupes si te duermes antes de leerlo todo xD... leelo en varios intentos .

Tan solo decir que hay muchas formas de realizar un programa. Esta es mi solución, no tiene por qué ser la mejor. Solo espero que sea lo más entendible posible y te ayude en algo.

Lo importante aquí no es solo aprender a valerse de arrays cuando hay que operar con muchos elementos de un mismo tipo.
Si no también que hay que intentar aplicar la POO al máximo posible y conseguir que cada elemento sea autosuficiente.

En lugar de hacer un programa que al pulsar un boton, se pregunte al resto de los 104 botones si ha sido pulsado o no...
hay que conseguir que al pulsar un boton, este haga lo que tenga que hacer por su propia cuenta sin tener que consultarle al resto de botones.

887
Hola.

A ver, para separar asuntos y no crear un mensaje demasiado grande, lo separaré en dos.

Primero:
Sobre los arrays. (también llamados vectores o arreglos).

Lo que hacen es agrupar un mismo tipo de dato, ya sean tipos primitivos como int, char, double... u objetos de clases complejas: String, Integer, JPanel, ...o cualquier clase creada por nosotros.

Al agruparse, todos los datos comparten el mismo nombre, que es el nombre que hayamos dado al array. Y cada dato está numerado con un indice, que empieza a partir de 0 (en algunos lenguajes empieza por el 1).

Si yo declaro un array de 10 enteros:
Código: [Seleccionar]
int[] arr = new int[10];Obtengo una estructura como esta:


Para referirme  a cada uno de estos elementos de forma individual, utilizo el nombre del array y entre corchetes la posicion que ocupa.
Ejemplo:
Código: [Seleccionar]
arr[0] = 34;
arr[4] = 27;

Supongamos que yo quiero sacar por pantalla los 10 valores del array.
Puedo hacer esto:
Código: [Seleccionar]
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
System.out.println(arr[4]);
System.out.println(arr[5]);
System.out.println(arr[6]);
System.out.println(arr[7]);
System.out.println(arr[8]);
System.out.println(arr[9]);

Pero es mucho trabajo....Y eso que este array es pequeño, imagina que quiero sacar por pantalla un array de 100 elementos, o de 1000, o de 100000....
Menudo desproposito....

Por ello, lo normal es usar un bucle que vaya aumentando una variable int que usaremos como indice para recorrer las posiciones. Y para esto, el más cómodo es sin duda el bucle for:

Código: [Seleccionar]
for (int i = 0; i < 10; i++)
    System.out.println(arr[i]);
Esto haría lo mismo que el codigo anterior, solo que ahorrando trabajo.
Lo que hacemos es incrementar la variable i, para que vaya desde el 0 al 9 (por eso condicion del bucle es "mientras i < 10" ) y la usamos para recorrer cada elemento del array.

Pero, ¿qué ocurre si tenemos que escribir un código donde no sabemos cuanto mide el array que vamos a recorrer? Es muy habitual que tengamos que escribir un método capaz de operar con array de cualquier tamaño.
Para esto, podemos preguntarle directamente al array cuando mide consultando su propiedad .length

Código: [Seleccionar]
for (int i = 0; i < arr.length; i++)
    System.out.println(arr[i]);

Esto funcionará independientemente de si arr tiene una dimensión de 10, de 1000 o la que sea...
El bucle for sabe gracias a la propiedad .length cuánto mide el array y por lo tanto cuándo ha de detenerse.

Un error que debemos evitar es intentar acceder a posiciones del array que no existen ya que esto producirá una excepción y se detendrá el programa.

Siguiendo con el ejemplo de:
Código: [Seleccionar]
int[] arr = new int[10];
Son 10 elementos, numerados del 0 al 9.
Ergo, la posicion tope que puedo consultar es:
Código: [Seleccionar]
System.out.println(arr[9]);
Si hiciera:
Código: [Seleccionar]
System.out.println(arr[10]);
Tendríamos un error y el programa se terminaría de forma abrupta. A no ser que "capturemos" el error  y los gestionemos con las instrucciones try...catch... pero ese es otro tema.

Entonces, cuando te dijeron que podrías haberte ahorrado trabajo usando un array. Se referían a esto.
Si tu usaste 35 botones, seguramente tuviste que preguntar 35 veces, una para cada botón, si estaba seleccionado.
Agrupándolos en un array, solo hubieras tenido que preguntarlo una vez... poniendo la pregunta en un bucle for que recorriese las 35 posiciones del array que albergaba los botones.

Bueno, esto es en teoría...porque no es solo preguntar....
cada boton pertenece a un panel, cada boton tiene una etiqueta, cada panel ha de ver modificado su color, cada uno ha de lanzar un mensaje al ser seleccionado....

Si queremos automatizar todo esto para poder simplificarlo en una o pocas instrucciones dentro de un bucle, hay que aplicar lo mejor posible la filosofia POO (Programacion Orientada a Objetos) de modo que cada objeto/elemento del programa sea lo más autosuficiente posible y sepa comunicarse con el resto de elementos de forma eficiente.

Por eso propuse crear una clase propia para cada panel, para que cada panel se autogestione al ser pulsado su boton.

888
No se donde tienes declarado el JButton rbtn1 o el JLabel lbl1, así que no tengo claro como está enfocado realmente el programa.

Pero bueno, da igual, hablemos del array.
La ventaja del array es poder agrupar muchos elementos en uno solo, de forma que puedes recorrerlos todos ellos de manera fácil usando un bucle.

Si quieres agrupar 105 botones, debes declarar un array como este.

Código: [Seleccionar]
JButton[] botones = new JButton[105];
Despues tienes que inicializar los 105 botones valiendote de un bucle for.
En ese mismo bucle, puedes establecerles un texto diferenciador usando el indice del bucle:
Código: [Seleccionar]
for (int i = 0; i < 105; i++) {
    botones[i] = new JButton("Boton_" + i);
}

Luego, para comprobar si alguno de esos botones está seleccionado de forma similar  a como tú lo estás haciendo, usamos otro bucle similar:
Código: [Seleccionar]
for (int i = 0; i < 105; i++) {
    if (botones[i].isSelected {
        //Cosas que hacer si este boton esta seleccionado
    }
    else {
        //Cosas que hacer si este boton NO esta seleccionado
    }
}

Ahora bien, por la parte de código que has puesto intuyo que tu botón no está solo, parece que forma parte de un JPanel y acompañado de al menos un JLabel.

Quizás entonces lo que necesites es un array de 105 JPanel, cada uno con su boton y su label o lo que sea...
Incluso tal vez lo ideal sería crear tu propia clase que herede de JPanel. En un archivo .java a parte, pero almacenado en el mismo package, se puede hacer algo así:

Código: [Seleccionar]
public class MiPanel extends JPannel {

    public JLabel etiqueta;
    public JButton boton;

    public MiPanel(String txtEtiqueta) {
        etiqueta = new JLabel(txtEtiqueta);
        boton = new JButton();
        add(etiqueta);
        add(boton);
    }
}

Esta clase crea un panel (con el layout por defecto, puedes cambiarlo por otro si quieres) con una etiqueta y un boton. Al crear un objeto a partir de esta clase, podemos pasarle a su constructor un texto para la etiqueta JLabel.
Nota:
Lo "correcto" sería que los atributos de la clase, el boton y la etiqueta, fuesen private y no public. Pero para este ejercicio y facilitar la tarea, se pueden poner como public.

Luego, igual que en el primer ejemplo, en el programa principal podemos declarar un array para albergar objetos de la clase que acabamos de crear.
Y con un bucle los instanciamos, pasandole un String para cada una de las 105 etiquetas

Código: [Seleccionar]
MiPanel[] misPaneles = new MiPanel[105];

for (int i = 0; i < 105; i++) {
    misPaneles[i] = new MiPanel("Lugar: " + i);
}

Luego, otro bucle para recorrer los 105 paneles de nuestra clase,a ver cual boton ha sido seleccionado.

Código: [Seleccionar]
for (int i = 0; i < 105; i++) {
    if (misPaneles[i].boton.isSelected()) {
        misPaneles[i].setBackgroundColor(Color.BLUE);
        String L1 = misPaneles[i].etiqueta.getText();
        lugar = L1;
        vacios --;
        ocupados ++;
        JOptionPane.showMessageDialog (null,"Selecciono el "+ L1 );
    }
    else {
        //codigo para cuando no esta seleccionado...
    }
}

No se si este código realmente funciona, o si bien se adaptaría a lo que realmente quieres conseguir.

Pero bueno, al menos creo que puede servirte para que veas como utilizar un array para ahorrar trabajo cuando tienes que trabajar con muchos elementos de un mismo tipo/clase.

889
Si, si tengo así, es que yo le cambié de nombre porque mi profesor prefiere que le pongamos así.
pero lo cambié en todos los lugares, así que no creo que sea por eso

Pues comprueba en que posición esta declarada esa variable.

Si nos fijamos en este código que pusiste, atento a lo señalado en rojo:

Citar
int max = 0;
int min = 0;
int intContador = 0;

max = min = Edades[0];

 for (int i=1; i<intContador; i++)
       {
         if (Edades>max) {
            max = Edades;
         }
         
         if (Edades<min) {
            min = Edades;
         }
       }
      
       System.out.println(      "\nla edad mínima es: " + min +
                      "\nla edad máxima es: " + max);

Primero declaras la nueva varaible intContador con valor = 0...

Y acto seguido la usas para el bucle for.

Esto significaría que el bucle no hace ninguna comprobación de edades, ya la condición para que el bucle se inicie y se mantenga, es que la variable i sea menor que intContador

Si desde el primer momento la variable i = 1 e intContador = 0...
...1 no es menor que 0... por lo tanto el bucle for no se inicia.

Para que funcione correctamente, la variable intContador ha de ser declarada e inicializada al principio del programa, antes de la petición de datos de personas.
Y asegurarnos de que cada vez que se introduzca una edad y sea validada, intContador se vaya incrementando para que cuente el número de personas introducidas.

890
Esa varaible intContador no te sirve y no la necesitas.

Has de usar la variable que usábamos para contar personas, la misma que te marco aquí en rojo negrita

Citar
//capturar edad

         indBien=false;
         while (indBien==false)
         {
            strError = "";
            indBien=true;
            strEdad = JOptionPane.showInputDialog("\nDigite su edad : ", strEdad).trim();

            try{
               intEdad=Integer.parseInt(strEdad);
            }
            catch (Exception e)
            {
               strError += "debe ingresar valores numéricos\n";
               JOptionPane.showMessageDialog(null, strError);
               indBien=false;
               continue;
            }

            if(intEdad<18||intEdad>125){
               strError += "Edad fuera del rango entre 18 y 125";
            }

            if(strError.length()>0){
               JOptionPane.showMessageDialog(null, strError);
               indBien=false;
            }

                            if (indBien == true){
                                        edades[contPsn] = intEdad;//Guardamos la edad validada en el arreglo
                                        contPsn++;//Aumentamos en 1 el contador de personas, que a su vez nos sirver de indice para el arreglo
                                }

                     
         }     


Citar
//Calcular promedio edad
       int sumaEdad = 0;
       for (int i=0; i<contPsn; i++)
       {
          sumaEdad = sumaEdad + edades[ i ];
       }
       System.out.println("La edad promedio es: " + (sumaEdad / contPsn));

Esa es la variable que hemos usado (bueno, al menos la que yo usé en mi ejemplo) para contar el número de personas de las que hemos introducido datos.
Así que también nos sirve para saber hasta cual posición vamos a recorrer el arreglo de edades, ya que nos indica hasta donde vamos a encontrar edades validadas.

Por lo tanto, eliminamos la variable intContador y usamos contPsn (no sé si le pusiste el mismo nombre o uno diferente...)

Citar
int max = 0;
int min = 0;
int intContador = 0;

max = min = Edades[0];

 for (int i=1; i<contPsn; i++)
       {
         if (Edades[ i ]>max) {
            max = Edades[ i ];
         }
         
         if (Edades[ i ]<min) {
            min = Edades[ i ];
         }
       }
      
       System.out.println(      "\nla edad mínima es: " + min +
                      "\nla edad máxima es: " + max);

891
Lo que te ha pasado tu profesor es cierto que es confuso, son varios ejemplos de operaciones con arrays (arreglos) todo en una misma clase.
No perdería demasiado tiempo intentando comprenderlo.


Sobre esto:
Citar
Pero aún tengo un problema, la salir el resultado, el valor mínimo siempre me sale 0, no importa que números estén, y todo parece estar como debe estar, no sé cuál es el problema?
Creo que se cual es el problema.

Para calcular el máximo y minimo, estás recorriendo el arreglo completo, hasta el final
Citar
for (int i=1; i<Edades.length; i++)

Recuerda que hemos puesto un arreglo de 50 elementos, pero al introducir edades, estamos usando unicamente las primeras posiciones de este arreglo.
Si por ejemplo ejecutas el programa y metes datos de cinco personas, en el arreglo solo te interesan sus primeras 5 posiciones pues son las que van a tener edades.
El resto de posiciones tienen valor 0 y estas posiciones son las que te están haciendo fallar.
Es decir, los valores del arreglo se parecen a esto (no pongo 50 valores porque seria enorme):
edades = {18, 24, 56, 32, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ......, 0, 0, 0, 0, 0, };

Los valores en azul son las edades que habríamos introducido como ejemplo.
Los valores en rojo son posiciones que no hemos utilizado, pero que automaticamente tienen valor 0.

Esto para calcular el maximo no importa.
Pero para el mínimo sí, pues donde comparas para decidir cual es el mínimo:
Código: [Seleccionar]
if (Edades[i]<min) {
min = Edades[i];
}
Como estas recorriendo el arreglo al completo, estamos haciendo comparaciones también con los valores 0.
El codigo piensa que todos los 0 del arreglo (los que he puesto en rojo como ejemplo) son también edades válidas y al usarlos para comparar, pues decide que la edad minima es 0.

Para evitar comparar posiciones del arreglo donde no hemos introducido edades, en este bucle for tendríamos que hacer como en el anterior para calcular el promedio y poner como límite la variable usada para contar personas, y no la longitud total del arreglo.
Esto:
Citar
for (int i=1; i<Edades.length; i++)
Habría que cambiarlo:
Citar
for (int i=1; i<contPsn; i++)

Así en las comparaciones para decidir maximo y minimo, solo pasaremos por las posiciones del arreglo que realmente tienen edades validas. Las posiciones que tienen valores 0, no pasaremos por ellas.

No es un fallo importante, de hecho, es muy habitual ya que lo normal es recorrer los arreglos enteros y ya por acto reflejo en el bucle for ponemos como limite la longitud total del arreglo, pero hay casos como este en los que NO querremos recorrerlo al completo.

Por lo demás está muy bien.
Lo de cómo encontrar el máximo y el mínimo de una serie de numeros, creeme que a muchísima gente le cuesta conseguirlo la primera vez.
No todo el mundo se da cuenta de lo evidente y sencilla que es esta lógica:
Código: [Seleccionar]
max = min = Edades[0];Es decir, establecer el primer número de la serie como máximo y a la vez como mínimo, y a partir de ahí comparar con el resto de números de la serie.

Parece una cosa tonta, pero repito que mucha gente no es capaz de deducirlo, y algunos incluso explicándoselo no terminan de entenderlo.

Sigue así, cualquier duda que tengas aquí estaremos en el foro para ayudarte en lo posible.





892
Sobre el while(true)...
Aquí entra la problemática que mencioné antes, hay profesores y "expertos" que lo utilizan y piensan que es un buen recurso a la hora de programar.
Pues no solo es un mal recurso, si no que es totalmente innecesario.
Para terminar un while(true), hay que utilizar un:
if (<condicion>).... break;

O bien:
if (<condicion>).... System.exit(0);

¿Pues no es más lógico y útil poner esa <condicion> directamente en el while()?
Si necesitamos que ese bucle se ejecute como mínimo una vez independientemente de si se cumple o no esa condición, para ello tenemos el do...while(), que es el utilicé en mi ejemplo.
Con este bucle, este se ejecuta como mínimo una sola vez y luego evalúa la condición para decidir si el bucle se repite o se termina.

Si haces una búsqueda por Internet, verás que la opinión generalizada es que es una mala práctica, incluso en este otro enlace una persona comenta que está cursando un grado y al usarlo en un ejercicio le penalizaron restándole puntos.

Ahora bien, por desgracia, quien "manda" son tus profesores, así que si te dicen que uses el while(true), hazlo.
Pero hazlo solo por contentarles, luego tú intenta recordar que es mala práctica, que en ejercicios simples no importa pero en programas más avanzados usar un while (true) conlleva inevitablemente problemas a posteriori, especialmente de "legibilidad" del programa y de mantenimiento.

Cuando te pasan un código que tú no has escrito para mantenerlo y modificarlo, y ves un while(respuesta == "si"), enseguida ves claramente cuál es la condición necesaria para que el bucle se repita o no.
Pero si te encuentras un while(true), no sabes cuál es la condición real que mantiene el bucle funcionando y tienes que empezar a revisar lineas de código hasta encontrar un break; un System.exit(0)...o similar.
Y como digo, en un programa profesional avanzado, puede ser una locura.


Sobre esto:
Citar
Con los números de la edad que se han introducido, debo hacer un arreglo para al finalizar, sacar un promedio, el número máximo y mínimo.
De nuevo, para contentar al profesor y cumplir lo que pide el anunciado, hay que complicar más el código inútilmente.

Para calcular el promedio, el máximo y el mínimo, no hace falta ningún arreglo, es un paso totalmente innecesario, se puede prescindir de él.
Pero si piden que se use, pues habrá que usarlo... pero esto plantea un problema importante.

En Java, para declarar un arreglo, tienes que saber de antemano que dimensión va a tener.
Es decir, necesitamos saber cuantas edades vamos a almacenar..., pero esto no lo podemos saber..., porque cada vez que se ejecute el programa no sabemos si el usuario va a meter los datos de 3 personas, de 5 personas, de 50, de 10000....

Tu declaración:
Código: [Seleccionar]
int [] arrEnteros = new int [strEdad.length()];Esto no te sirve, le estás diciendo que la dimensión del arreglo ha de ser la longitud del valor de la variable String que contiene la edad.

Es decir, si en ese momento tiene almacenada la edad de una persona de 25 años:
strEdad = "25";
Entonces le estas diciendo al arreglo que su dimensión es de tan solo dos elementos. Porque la longitud del valor de esa variable, es decir, strEdad.length() es de dos, puesto que el string "25" tiene dos caracteres, el '2' y el '5'.

Vamos, que no puedes deducir cuál va a ser el tamaño del arreglo valiéndote de la longitud ( .length() ) de esa varaible, ni de ninguna otra.

De hecho, repito, no puedes deducir cuál ha de ser el tamaño de ninguna manera, porque tu no puedes saber cuantos datos de personas va a introducir el usuario.

En estos casos, se usa unas clases más avanzadas, como puede ser la clase Vector o la clase ArrayList.
Estas clases tienen la ventaja de que no hace falta indicarles ninguna dimensión al declararlos. Son como los arreglos "normales", pero puedes ir añadiendo y quitando datos y ellos irán aumentando o disminuyendo su longitud de forma dinámica.

Como aún no te los han explicado, supongo que no puedes recurrir a ellos.

Si vas a tener que usar un arreglo "normal", no te queda otra que decidir una dimensión lo suficientemente grande para poder hacer el ejercicio.
Total, es solo eso, un ejercicio, y no tiene porque ser perfecto si no tan solo servirte para aprender.
Puedes poner por ejemplo que mida 50, y ya vas sobrado porque para el ejercicio no vas a necesitar meter más de 50 personas.
Código: [Seleccionar]
int[] edades = new int[50];
Para calcular el promedio, vas a necesitar otra variable para contar de cuantas personas se han introducido datos.
Código: [Seleccionar]
int contPsn = 0;//Para contar personasEsta variable, además, te puede servir como "indice" para el arreglo.
Ya que la primera vez que se meta el dato de una persona, la edad habrá que guardarla en la posicion 0 del arreglo y contar esa persona.
La próxima edad se ha de guardar en la posicion 1, y contra otra persona más.
Y así continuamente.....

Pero solo se han de introducir y contar cuando la edad haya quedado validada.
Tú has usado este código para capturar y validar la edad:
Citar
//capturar edad

         indBien=false;
         while (indBien==false)
         {
            strError = "";
            indBien=true;
            strEdad = JOptionPane.showInputDialog("\nDigite su edad : ", strEdad).trim();

            try{
               intEdad=Integer.parseInt(strEdad);
            }
            catch (Exception e)
            {
               strError += "debe ingresar valores numéricos\n";
               JOptionPane.showMessageDialog(null, strError);
               indBien=false;
               continue;
            }

            if(intEdad<18||intEdad>125){
               strError += "Edad fuera del rango entre 18 y 125";
            }

            if(strError.length()>0){
               JOptionPane.showMessageDialog(null, strError);
               indBien=false;
            }
            
                     
            
         }      

Yo lo habría hecho de otra forma, pero para seguir con tu enfoque, podríamos añadir lo siguiente (en color rojo):
Citar
//capturar edad

         indBien=false;
         while (indBien==false)
         {
            strError = "";
            indBien=true;
            strEdad = JOptionPane.showInputDialog("\nDigite su edad : ", strEdad).trim();

            try{
               intEdad=Integer.parseInt(strEdad);
            }
            catch (Exception e)
            {
               strError += "debe ingresar valores numéricos\n";
               JOptionPane.showMessageDialog(null, strError);
               indBien=false;
               continue;
            }

            if(intEdad<18||intEdad>125){
               strError += "Edad fuera del rango entre 18 y 125";
            }

            if(strError.length()>0){
               JOptionPane.showMessageDialog(null, strError);
               indBien=false;
            }

                            if (indBien == true){
                                        edades[contPsn] = intEdad;//Guardamos la edad validada en el arreglo
                                        contPsn++;//Aumentamos en 1 el contador de personas, que a su vez nos sirver de indice para el arreglo
                                }

                     
         }      

De este modo cada vez que se repite el bucle, se guarda la edad validad en la posición adecuada del arreglo y al mismo tiempo contamos las personas introducidas.


Bien, para mostrar y calcular el promedio, tenemos que esperar a que el usuario termine de introducir datos, es decir, hay que hacerlo cuando haya terminado el bucle while().

Ahora mismo, tu bucle while en realidad no termina, sino que estamos cerrando el programa brúscamente con el System.exit(0) (otra mala práctica por cierto)
Esto implica que no tenemos oportunidad de seguir haciendo operaciones al terminar de introducir datos de personas.
Para evitarlo, podemos cambiar el System.exit(0) por la sentencia break;

De este modo, el bucle while() terminará pero el programa seguirá funcionando si le añadimos más codigo tras el //fin while

Así ahora ya tenemos la oportunidad de hacer más operaciones con los datos de la edad, como lo de calcular el promedio.
Para ello, necesitamos otra variable para sumar las edades que hemos almacenado en el arreglo.
Hay que recordar que para nuestro arreglo decidimos darle una dimension de 50, pero en realidad puede que solo tenga 5 edades, ó 7, ó 23..
Así que para sumar las edades, no debemos recorrer el arreglo entero, solo según las personas que hayamos introducido.
Y para esto nos servimos de la variable que hemos usado para contar personas:

Código: [Seleccionar]
//Calcular promedio edad
int sumaEdad = 0;
for (int i=0; i<contPsn; i++)
{
sumaEdad = sumaEdad + edades[i];
}
System.out.println("La edad promedio es: " + (sumaEdad / contPsn));

Con eso ya tienes el promedio de las edades validas introducidas, y funciona para cualquier número de personas introducidas (máximo 50).

Ahora te faltaría lo de calcular la edad máxima y la edad mínima. A ver si consigues averiguar como hacerlo.
Un saludo.

893
Hola,
quizás me equivoco, pero según interpreto yo tu respuesta, diría que estás confundiendo los "objetos" con los "atributos".

Un objeto es un elemento específico, y único, creado según la definición de la clase a que pertenece.

Es decir, para completar el diagrama proponiendo objetos pertenecientes a por ejemplo la clase AvionDeCarga, deberíamos proponer distintos aviones "concretos":
- el AvionDeCarga con matricula: AV-AAA
- el AvionDeCarga con matricula: AV-AAB
- el AvionDeCarga con matricula: AV-AAC
- etc...
Cada uno de estos, es un "objeto" perteneciente a la clase AvionDeCarga.

Luego, al margen del diagrama, efectivamente cada "objeto" posee unos atributos propios.
El primer "objeto" podría tener por ejemplo estos "atributos":
- Matricula: AV-AAA
- PotenciaMotor: 5000 CC
- Capacidad de carga: 100 Tn
- Autonomía: 300Km
El segundo "objeto" podría tener estos otros:
- Matricula: AV-AAB
- PotenciaMotor: 4500 CC
- Capacidad de carga: 80 Tn
- Autonomía: 350Km

etc...

Estas son las diferencias entre "clase", "objetos" y "atributos".

Una "clase" simplemente describe y establece que "atributos" han de poseer los "objetos" que se crearán a partir de ella.
Según este ejemplo que he puesto, un AvionDeCarga ha de tener estos atributos:
- Matricula;
- PotenciaMotor;
- Capacidad de carga;
- Autonomía;

La clase solo indica que atributos ha de tener, no dice cuales serán sus valores.

Es luego, al crear un "objeto", cuando estos "atributos" tomarán valores


Un ejemplo con el que se entiende muy bien, es pensando en Personas.
Para describir e identificar una Persona, podemos usar atributos como:
- Nombre;
- Apellidos;
- Grupo Sanguineo;
- ColorOjos;
- FechaNacimiento;
- PaisNacimiento;
- PaisResidencia;
- EstadoCivil;
- .....

Estos podrían ser los atributos de una Persona, pero los valores específicos de cada atributo se establecen cuando las personas nacen.
Es decir, el nacimiento de una persona es equiparable a la creación de un "objeto" de la clase "Persona".
Cuando nacen, es cuando se establece cuál será su nombre, su color de ojos, su grupo sanguineo, en que pais ha nacido, etc..

Perdón si alargo demasiado la explicación, pero estas cosas son un poco abstractas y pueden costar de entender.
Luego cuando se hacen ejercicios prácticos ya en Java, se entienden mejor.

894
¿Solo se ha de imprimir los datos del cliente actual?
¿O han de ir acumulándose los datos de cada cliente?

Es decir, supongamos que Paco Pelucas mete sus datos. Y se imprimen en pantalla.
Luego Juanito Calvicie mete sus datos.
¿Ahora en pantalla solo han de salir los datos de Juanito Calvicie?
¿O han de salir también los datos de Paco Pelucas seguidos de los datos de Juanito Calvicie?

Si en pantalla han de salir solo los datos del usuario actual, entonces no hay problema. Pides los datos, cada uno lo almacenas en su correspondiente variable String, imprimes en pantalla y el bucle se repite.

Pero si los datos de cada nuevo usuario se han de ir guardando para mostrarlos todos en pantalla, entonces es un poquito (solo un poquito) más complicado. Si fuera este el caso, dilo y ya veríamos como hacerlo.

Vamos a suponer que solo se han de mostrar los datos del cliente actual. Como digo, esto no presenta ninguna dificultad.

Pero antes quiero comentar lo siguiente:
el código que pones como referencia, lo veo un poco lioso de forma innecesaria. Y sobre todo veo algo que me horroriza..
Ese while(true).... eso es algo que se debe evitar, es algo que muy rara vez es realmente necesario recurrir a ello (yo nunca lo he necesitado), y es algo que veo que incluso profesores y expertos lo utilizan habitualmente.
Y repito, me horroriza...aunque funcione, no es una buena práctica a seguir.

Un programa no solo ha de funcionar, ha de seguir una lógica y ha de ser lo más simple posible.

Para conseguir esto, lo mejor es afrontar el ejercicio construyendolo poco a poco, ir por objetivos.

Para este ejercicio necesitamos un bucle que se repita hasta que el usuario, desde una ventana de confirmación, pulse el boton "NO" (NO seguir introduciendo datos)
Pues empecemos por ahí, vamos a crear un bucle que cumpla esto. Luego ya veremos que escribimos dentro del bucle.
Eso lo conseguimos con algo tan sencillo como esto:

Código: [Seleccionar]
package datosPersona;

import javax.swing.JOptionPane;

public class DatosPersona {

public static void main(String[] args) {

//Variables para los datos del usuario
String nombre;
String apellidos;
String edad;
String cedula;

do
{

//Aqui pondremos el codigo para pedir datos

}while(JOptionPane.showConfirmDialog(null, "¿Introducir mas datos?", "Elija opcion", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION);
//El programa termina aqui
}

}

Ese código puedes ejecutarlo tal cual y verás que funciona. No hace nada útil, solo repite un bucle vacío mientras el usuario pulse el botón "SI".
Cuando pulse "NO", termina el bucle y termina el programa.
Se podría hacer un bucle while(), pero para este caso me gusta mas usar su variante do...while()
Como se puede ver, la condición para que se repita es que el usuario pulse el boton "SI", por eso comparamos el showConfirmDialog() con el valor JOptionPane.YES_OPTION
Si el usuario ha pulsado el boton "SI" (o "YES" según el idioma de nuestro sistema operativo) esa comparación dara como resultado TRUE y el bucle se repetirá de nuevo.

Vale, ahora hay que pedir los datos al usuario y sacarlos en pantalla.
No hay que realizar ninguna operación especial, solo pedir y mostrar.
Intenta hacerlo y muestranos como te ha ido.


También hablas de validar los datos. Yo esto lo pensaría después, de momento me centraría solo en pedir y mostrar. Una vez esto funcione, ya miraría que comprobaciones son necesarias para validar datos.

Por ejemplo, NOMBRE y APELLIDO, no hay mucho que validar.
A lo sumo, podemos comprobar que el dato introducido no este vacío, es decir, que haya introducido al menos una letra, o tal vez obligar que como mínimo sean dos letras.

EDAD si tiene más opciones de validación. Lo primero sería transformar el dato introducido (entra como un String) a un valor int. Si esta transformacion falla, es que el usuario ha metido letras en lugar de numeros.
Si la transformación ha funcionado, entonces habría que comprobar la "calidad" del dato, es decir, si estamos pidiendo una edad, pues no puede ser un numero negativo ni tampoco un numero demasiado alto.
Normalmente solo se admiten edades entre 0 y 99. Tampoco tiene importancia ponernos ahora a filosofar sobre cuál debería ser el máximo de edad. Lo importante es poner un máximo simplemente para practicar el ejercicio de programación.

Para la CEDULA..., para hacer una validación realista habría que complicar aún más el programa y no creo que valga la pena.
Yo haría algo parecido a lo pensado para NOMBRE y APELLIDO, exigir una longitud mínima para el dato.

895
¿Qué esperas conseguir con el código que hay en el
bucle do..while()?
No hace nada útil, ni en realidad necesitas que lo haga. Este bucle puedes ahorrartelo.
Y por consiguiente no necesitas tampoco el array de Strings, ni la variable booleana.

Solo necesitas usar el switch para comparar la cadena introducida por el usuario.

Otra cosa. Esta bien intentar que el programa acepte "Enero" y "enero", "Febrero" y "febrero"..... pero no es práctico poner las distintas formas posibles, porque además esas no son las únicas posibles..
¿que pasa si pone "ENERO"?
¿O si es un usuario tocanarices y le da por poner "eNero", "EnErO", etc...?

Es una locura intentar contemplar todas las posibles combinaciones, lo mejor es usar los métodos que nos ofrece la clase String de Java para transformar a minúscula todas las letras de la cadena que ha introducido el usuario, y luego comparar.

Si añades esto al código:
Citar
System.out.println("Ingresa el mes en que naciste:");
a=S.nextLine().toLowerCase();

Conseguirás que lo que teclee el usuario sea recogido en minúsculas, independientemente de como lo haya tecleado el usuario.

Así, en tu switch, solo necesitarás usar las palabras minúsculas para comparar
Citar
switch(a)
{
case "enero":
case "febrero":
case "marzo":
.....
.....
}

Si por algún motivo lo quisieras en mayúsculas, tienes este otro método:
Citar
System.out.println("Ingresa el mes en que naciste:");
a=S.nextLine().toUpperCase();

Y el swich debería ser este:
Citar
switch(a)
{
case "ENERO":
case "FEBRERO":
case "MARZO":
.....
.....
}

896
Muchas gracias me ha servido mucho y he entendido, lo que si queria saber es 
Citar
System.out.println(filasOK?"Las filas son correctas":"Las filas estan mal.")
  lo que hace por ejemplo el (?" ":" ") o sea el signo de interrogacion y los dos puntos ¿cual es su funcion y como funciana?

Muchas gracias, se lo agradezco, buen día.

Hola,
esa línea hace exactamente lo mismo que esto:

Código: [Seleccionar]
if (filasOK == true)
    System.out.println("Las filas son correctas");
else
    System.out.println("Las filas estan mal");

Esa expresión lo que hace es condensar un if... else... dentro de un System.out para que quede en una sola línea.

Lo que hace es analizar la expresión que hay antes del interrogante.
Si la expresión es cierta (true), el System.out mostrará en pantalla la primera cadena de texto que hay antes de los dos puntos :

Si la expresión es falsa, el System.out mostrará en pantalla la segunda cadena de texto que hay después de los dos puntos.

Citar
System.out.println(Expresion_a_Analizar?"Texto a mostrar si es TRUE":"Texto a mostrar si es FALSE");

La primera vez siempre resulta un poco confusa. Pero una vez se ha comprendido como utilizarla, es muy útil para ayudar a que nuestro código no se haga demasiado extenso

897
Hola,
mira te explico un poco el enfoque que yo le dí.

Dijimos que el sudoku será válido si todas las lineas, tanto las horizontales (filas) como las verticales (columnas) cumplen la condicion de que contienen todos los numeros del rango del 1 al 9, sin repetirse.

Así que lo primero que necesitamos es un método que vaya recibiendo "líneas" de una en una y decida si son validas (true) o no (false).
Cada "línea" será en realidad un vector, así que eso es lo que ha de recibir como argumento: un vector.
Y el valor que devolverá será de tipo boolean.

Esta podría ser su firma:
public static boolean lineaEsCorrecta(int[] linea);

Ahora hay que decidir su código.
A mi se me ocurrió una forma de hacerla. Puede que no sea la más inteligente, ni la más elegante.. no le pude dedicar mucho tiempo la verdad, pero funciona perfectamente.
Te la pongo a continuación con algunos comentarios explicativos. Tu decides si quieres verla o primero quieres volver a intentarlo por tu cuenta.

Citar
public static boolean lineaEsCorrecta(int[] linea)
   {
      //Un contador para cada numero, del 1 al 9
      int c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0,
            c6 = 0, c7 = 0, c8 = 0, c9 = 0;
      
      //Recorremos linea, numero a numero y contamos segun lo que encontramos
      for (int num : linea)
      {
         switch (num)
         {
         case 1:
            c1++;
            break;
         case 2:
            c2++;
            break;
         case 3:
            c3++;
            break;
         case 4:
            c4++;
            break;
         case 5:
            c5++;
            break;
         case 6:
            c6++;
            break;
         case 7:
            c7++;
            break;
         case 8:
            c8++;
            break;
         case 9:
            c9++;
            break;
         default:
            return false;//Si encontrasemos un numero fuera del rango 1-9, Sudoku es erroneo
         }
      }
      
      /*
       * Ya se ha recorrido la linea y hemos contado según los numeros encontrados.
       * La linea será CORRECTA si TODOS los contadores tienen valor 1, es decir, se ha encontrado
       * UN UNICO NUMERO para cada posible valor entre 1-9.
       * Si algun contador tuviera valor 0 o mayor que 1, es que la linea es INCORRECTA, porque
       * faltan numeros y/o algunos están repetidos.
       */

      if (c1 == 1 && c2 == 1 && c3 == 1 && c4 == 1 && c5 == 1 && c6 == 1
            && c7 == 1 && c8 == 1 && c9 == 1)
         return true;
      else
         return false;
   }

Bien, ahora ya tenemos un método que nos dice si las líneas son válidas, o no lo son.
Ahora hay que usar este método en main().

Lo ideal sería primero pasarle las FILAS del sudoku y que las compruebe.
Y luego pasarle las COLUMNAS.

Como explicamos al principio, pasarle FILAS es muy fácil, pues solo hay que extraer de la matriz (el Sudoku) los vectores/arreglos de los que está compuesta y para hacer esto nos basta con usar un unico indice para apuntar a cada uno de estos vectores.

Con las COLUMNAS es más dificil porque tenemos que construirlas nosotros previamente para pasarselas al metodo que comprueba las lineas.
Así que de momento, vamos a olvidarnos de las COLUMNAS y vamos a hacer que nuestro programa solo compruebe FILAS.

Yo lo hice así el método main(). De nuevo puedes decidir intentarlo tú antes de ver como lo he hecho yo:

Citar
public static void main(String[] args) {
      /*
       * Usaremos variable booleana para controlar si tras recorrer
       * todas las FILAS, hemos encontrado alguna NO VALIDA.
       * Si todas las FILAS son correctas, esta variable conservará
       * su valor TRUE.
       * Si se encuentra alguna NO VALIDA, su valor pasará a ser FALSE.
       * Luego tras la comprobación de FILAS, mostraremos un mensaje u otro
       * según el valor de esta variable
       */

      boolean filasOK = true;
      
      //Comprobamos las filas
      for (int fila = 0; fila < sudoku.length; fila++)//Con un solo indice obtenemos vectores completos
         if (lineaEsCorrecta(sudoku[fila]) == false)//Se ha encontrado una linea no valida
         {
            filasOK = false;
            System.out.println("Fila no valida: " + fila);//Incluso indicamos cuál fila es incorrecta
         }
      
      System.out.println(filasOK?"Las filas son correctas":"Las filas estan mal.");//Informamos segun el valor de la variable booleana


Pruebalo con el sudoku que pusimos y debería indicar que es correcto.
Luego prueba a alterar algún numero del sudoku para que sea incorrecto y comprueba que este código lo detecta.

Si hasta aquí te funciona, y tienes claro qué es lo que hemos hecho, y por qué....
ahora habría que hacer lo mismo con las COLUMNAS.

Para ello, necesitaríamos crear otro método. Un método que se encargue de construir y devolver"líneas" (un vector) a partir de un número de COLUMNA que le indiquemos.

Esta podría ser su firma (un nombre un poco feo, pero descriptivo):
public static int[] creaLineaParaColumna(int columna);

Entonces, para este sudoku:
Citar
static int[][] sudoku = {
      {5,3,4,6,7,8,9,1,2},
      {6,7,2,1,9,5,3,4,8},
      {1,9,8,3,4,2,5,6,7},
      {8,5,9,7,6,1,4,2,3},
      {4,2,6,8,5,3,7,9,1},
      {7,1,3,9,2,4,8,5,6},
      {9,6,1,5,3,7,2,8,4},
      {2,8,7,4,1,9,6,3,5},
      {3,4,5,2,8,6,1,7,9}
   };

si por ejmplo le indico el valor "0" como numero de columna, me ha de devolver un vector como este:
{5,6,1,8,4,7,9,2,3};

Para así poder pasarselo al método que valida líneas.

Te pongo el código de como lo hice yo. Es más fácil de lo que parece y de nuevo te recomiendo que primero intentes hacerlo por tu cuenta. Y si no lo consigues, pues aquí tienes mi código para ver como solucionarlo.

Citar
static int[] creaLineaParaColumna(int columna)
   {
      int[] linea = new int[9];//Este será el vector que devolveremos
      
      for (int fila = 0; fila < 9; fila++)
         linea[fila] = sudoku[fila][columna];
//Usamos dos indices: fila nos lo da el bucle y cambia en cada iteracion. La columna es la que recibimos como argumento y NO varia con cada iteracion del bucle

//Además el indice fila nos sirve para apuntar a cada una de las 9 posiciones del vector que tenemos que rellenar para crear la linea
      
      return linea;
   }


Con este método, ya podemos construir COLUMNAS y pasárselas al método que se encarga de validar lineas del sudoku.

Esto lo hacemos en el main, del mismo modo que lo hicimos para las FILAS, usando una variable booleana para controlar.
Este sería el main final:

Citar
public static void main(String[] args) {
      /*
       * Usaremos variable booleana para controlar si tras recorrer
       * todas las FILAS, hemos encontrado alguna NO VALIDA.
       * Si todas las FILAS son correctas, esta variable conservará
       * su valor TRUE.
       * Si se encuentra alguna NO VALIDA, su valor pasará a ser FALSE.
       * Luego tras la comprobación de FILAS, mostraremos un mensaje u otro
       * según el valor de esta variable.
                 * Hacemos igual con las COLUMNAS
       */

      boolean filasOK = true;
                boolean columnasOK = true;
      
      //Comprobamos las filas
      for (int fila = 0; fila < sudoku.length; fila++)//Con un solo indice obtenemos vectores completos
         if (lineaEsCorrecta(sudoku[fila]) == false)//Se ha encontrado una linea no valida
         {
            filasOK = false;
            System.out.println("Fila no valida: " + fila);//Incluso indicamos cuál fila es incorrecta
         }
      
      System.out.println(filasOK?"Las filas son correctas":"Las filas estan mal.");//Informamos segun el valor de la variable booleana

        /*
       * Filas Comprobadas.
       * Ahora hay que comprobar Columnas. Esto es un poco más dificil porque la MATRIZ
       * sí tiene los valores de las Filas agrupados en estructuras separadas.
       * Cada Fila es en realidad un VECTOR individual y podemos cogerlos facilmente
       * para pasarselos al método que comprueba si es una línea Sudoku correcta.
       *
       * Pero los valores que corresponden a las Columnas no están agrupados en un
       * VECTOR, sino separados en cada uno de los VECTORES que componen la MATRIZ.
       * Para facilitar la tarea, lo que hacemos es pasarle a un método el número de Columna
       * que queremos comprobar y él se encargará de recorrer las Filas cogiendo el numero
       * correspondiente a la Columna que estamos consultando y construirá un VECTOR que ahora
       * sí podremos tratarlo también como una línea de Sudoku y comprobar su validez.
       */

      
      //Comprobamos columnas
      for (int columna = 0; columna < 9; columna++)
      {
                 //Con el indice de esta bucle le indicamos al método cual columna ha de construir y se la pasamos al metodo que nos dice si la linea es correcta o no
         if (lineaEsCorrecta(creaLineaParaColumna(columna)) == false)
         {
            columnasOK = false;
            System.out.println("Columna no valida: " + columna);
         }
      }
      
      System.out.println(columnasOK?"Las columnas son correctas":"Las columnas estan mal.");
      
      if (filasOK && columnasOK)
         System.out.println("\nEl Sudoku es correcto");
      else
         System.out.println("\nEl Sudoku es incorrecto");
   }


Con todo esto, quedaría resuelto el ejercicio.

Perdón que me repita de nuevo: Importantísimo que lo intentes hacer tú guiándote si quieres por el enfoque que yo le he dado y que solo copies mi código cuándo no te haya sido posible solucionarlo por tu cuenta.

En cualquier caso, pregunta cualquier duda que puedas tener.
Un saludo.

898
Gracias, no habia pensado en usar metodos pero creo que me seria util, lo tendre en cuenta, gracias por el aporte me sirvio mucho, cualquier otra duda la publicare para saber opiniones y certeza gracias a su experiencia.

buen día.

Siempre es mejor (por no decir obligatorio) usar métodos/funciones, incluso para tareas simples.

Este programa tiene un objetivo: determinar si un Sudoku es acertado o no.
Pero para alcanzar ese objetivo, tiene que realizar distintas tareas menores: comprobar si lineas son válidas, extraer columnas de la matriz en forma de vector....

Separar estas tareas en métodos/funciones separadas hace que sea más sencillo afrontar la solución del programa porque puedes ir cumpliendo pequeños objetivos menores en lugar de ir directamente a por "el todo".

Además luego sirve para que el código sea más legible, más fácil de mantener, más fácil de reaprovechar....por ejemplo una función que reciba como argumentos una matriz y un numero de columna, y te devuelva un vector con los valores de la columna indicada, puede ser de utilidad en infinidad de programas que operen con matrices, no solo para este del Sudoku.

Tener este método/función escrito por separado del código principal, facilita el poder copiarlo y usarlo en otros.
Incluso puede pasar a formar parte de una libreria personal tuya, una que aglutine distintos métodos/funciones para operar con matrices, de modo que en el futuro te puede bastar con importar dicha librería desde cualquier programa y llamar a estas funciones sin tener que volverlas a escribir o copiar.

899
Hola,

aquí lo importante es tener claro como está compuesta una matriz.
Una matriz es en realidad una sucesion de vectores (arreglos).
Si suponemos una matriz de 3x3:
Citar
int[][] matriz = new int[3][3];
Esto en realidad es una agrupacion de 3 vectores, en los que cada vector tiene a su vez 3 posiciones para guardar valores. Lo que daría un total de 9 valores posibles para guardar en la matriz.
Esto significa que yo de una matriz, puedo coger uno de esos 9 valores individuales indicando dos posiciones, la primera posicion apunta a uno de los vectores que compone la matriz y la segunda posicion apunta a uno de los valores que compone dicho vector.

Asi que con:
Citar
matriz[0][0];
Estoy apuntando al primer vector y al primer valor de dicho vector.

Con:
Citar
matriz[1][2];
Estoy apuntando al segundo vector y al tercer valor de dicho vector.

Esto seguramente ya lo tenías claro porque es lo que habitualmente se hace en programación al trabajar con matrices: apuntar a valores individuales de la matriz indicando dos posiciones.

Pero algo que quizás no sabías es que al trabajar con matrices, además de coger valores individuales, también podemos coger directamente uno de los vectores.

Asi que con:
Citar
matriz[0];
Estariamos cogiendo el primer vector al completo, con todos sus valores, de modo que podríamos tratarlo y trabajar con él como si fuera un vector (o arreglo) individual, olvidándonos de que en realidad pertenece a una matriz.

Esto no es tan habitual hacerlo al trabajar con matrices, lo de coger un vector completo... pero no es algo tan raro y de hecho para este ejercicio del Sudoku nos va a ser muy útil.

Pero antes, otra aclaración:
Muchas veces representamos la matriz como si fuera una tabla, de modo que tenemos FILAS (valores horizontales de la tabla) y COLUMNAS (valores verticales de la tabla)

Bien, pues cada FILA corresponde a un vector completo de la matriz.
Así que como hemos dicho antes, podemos coger fácilmente una FILA completa de la tabla/matriz y operar con ella ya que en realidad es un vector individual.

Pero en el caso de las COLUMNAS, es más complicado, no podemos coger COLUMNAS tan fácilmente como sí podemos coger las FILAS.
Los valores de las COLUMNAS se componen de valores individuales guardados en cada uno de los vectores (filas) que componen la tabla/matriz.

Así que si queremos coger los valores de una FILA, es muy fácil, le pedimos a la matriz la posicion del vector que corresponde a la FILA y ya está. Ya los tenemos estructurados dentro de un vector.

Pero si queremos coger los valores de una COLUMNA, es más dificil. Habría que recorrer cada uno de los vectores de la matriz, coger únicamente el valor individual correspondiente a la posicion de la COLUMNA que nos interesa y una vez que hemos cogido dicho valor, estructurarlo nosotros mismos en otro vector a parte donde guardaríamos todos estos valores.


¿Y por qué explico todo esto?

Un Sudoku es básicamente una tabla.

Para determinar si un Sudoku esta bien resuelto, se podría hacer cogiendo cada FILA por separado y comprobar que dicha FILA solo tiene numeros del 1 al 9 y no están repetidos.
Luego lo mismo con las COLUMNAS, ir una por una y comprobar que tienen números válidos y no repetidos
Si esto se cumple, el Sudoku es correcto.

Vale, pues esta es la lógica que tenemos que programar.

Y como ya hemos explicado, si representamos el Sudoku en forma de matriz 9x9, coger sus FILAS será muy sencillo porque son vectores individuales y la matriz nos los dará directamente indicandoles su posicion.

Pero luego coger las COLUMNAS, ya es más complicado. La matriz no nos las puede dar directamente, tendremos que recorrer cada uno de los vectores (filas), coger el valor que está en la posición de la columna y copiarlo en otro vector creado por separado para luedo poder trabajar con él.


Cada FILA y cada COLUMNA individual que obtengamos del Sudoku, tendremos que validarlas una por una comprobando que no tiene numeros repetidos.

Así que con esto, ya podemos hacernos una idea de las funciones/métodos que vamos a necesitar en nuestro código.

EL primer método que necesitaremos será uno que reciba " las líneas del Sudoku", es decir, que reciba un vector (ya provenga de una FILA o de una COLUMNA) y determine si es válida o no.

Su declaración podría ser:
Citar
boolean validarLinea(int[] linea);

Y otro método/función, que indicándole el numero de columna, sea capaz de recorrer la matriz y crear un nuevo vector con los valores correspondientes a esa columna.
Se puede declarar como:
Citar
int[] crearLineadesdeColumna(int columna);
Así obtendremos las líneas del Sudoku correspondiente a las COLUMNAS y se las podremos pasar al método validarLinea(); que podrá trabajar con ellas igual de fácil que con las FILAS.

Pues estas son las funciones que tienes que rumiar. Si no lo consigues te ayudaremos, pero de momento intenta hacerlo tú.
Ves por partes e intenta pensar el primer método:
Citar
boolean validarLinea(int[] linea);
Este método ha de ser capaz de recorrer la linea que recibe, comprobar si tiene todos los números del 1 al 9 sin repetirse.
Si esto se cumple ha de devolver TRUE, de lo contrario ha de devolver FALSE.

Si lo consigues, ya puedes hacer la primera parte del ejercicio, que sería validar las FILAS.
Es decir, recorrer la matriz cogiendo los vectores completos y pasándoselos a la funciona validarLinea().
Y comprobar que esta funcion ha devuelto TRUE para cada uno de estos vectores/FILAS.
Si devuelve FALSE en alguno de ellos, es que el Sudoku es incorrecto.

Intentalo y luego ya se pensará como hacer la segunda parte, validar COLUMNAS.


Puedes usar esta matriz que representa un Sudoku correcto:
Citar
int[][] sudoku = {
      {5,3,4,6,7,8,9,1,2},
      {6,7,2,1,9,5,3,4,8},
      {1,9,8,3,4,2,5,6,7},
      {8,5,9,7,6,1,4,2,3},
      {4,2,6,8,5,3,7,9,1},
      {7,1,3,9,2,4,8,5,6},
      {9,6,1,5,3,7,2,8,4},
      {2,8,7,4,1,9,6,3,5},
      {3,4,5,2,8,6,1,7,9}
   };

900
De todo un poco... / Re:Pregunta de java
« en: 16 de Noviembre 2017, 11:57 »
El mensaje de System.out está puesto en un sitio que puede llevar a confusión, ya que SIEMPRE informa de que está repetido, cuando en realidad aún no ha pedido ningún dato siquiera.

Lo ideal sería que ese mensaje estuviera DENTRO del if donde comparamos números de cédulas:

Citar
boolean repetido = true;

 int cedula;

while (repetido){
                System.out.println("Está repetido");
                cedula = sc.nextInt();
                repetido=false;
                for(j=0; j<vector.length; j++){
                    if (vector[j] == cedula){
                        System.out.println("Está repetido");
                        repetido = true;
                    }
                }
                }

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

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

Abraham Lincoln (1808-1865) Presidente estadounidense.

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

Preguntas y respuestas

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