Codigo para crear SUDOKUS

Iniciado por Editame, 28 Julio 2017, 22:27 PM

0 Miembros y 1 Visitante están viendo este tema.

Editame

lo que hago para contar con la matriz en todo el codigo es declararla como static  como si fuera una variable global, eso mismo es lo que estaba intentando con los otros array ponerlos globales a ver si me funcionaba y ya habia corregido lo de los parametros solo pase los necesarios para cada funcion, solo seria optimizar el codigo de la caja como lo recomendaste.

Por otro lado hay algunas cosas que no entiendo de tu codigo pero lo estoy intentando a mi manera tratando de interpretar tu codigo.

A la hora de crear el unificado tengo problemas con el ciclo lo empiezo en 1 hasta <= 9 para que no tome los valores de 0 y me bota error, esto es lo que llevo hasta el momento no esta terminado ni depurado hay sobre la marcha me voy dando cuenta que me falta

package Clases;

import java.util.Random;

public class Tratando {

    static Random rand = new Random();

    static int matriz[][] = new int[9][9];
    static int filas[] = new int[9];
    static int columnas[] = new int[9];
    static int caja[] = new int[9];
    static int unificado[] = new int[9];
    static int ausentes[] = new int [9];
    public static void GeneradorAleatorio() {

        int numero;
        int em = 0;
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                numero = 1 + rand.nextInt(9);
                if (em == 0) {
                    matriz[i][j] = numero;
                    em++;
                }else{
                    if (NumeroPermitido(numero)) {
                        matriz[i][j] = numero;
                    }
                }
            }
        }
       
        for (int i = 0; i < 9; i++) {
            System.out.println("");
            for (int j = 0; j < 9; j++) {
                System.out.print(matriz[i][j] + "\t");
            }
        }
    }

    public static void GetFila(int fila) {

        for (int i = 0; i < 9; i++) {
            filas[i] = matriz[fila][i];
        }
    }

    public static void GetColumna(int columna) {

        for (int i = 0; i < 9; i++) {
            columnas[i] = matriz[i][columna];
        }
    }

    public static void GetCaja(int filas, int columnas) {

        int minfila, maxfila;
        int mincolum, maxcolum;

        if (filas >= 0 && filas < 3) {
            minfila = 0;
            maxfila = 2;
        } else if (filas >= 3 && filas < 6) {
            minfila = 3;
            maxfila = 5;
        } else {
            minfila = 6;
            maxfila = 8;
        }

        if (columnas >= 0 && columnas < 3) {
            mincolum = 0;
            maxcolum = 2;
        } else if (columnas >= 3 && columnas < 6) {
            mincolum = 3;
            maxcolum = 5;
        } else {
            mincolum = 6;
            maxcolum = 8;
        }

        int k = 0;

        for (int i = minfila; i < maxfila; i++) {
            for (int j = mincolum; j < maxcolum; j++) {
                caja[k] = matriz[i][j];
                k++;
            }
        }
    }

    public static void unificarArray() {

        for (int i = 0; i < 9; i++) {
            unificado[filas[i]] = unificado[filas[i]] + 1;
            unificado[columnas[i]] = unificado[columnas[i]] + 1;
            unificado[caja[i]] = unificado[caja[i]] + 1;
        }

        for (int i = 0; i < 9; i++) {
            System.out.print(unificado[i] + "\t");
        }
    }
   
    public static void TomarAusentes (){
       
       
        int numeros;
        for (int i = 0; i < 10; i++) {
            if (unificado[i] == 0) {
                ausentes[i] = i;
               
            }
        }
    }
   
    public static boolean NumeroPermitido (int valor){
        boolean resultado = true;
        for (int i = 0; i < ausentes.length ; i++) {
            if (valor == ausentes[i]) {
                resultado = false;
                break;
            }
        }
        return resultado;
    }

    public static void main(String[] args) {

        GeneradorAleatorio();
       
    }
}
Edilberto Tapias Mercado
Estudiante Ing. Telematica

Serapis

#11
Tengo que irme, no he tenido tiempo de revisar tu código (el último)...
Pero si he alcanzado a ver que en las declaraciones de los arrays tienen todos 9 elementos... fíjate en mi código y verás que hay justo una que debe tener 10 elementos y adivina cual es...
En  mi pseudocódigo verás en casi todas partes
Array x (0 a c_Ocho) //c_ocho e suna contante cuyo valor es precisamente 8
pero en una de ellas verás que  en cambio pone:
Array x (0 a c_Nueve) <-----
Adivina cual de las funciones es ???

Citarstatic int unificado[] = new int[9];
¿NUEVE??????

Revisa y si lo ves necesario contesta, a mediodía que vuelva, reviso tu código... y las dudas que te hayan surgido hasta entonces.

Serapis

#12
Cita de: Editame en  3 Agosto 2017, 07:12 AM
lo que hago para contar con la matriz en todo el codigo es declararla como static  como si fuera una variable global, eso mismo es lo que estaba intentando con los otros array ponerlos globales a ver si me funcionaba
Bien. Cuando unos parámetros, en este caso arrays se usan para unas funciones que se usan masivamente, es preferible crear el array una sola vez y luego solo sobrescribirlos. Obviamente de cara a explicaciones, es preferible que cada función se acompañe de exactamente los parámetros que necesite o es más fácil perderse por no ver o saber de donde salen esas variables...
De hecho, de cara a optimizarlo (primero haz que funcione y funcione bien, siempre es lo primero, luego ya se optimizará), a veces un array puede ser reutilizado en más de una función (uno debe tener claro cuando esto es así, para no interferir en los valores y tenerlos sucios esperando unos valores que fueron cambiados por otra función).

Cita de: Editame en  3 Agosto 2017, 07:12 AM
Por otro lado hay algunas cosas que no entiendo de tu codigo pero lo estoy intentando a mi manera tratando de interpretar tu codigo.
Cuando suceda, lo remarcas y luego que sumes varias (si las hay), preguntas por esas dudas.


Cita de: Editame en  3 Agosto 2017, 07:12 AM
A la hora de crear el unificado tengo problemas con el ciclo lo empiezo en 1 hasta <= 9 para que no tome los valores de 0 y me bota error, esto es lo que llevo hasta el momento no esta terminado ni depurado hay sobre la marcha me voy dando cuenta que me falta


   static int unificado[] = new int[9];
 
   public static void unificarArray() {
       for (int i = 0; i < 9; i++) {
           unificado[filas[i]] = unificado[filas[i]] + 1;
           unificado[columnas[i]] = unificado[columnas[i]] + 1;
           unificado[caja[i]] = unificado[caja[i]] + 1;
       }
       for (int i = 0; i < 9; i++) {
           System.out.print(unificado[i] + "\t");
       }
   }

No es eso lo que veo en tu código es más, no se ajusta a mi descripción, copio y pego la mía y verás que no se ajusta...
Al caso he retirado los comentarios previos y añadido otros que es donde debes fijarte. También cambio las etiquetas de code por cita, para poner énfasis con negrita:

CitarArray Byte = Funcion UnificarCubiculos(Array Byte Fila(), Array Byte Columna(), Array Byte Bloque())
   Array tipo Byte V(0 a c_Nueve)  // esto es, 10 ELEMENTOS. Este array es de 10 elementos

   // contar el número de presencias de cada valor...
   Bucle para k desde 0 a c_Ocho  // OJO: 0 a 8
       Si (Fila(k) > 0) luego   // Si no está vacía la casilla...
           V(Fila(k)) += 1
       fin si
       Si Columna(k) > 0 luego   // Si no está vacía la casilla...
           V(Columna(k)) += 1
       fin si
       Si (Bloque(k) > 0) luego   // Si no está vacía la casilla...
           V(Bloque(k)) += 1
       fin si
   Fin Bucle
 
   V(0) = 0 //Realmente no es necesario, ya que no llevó la cuenta de 'ceros'
   // Tu si llevas la cuenta al omitir, los condicionales d emás arriba, luego esto es aconsejable, no tanto como obligado 8más abajo mé extiendo sobre esto).


  // En tu versión, falta este bucle
   Bucle para k desde 1 a c_Nueve   //OJO: el bucle recorre desde 1 a 9
       Si (V(k) > 0) luego  //esto es imprescindible. Presencia, indica que aparece. Se consigna k, sólo si v(k) es mayor que 0, es decir si aparece.
           V(k) = k            
       Fin si
   Fin Bucle

   Devolver V        
Fin Funcion
En tu código también llevas la cuenta de 0, no importa, es más sencillo eliminar el condicional, pero en ese caso si será útil, al final la línea donde la comento como: " //Realmente no es necesario, ya que no llevó la cuenta de 'ceros'", como tu si has llevado la cuenta, ponlo a 0. Incluso aunque no se utilice ahora, un cambio a futuro, y que hayas olvidado que eso vale 0 podría darte dolores de cabeza intentando buscar el error. Es sólo una línea de código y evita problemas a futuro, es mejor ponerla.

Luego en mi 'versión' hay dos bucles, en uno genero la "tabla de conteo" de cada valor, pero eso es solo la primera parte, falta la segunda parte, donde en el otro la tabla de conteo se convierte en una "tabla de presencia".
En 'tu versión' el segundo bucle no existe, el que hay se remite al "System.out.print" que solo tiene efectos de verificación, pero le falta el 2º bucle que yo le pongo.

Ya he comentado que a efectos de optimización en ese segundo bucle se podría hacer la parte de la siguiente función, pero sería mucho más scuro, haciendo que cadas función haga una sola tarea (eso si, completa), queda perfectamente claro el propósito (único) de cada función...

- Una tabla de conteo: Es una tabla (array, unidimensional, bidimensional etc...) que lleva la cuenta de veces que aparece un determinado valor. Imagina un fichero de imagen, imagina que quieres obtener su histograma, necesitas contar cuantas veces aparece cada nivel de rojo, de verde y de azul en la imagen. Dando una imagen de 8bits por canal (un byte), se necesitará pués 3 arrays para contar los niveles de rojo, verde y azul. el array tendrá256 elementos por 256 son los niveles posibles para el rojo, verde y azul, es decir valores entrte 0 y 255...entonces leyendo la imagen con cada aparición haríamos algo como (para contarlos):
 arrRojo(Imagen.Rojo(n)) = arrRojo(imagen.Rojo(n)) +1
Que como se ve, no es distinto de nuestor caso, salvando el origen de los datos y el tamaño del array.
- Tabla de presencia: es una tabla donde lo único que necesitamos saber es que dicho valor aparece y nos da igual cuántas veces aparece... Esto puede hacerse directamente o a partir de la tabla anterior. De cara a entender, es preferible hacerlo indirectamente desde creando antes la tabla de conteo, así se vé con mucha claridad,  como se crea esta otra...
si arrRojo(nivel) > 0  luego
  arrRojo(nivel) = nivel
Fin si

Antes el array podía tener un valor elevado (más tratándose de una imagen si la imagen fuera casi toda blanca y tuviera pongamos un tamaño de 3500x2500 píxeles de ancho y alto (o al revés) tendríamos 8.750.000 píxeles en total, en total como solo hay 256 canales y lo son para el rojo, verde y azul, ni 8bits ni 16bits, nos valen para contener dicha cuenta, tendríamos que usar un array de 32 bits... Así es la tabla de conteno. En cambio la tabla de presencia basta que tenga como tipo de datos el más alto del valor que haya de contener, en este caso aún tratándose de colores, bastaría un array de bytes, porque los niveles solo van del 0 al 255. Luego es decisión de cada cual si aprovechas el mismo array para ambas tablas o no.

En el caso del sudoku, aunque lo has declarado integer y realmente nos basta con byte reutilizamos el array...

Para ver la diferencia entre ambas tablas, puedes imprimir el resultado de cada una al final de cada bucle. Verás que la tabla de conteo es equivalente a la tabla de presencia, la tabla de presencias, es también una tabla de ausencias, todos aquellos índices cuyo valor es 0, señala que no están ausentes. La tabla de ausencias que creamos luego es 'ordenada', y es básicamente mover al comienzo del array esos valores ausentes. Con el fin justamente de luego al usar una función random, elegir un índice al azar entre 0 el el último que porta un valor ausente. Al estar contiguos, eso es posible, si no habría que ver si el valor al azar entre el 0 y el 9, está ausente... pero si no lo está repetir todo el proceso se eterniza. Del modo en que procedemos se garantiza con una sola vez la elección de azar y una sola vez la
verificación (previa), sacar el siguiente número a consignar.

--------------------
P.d.:

En tu función de ausentes observo dos fallos:
Quito las etiquetas de code, para comentar encima con engrita.
Bueno al quirtar las etiquetas de code, como usas llaves con 'i', el codigo BBcode, lo interpreta como itálica, así que lo cambio, saco los comentarios y en su lugar dejo asteriscos

public static void TomarAusentes (){
       int numeros;  //no se usa...
       for (int i = 0; i < 10; i++) {  // **********01
           if (unificado[i] == 0) {
               ausentes[i] = i;  // **********02
           }
       }
   }


// **********01 Este bucle debe empezar en 1, no en 0. Los valores UTILES para el sudoku van del 1 al 9, el 0 no es un valor elegible, indica 'casilla vacía', 'casilla libre', 'casilla sin valor aún'

// **********02 NO: Este debe llevar su propio contador, no puede ser 'i'. Con cada aparición aumenta, si no, no estarían los valores contiguos...
// Imagina que te dicen aqui tienes una lista de alumnos. Todos los que tengan más de 18 años, los escribes en ESTA OTRA lista... acaso en esa nueva lista, no irían contiguos?. el primero hallado en la posición 0, el siguiente en la 1, el siguiente hallado en la 2, etc... sería absurdo que en esa nueva lista, aparezca un alumno en la posición 43, y en la nueva lista, tu lo consignes también en la posición 43... ¿Capisci, el significado de 'nueva lista' y 'valores contiguos'? . cuando se tenga esa lista de alumnos con más de 18 años quien la trate, la tratará contigua, imagina que entre ellos se va  ahacer un sorteo para ver una peli para mayor de 18 años, si en la lista hay inscritos 61 alumnos, se harían papeletas entre 1 y 61 (0 y 60 si lo consideramos técnicamente). Si la lista el último alumno se hubiera inscrito con su posición original pongamos 1563, sería complicado elegir al azar a un alumno, por número, se podría hacer por nombre, peor las matemáticas están para socorrernos, simplifiquemos cuando es posible. Entre 1 y 61 8ó 0 y 60), todos en una sala solitos, es más aislado que sortearlo entre los 1850 alumnos d ela escuela y luego preguntarle si tiene más de 18 años y si es que no, dejarle con un palmo de narices. Usando nombres, los que  son menores no entran en el sorteo, pero ven 'en directo' el sorteo saltando por encima de sus cabezas 'produciendo algo de envidia'  :laugh: :laugh: :laugh: :laugh:
Mejos con la lista aparte en otra función (una sala, se los llama ) y a puerta cerrada se hace el sorteo solo entre los implicados...

Bueno, cuando ya 'furrulen' estas dos funciones si tienes más dudas, pregunta.

Editame

Hola NEBIRE que mas como etas espero que muy bien.

Bueno te comento ya hoy pude sentarme realmente a dedicarle tiempo a esto y creo que me fue super bien por que creo que adelante bastante y de la forma correcta, modifique cosas que para mi estaban demasiado enredadas y que no sabia si el codigo se estaba ejecutando de forma correcta pero llegue a un punto que no te entiendo y es la parte final de rellenar el sudoku como lo tienes en el siguiente codigo:

//código previo
            Valor = SeleccionarValorAzar(Columna, Fila)  //la función que obtiene un valor de cada vez.
            Si (Valor>0) luego
                Sudoku((Fila * c_Nueve) + Columna) = valor   //Sudoku() es el array que mantiene internamente los valores.             
                Columna +=1
            Si no
                // Borra los valores de la fila actual
                Bucle para k desde 0 a columna
                    Sudoku((Fila * c_Nueve) + k) = 0
                Fin bucle

                // Tras 10 intentos en la misma fila, borramos también la fila previa
                Intentos += 1
                Si (Intentos = 10) luego
                    Si (Fila > 0) luego  // no podemos retroceder a filas más atrás que la primera.
                        Fila = (Fila - 1) // Borramos también la fila anterior (y si sucede otra vez, la previa, etc...)
                        Bucle para k desde 0 To c_Ocho
                            Sudoku((Fila * c_Nueve) + k) = 0                           
                        Fin Bucle
                    Fin si
                    Intentos = 0
                Fin si
                Columna = 0
            Fin si
.... // código después...

aqui hay cosas obvias y otras no tanto.
1- cual es ese array sudoku y para que sirve ? no lo entiendo la verdad

2- yo estoy trabajando con una matriz bidimensional y en mi funcion generadoraleatorio() es donde supuestamente lo lleno(Segun mi forma de hacerlo) pero no se en que lugar estaria metiendo este codigo que te muestro arriba el tuyo, por que tu hablas de codigo previo y codigo despues ???

3- por otro lado tengo muchas dudas con la funcion de tomar ausentes por que pones como parametro un out NumAusentes

Array Byte = Funcion TomarAusentes(Array Byte Presentes(), Out Entero NumAusentes) no entiendo por que pones ese valor ahi, o bueno creo saberlo, lo haces para tener el indice de ese vector pero lo que no se es por que tenerlo de parametro si al llamarlo de otra funcion como lo haces en
Array byte = GetArrayAusentes(Entero X, Entero Y,  Out Entero NumAusentes)

ese valor no lo utilizas de ninguna manera o por lo menos no lo veo que lo hagas para mi ese valor por parametro no sirve por que el dato que se utiliza es es que devuelve la funcion como tal.

La verdad no me queda muy claro eso voy a colocar el codigo que tengo solo para que me ayudes a depurar errores pero solo faltaria que me explicaras eso que te pido para poder hacer las funciones de valor azar y la de permitido o admisible no entiendo el por que tu tienes otras mas tampoco.
package Clases;

import java.util.Random;

public class Tratando {

    public static void GeneradorAleatorio() {
       
        int matriz[][] = new int[9][9];
               
        for (int i = 0; i < 9; i++) {
            System.out.println("");
            for (int j = 0; j < 9; j++) {
                System.out.print(matriz[i][j] + "\t");
            }
        }
    }

    public static int [] GetFila(int matriz[][], int fila) {
        int filas[] = new int[9];
        for (int i = 0; i < 9; i++) {
            filas[i] = matriz[fila][i];
        }
        return filas;
    }

    public static int [] GetColumna(int matriz [][], int columna) {
        int columnas[] = new int[9];
        for (int i = 0; i < 9; i++) {
            columnas[i] = matriz[i][columna];
        }
        return columnas;
    }

    public static int [] GetCaja(int matriz[][], int filas, int columnas) {

        int minfila, maxfila;
        int mincolum, maxcolum;

        if (filas >= 0 && filas < 3) {
            minfila = 0;
            maxfila = 2;
        } else if (filas >= 3 && filas < 6) {
            minfila = 3;
            maxfila = 5;
        } else {
            minfila = 6;
            maxfila = 8;
        }

        if (columnas >= 0 && columnas < 3) {
            mincolum = 0;
            maxcolum = 2;
        } else if (columnas >= 3 && columnas < 6) {
            mincolum = 3;
            maxcolum = 5;
        } else {
            mincolum = 6;
            maxcolum = 8;
        }
       
        int caja[] = new int[9];
        int k = 0;

        for (int i = minfila; i < maxfila; i++) {
            for (int j = mincolum; j < maxcolum; j++) {
                caja[k] = matriz[i][j];
                k++;
            }
        }
        return caja;
    }

    public static int[] unificarArray (int filas[], int columnas[], int caja[]) {
       
        int unificado[] = new int[10];
       
        for (int i = 0; i < 9; i++) {
            if (filas[i]>0) {
                unificado[filas[i]] += 1;
            }
            if (columnas[i]>0) {
                unificado[columnas[i]] += 1;
            }
            if (caja[i]>0) {
                unificado[caja[i]] += 1;
            }
        }
        unificado[0] = 0;
       
        for (int i = 1; i < 10; i++) {
            if (unificado[i]>0) {
                unificado[i] = i;
            }
        }
        return unificado;
    }
   
    public static int [] TomarAusentes (int unificado[]){
        int ausentes[] = new int [9];
        int k=0;
        for (int i = 1; i < 10; i++) {
            if (unificado[i] == 0) {
                ausentes[k] = i;
                k++;
            }
        }
        return ausentes;
    }
   
//    public static int ValorAZar (int matriz[][], int i, int j) {
//       
//        Random rand = new Random();
//       
//     
//        return azar[n];
//    }
//    public otra funcion (){
//        int tempfila[];
//        int tempcolum[];
//        int tempcaja[];
//        int tempo[];
//       
//          tempfila = GetFila(matriz, i);
//        tempcolum = GetColumna(matriz, j);
//        tempcaja = GetCaja(matriz, i, j);
//    }
   
    public static void main(String[] args) {

        GeneradorAleatorio();//
       
    }
}

La parte comentada es donde iria las funciones que me faltan por entender.
Edilberto Tapias Mercado
Estudiante Ing. Telematica

Serapis

#14
Cita de: Editame en  5 Agosto 2017, 10:44 AM
... pero llegue a un punto que no te entiendo y es la parte final de rellenar el sudoku como lo tienes en el siguiente codigo:

...por que tu hablas de codigo previo y codigo despues ???

//código previo
          ....el código intermedio (omitido por brevedad)
.... // código después...

Puse 'código previo' y 'código después', para no volver a poner la función completa... En ese tramo, lo que te indicaba era que justo esa parte (de la función) es la que se encarga de que si la 'obtención' de valores llega a un punto donde se bloquea, esa parte CRUCIAL, es la que dando 1, ó 2 pasos atrás, permite salir del bloqueo:
1 paso atrás: elimina toda la fila actual y la rehace.
2 pasos atrás: deshace también la fila previa, si tras deshacer 10 veces la fila actual, no logra avanzar (salir del bloqueo)... un bloqueo 'persistente', se debe a que no deja muchas opciones para la línea actual.

Cita de: Editame en  5 Agosto 2017, 10:44 AM
1- cual es ese array sudoku y para que sirve ? no lo entiendo la verdad

2- yo estoy trabajando con una matriz bidimensional y en mi funcion generadoraleatorio() es donde supuestamente lo lleno(Segun mi forma de hacerlo) pero no se en que lugar estaria metiendo este codigo que te muestro arriba el tuyo,
1 - Es el nombre que yo le he dado al array que guarda los valores... tu lo llamas matriz[][] y lo usas de modo bidimensional (filas y columnas, 9x9), yo lo llamo sudoku y usa índices (0 a 80).

2 - Yo hice una función llamada RellenarSudokuAlAzar, que es función principal para generar el sudoku por completo, es desde aquí donde se llama a la segunda función principal (para un solo valor al azar) y en esa donde se llama al resto...

Repongo la función completa, esta función la puse en el 'Respùesta #2' de este hilo  (IMPORTANTE: lee los comentarios en el pseudocódigo):

Funcion RellenarSudokuAlAzar()    
   Entero Fila, columna
   Byte Valor, Intentos

   Fila=0 // la primera fila, la podrías obtener al azar completamente en ese caso marcar aquí 1, para comenzar en la fila 1, la 0 no va a requerir todas las comprobaciones que pueden requerir las siguientes.
   Hacer  '// esto es fila, puede ser un bucle que va de 0 a 8
       Intentos = 0
       Columna = 0
       Hacer    
           Valor = SeleccionarValorAzar(Columna, Fila)  //la función que obtiene un valor de cada vez.
           Si (Valor>0) luego
               Sudoku((Fila * c_Nueve) + Columna) = valor   //Sudoku() es el array que mantiene internamente los valores.            
               Columna +=1
           Si no
               // Borra los valores de la fila actual
               Bucle para k desde 0 a columna
                   Sudoku((Fila * c_Nueve) + k) = 0
               Fin bucle

               // Tras 10 intentos en la misma fila, borramos también la fila previa
               Intentos += 1
               Si (Intentos = 10) luego
                   Si (Fila > 0) luego  // no podemos retroceder a filas más atrás que la primera.
                       Fila = (Fila - 1) // Borramos también la fila anterior (y si sucede otra vez, la previa, etc...)
                       Bucle para k desde 0 To c_Ocho
                           Sudoku((Fila * c_Nueve) + k) = 0                            
                       Fin Bucle
                   Fin si
                   Intentos = 0
               Fin si
               Columna = 0
           Fin si
       Repetir Mientras (Columna <9)
       Fila +=1
   Repetir Mientra (Fila<9)
Fin Funcion
// Al término de esta función se podría dibujar los valores en el tablero para verificar visualmente el resultado.


Cita de: Editame en  5 Agosto 2017, 10:44 AM
3- por otro lado tengo muchas dudas con la funcion de tomar ausentes por que pones como parametro un out NumAusentes

Array Byte = Funcion TomarAusentes(Array Byte Presentes(), Out Entero NumAusentes) no entiendo por que pones ese valor ahi, o bueno creo saberlo, lo haces para tener el indice de ese vector pero lo que no se es por que tenerlo de parametro si al llamarlo de otra funcion como lo haces en
Array byte = GetArrayAusentes(Entero X, Entero Y,  Out Entero NumAusentes)

ese valor no lo utilizas de ninguna manera o por lo menos no lo veo que lo hagas para mi ese valor por parametro no sirve por que el dato que se utiliza es es que devuelve la funcion como tal.
Te aclaro... esta función devuelve un array. El array tiene 9 elementos, pero necesitamos también devolver otro valor. el de cuantos valores en ese array son 'útiles' (detrás de esos valores útiles hay ceros, no nos interesan).
El parámetro es de salida, es decir es devuelve por referencia (por puntero, una dirección de memoria).

Un ejemplo: Imagina una lista de 9 alumnos para el carnet de conducir... se examinan y aprueban solo 3, se devuelve una lista, con sus nombres, pero es preciso saber cuantos son. La lista sigue teniendo 9 elementos, no viene a cuento crear una nueva lista con exactamente los conductores aprobados, la reutilizamos.
Si no sabes pasar un parámetro por referencia, todavía puedes solucionarlo en tu código, recorriendo el array hasta que se encuentre un valor vacío (cero).
Es decir había una lista de 9 alumnos inscritos, creamos otra del mismo tamaño 8por si todos aprobaban), pero luego resulta que aprueban 3, ó 5 o 6, o todos o ninguno)... entonces en la lista entregada leemos nombres, con cada uno leído sumamos 1, cuando no haya más en la lista de aprobados, sabemos ya CUANTOS alumnos aprobaron. 3,5,6,todos, ninguno, etc...

Y porqué necesitamos saber cuantos valores 'útiles' (valores ausentes) tiene la lista?. Pués porque ahora vamos a sortear entre ellos, el elegido será el que se ponga en la casilla.
Si hay 5 valores ausentes (útiles),  (similar a los alumnos aprobados) y ocupan los puestos del 0 al 4, nosotros luego vamos a elegir al azar entre 0 y 4.
SIIIIIIII... elegimos ún índice, porque las funciones aleatorias no saben elegir al azar un valor 2,5,6,9, solo saben elegir un valor dentro de un rango dado, y dentro de ese rango los valores contenidos son elegibles. Si el 3,4,7 y8 quedan fuera del sorteo, significa que no debn ser elegibles, luego toca asignarles un número a los que si optan y luego por ese número (índice en el array), sabemos que valor salió elegido.
Imagina que son esos alumnos, podríamos hacer papelitos con sus nombres, pero OH, nuestro sistemá es matemático (míralo como si tuvieras un bingo de juguete con 100 bolitas, sacas todas y dejas una por cada alumno aprobado) y a cada bola se le asigna un nombre: La bola 0, para Juan, la bola 1 para Luis, la bola 2 par aandrés,etc... entonces hhaces mover el bombo, extraes la bola y cantas la que sale: Bola 2.... a qui
én corresponde? a Andres.... luego Andres salió elegido al azar...

Justo eso esa parte final, es la que hacen las líneas tras la función Tomarausentes:

Este trozo de código es un extracto al final de la función: "SeleccionarValorAzar"
// OJO: si el array queda vacío <----------- HAY UN BLOQUEO.
   Si (n=0) luego devolver 0 //y salir de la función tras devolver

   // Finalmente se toma un valor al azar entre 0 y n-1, que representa el indice del array Azar. Este array tiene exclusivamente los números que no aparecen ni en la fila, ni en columna, ni en bloque.
   k = Aleatorio( entre 0 y n-1)

   Devolver Azar(k) //ha salido la bola K, devlver el valor contenido en ese índice (si fuera un alumno, sería su nombre).



Cita de: Editame en  5 Agosto 2017, 10:44 AM
La verdad no me queda muy claro eso voy a colocar el codigo que tengo solo para que me ayudes a depurar errores pero solo faltaria que me explicaras eso que te pido para poder hacer las funciones de valor azar y la de permitido o admisible no entiendo el por que tu tienes otras mas tampoco.
Creo que debería quedarte todo claro ya...

Verás tu función "GeneradorAleatorio" sería equivalente a la que yo llamo: "RellenarSudokuAlAzar"....
Debe tener 2 bucles, uno por filas y otro interno para columnas. Dentro de ese es que en cada cilo se invoca "SeleccionarValorAzar(fila, columna)" esperando que se le devuelva un valor.
Si es mayor que 0 se asigna al array que mantiene los valores (tu llamas 'Matriz' a tu array, yo le llamo directamente 'Sudoku' a mi array)
Pero si el valor obtenido de regreso es 0, significa que hay una situación de bloqueo. Hay que eliminar la fila actual completa (se suma un intento y si se alcanzan 10 antes de poder completar la fila, se elimina también la fila anterior).


----------------------------------------------
Te comento por encima si veo bien tus funciones, pero debes probarlas siempre. Yo solo reviso la lógica, que es la parte que el IDE (seguramente uses Eclipse), no puede decirte nada...

- GeneradorAleatorio: Llámala como prefieras, pero esta función, impleméntala tomando como referencia la que yo llamo "RellenarSudokuAlAzar". Justo te acabo de dar unas palabras al respecto... y el pseudocódigo de la misma te lo he vuelto a poner completo, también más arriba en este mensaje.
Citarpublic static void GeneradorAleatorio() {

- GetFila: OK
Citarpublic static int [] GetFila(int matriz[][], int fila) {

- GetColumna: OK
Citarpublic static int [] GetColumna(int matriz [][], int columna) {

- GetCaja: OK, pero puede optimizarse saber a qué bloque (caja), nos estamos refiriendo (ya te comenté)
 
Citarpublic static int [] GetCaja(int matriz[][], int filas, int columnas) {


- unificarArray: OK, ahora sí...
Citarpublic static int[] unificarArray (int filas[], int columnas[], int caja[]) {

- TomarAusentes: CASI, te falta devolver el valor de k (yo lo hago por referencia como un parámetro). Si no lo devuelves de ninguna manera, deberás volver a calcular dicho valor en un bucle tras esta función (más arriba ya te comenté esto)  
 
Citarpublic static int [] TomarAusentes (int unificado[]){

Cita de: Editame en  5 Agosto 2017, 10:44 AM
La parte comentada es donde iria las funciones que me faltan por entender.
OK, en otro mensaje (un poco más tarde, ahora tengo cosas que hacer), te desgrano ambas funciones (son dos, no?): SeleccionarValorAzar y RellenarSudokuAlAzar

Editame

Hola nebire espero que estes bien ...

mira pido disculpas por no haberte comentado nada de hace tiempo pero no me encontraba en la ciudad y no habia podido continuar con este proyecto.

Bueno te comento que sigo un poco perdido con el tema del parametro que pasas donde tienes el out
Array Byte = Funcion TomarAusentes(Array Byte Presentes(), Out Entero NumAusentes)
entiendo que es el indice del vector ausentes pero no se manejarlo como tu lo haces por ende las ultimas funciones de devolverValorAzar no las hice si no que lo hice como yo pude, por otro lado el metodo generarSudoku ya lo hice si tenias razon era algo muy sencillo probe el codigo hasta donde me deviuelve los valores ausentes y todo esta correcto pero aun asi me sigue presentando el bloqueo y solo me llena aproximadamente unos 36 a 44 valores de ahi no me pasa y no se si es un error en la funcion que devuelve el valorAzar pero no me esta retrocediendo y me esta botando un error que traduce que debe ser positivo.

Te coloco el error completo

Exception in thread "main" java.lang.IllegalArgumentException: bound must be positive
at java.util.Random.nextInt(Random.java:388)
at Clases.Tratando.SeleccionarValorAzar(Tratando.java:199)
at Clases.Tratando.GeneradorAleatorio(Tratando.java:14)
at Clases.Tratando.main(Tratando.java:205)
C:\Users\Edilberto\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)


y te coloco el sodigo completo de lo que hice

package Clases;
import java.util.Random;
public class Tratando {

    public static void GeneradorAleatorio() {
       
        int matriz[][];
        int fila = 1, columna, intentos, valor;
        matriz = PrimeraFila();
        do {
            columna = 0;
            intentos = 0;
            do {
                valor  = SeleccionarValorAzar(matriz, fila, columna);
                if (valor > 0) {
                    matriz[fila][columna] = valor;
                    columna++;
                }else{
                    for (int i = 0; i < columna; i++) {
                        matriz[fila][i] = 0;
                    }
                    intentos++;
                    if (intentos == 5) {
                        System.out.println("intentos: " + intentos);
                        if (fila>0) {
                            fila = fila-1;
                            for (int i = 0; i < 8; i++) {
                                matriz[fila][i] = 0;
                            }
                        }
                        intentos = 0;
                    }
                    columna = 0;
                }
            } while (columna < 9);
            fila++;
        } while (fila < 9);
       
        for (int k = 0; k < 9; k++) {
            System.out.println("");
            for (int h = 0; h < 9; h++) {
                System.out.print(matriz[k][h] + "\t");
            }
        }
    }
   
    public static int [][] PrimeraFila() {
       
        int matriz[][] = new int[9][9];
        Random ran = new Random();
        int fila = 0;
        int numero;
        int em=0;
        int cont=0,j;
        int i = 0;
        while (i < 9) {
            numero = 1 + ran.nextInt(9);
            if (em == 0) {
                matriz[fila][i] = numero;
                em++;
            }else{
                cont = 0;
                j = 0;
                while (j < i) {
                    if (numero == matriz[fila][j]) {
                        cont++;
                        break;
                    }else{
                        matriz[fila][i] = numero;
                    }
                    j++;
                }
            }
            if (cont==0) {
                i++;
            }
        }
       
        return matriz;
    }

    public static int [] GetFila(int matriz[][], int fila) {
       
        int filas[] = new int[9];
        System.arraycopy(matriz[fila], 0, filas, 0, 9);
        return filas;
    }

    public static int [] GetColumna(int matriz [][], int columna) {
        int columnas[] = new int[9];
        for (int i = 0; i < 9; i++) {
            columnas[i] = matriz[i][columna];
        }
        return columnas;
    }

    public static int [] GetCaja(int matriz[][], int filas, int columnas) {

        int minfila = 0, maxfila = 0;
        int mincolum = 0, maxcolum = 0;

        if (filas >= 0 && filas < 3) {
            minfila = 0;
            maxfila = 2;
        } else if (filas >= 3 && filas < 6) {
            minfila = 3;
            maxfila = 5;
        } else if (filas >= 7 && filas < 9){
            minfila = 6;
            maxfila = 8;
        }

        if (columnas >= 0 && columnas < 3) {
            mincolum = 0;
            maxcolum = 2;
        } else if (columnas >= 3 && columnas < 6) {
            mincolum = 3;
            maxcolum = 5;
        } else if (columnas >= 7 && columnas < 9){
            mincolum = 6;
            maxcolum = 8;
        }
       
        int caja[] = new int[9];
        int k = 0;

        for (int i = minfila; i <= maxfila; i++) {
            for (int j = mincolum; j <= maxcolum; j++) {
                caja[k] = matriz[i][j];
                k++;
            }
        }
        return caja;
    }

    public static int[] unificarArray (int filas[], int columnas[], int caja[]) {
       
        int unificado[] = new int[10];
       
        for (int i = 0; i < 9; i++) {
            if (filas[i]>0) {
                unificado[filas[i]] += 1;
            }
            if (columnas[i]>0) {
                unificado[columnas[i]] += 1;
            }
            if (caja[i]>0) {
                unificado[caja[i]] += 1;
            }
        }
        unificado[0] = 0;
       
        for (int i = 1; i < 10; i++) {
            if (unificado[i] > 0) {
                unificado[i] = i;
            }
        }
        return unificado;
    }
   
    public static int [] TomarAusentes (int unificado[]){
        int cont = 0;
        for (int i = 1; i < 10; i++) {
            if (unificado[i] == 0) {
                cont++;
            }
        }
       
        int ausentes[] = new int [cont];
       
        int k=0;
        for (int j = 1; j < 10; j++) {
            if (unificado[j] == 0) {
                ausentes[k] = j;
                k++;
            }
        }
       
        return ausentes;
    }
   
    public static int [] GetArrayAusentes (int matriz [][], int x, int y){
        int tempfila[] = GetFila(matriz, x);
        int tempcolum[] = GetColumna(matriz, y);
        int tempcaja [] = GetCaja(matriz, x, y);
       
        int temp [] = unificarArray(tempfila, tempcolum, tempcaja);
       
        return TomarAusentes(temp);
    }
   
    public static int SeleccionarValorAzar (int matriz [][], int x, int y){
        int n;
        int temp[] = GetArrayAusentes(matriz, x, y);
        for (int i = 0; i < temp.length; i++) {
            System.out.print("\n"+temp[i]+"\t");
        }
        Random rand = new Random();
        n = + rand.nextInt(temp.length);
        System.out.println(":" + temp[n]);
        return temp[n];
    }
   
    public static void main(String[] args) {
        GeneradorAleatorio();
    }
}

Edilberto Tapias Mercado
Estudiante Ing. Telematica

Editame

Hola NEbire te doy mil gracias por la ayuda ya logre hacerlo solo me faltaba evaluar cuando el indice de ese arrayazar llegaba a 0 para que devolviera 0 como tu lo tenias,  para asi poder entrar en la parte que corrige el bloqueo, ya pude realizarlo mil gracias por todo.

ahora viene la parte grafica. cuando este terminado o necesite ayuda te comentare e igual lo publicare para que les sirva de guia a los que inicen algo similar
Edilberto Tapias Mercado
Estudiante Ing. Telematica

Serapis

#17
Vaya... me alegro, porque te estaba respondiendo y casi había terminado cuando me llamaron para ir a cenar fuera, y a la vuelta he acabado de terminar y enviaba respuesta... de todos modos, la publico...


Vamos por partes....
Citar
mira pido disculpas por no haberte comentado nada de hace tiempo pero no me encontraba en la ciudad y no habia podido continuar con este proyecto.
No te preocupes. Cada uno dispone del tiempo que dispone y nadie tiene derecho a reclamar nada al respecto.


-----------------------
El tema del parámetro de devolución...
CitarArray Byte = Funcion TomarAusentes(Array Byte Presentes(), Out Entero NumAusentes)
entiendo que es el indice del vector ausentes pero no se manejarlo como tu lo haces
Bien, no importa si no sabes devolver un parámetro por referencia, se recalcula de nuevo, es muy simple...

Varíamos la función, seguimos devolviendo el array y solo el array...
CitarArray Byte = Funcion TomarAusentes(Array Byte Presentes() )
voy a tu código, donde se llama a todas las funciones y finalmente a TomarAusentes:
Citarint temp[] = GetArrayAusentes(matriz, x, y);
Ahora entonces hacemos un bucle para tomar el valor que no has sabido devolver:
Bucle para k desde 1 a 9
 si temp(k) es mayor que cero luego
    NumAusentes = k  // esto se puede hacer de diferentes maneras, esta es la mas sencilla, otra es saliendo del bucle cuando se encuentre un valor 0, etc...
    // se actualiza con cada ocasión que sea cierta la condición, ...no importa es un bucle pequeño.
 Fin si
Fin Bucle

Ya tenemos el valor de NumAusentes.

Ahora la funcion rand.nextInt debe devolver un valor al azar entre 1 y numausentes, pero solo si NumAusentes es mayor que cero
Si NumAusentes > 0 luego
  azar = rand.nextInt(entre 1 y NumAusentes)  
Si no
  // este es el caso de que no haya números ausentes, se devlvería 0.
Fin si


Cuando una función para devolver un número al azar, no permite especificar un rango, y siempre fuerza desde '0' hasta 'x', se puede truncar... veamos como:
Sea el rango entre 5 y 12, entonces en la función se toma el mismo espacio del rango pero empezando en 0, esto es, si empeiza en 0 y no en 5, es que (es como si) hemos restado 5, luego al valor mayor del rango también le restamos 5. Luego al valor que salga (que será: 0,1,2,3,4,5,6 ó 7), pués le sumamos 5 y efectivamente tendremos el valor en el rango 5-12 , la demostración sencilla sería: (0+5, 1+5, 2+5, 3+5, 4+5, 6+5 ó 7+5), que en efecto es entre 5 y 12
 n = ...rand.nextInt(12-5) + 5  

Unificando un poco el código de esta sección, sería más o menos así
SeleccionarValorAzar (matriz(), x, y)
       int n, Numausentes
       int temp[] = GetArrayAusentes(matriz, x, y)

       Bucle para i desde 1 a temp.length //OJO: desde 1, porque el indice 0, sabemos que SIEMPRE vale 0
           Si matriz(i) > 0 luego
               NumAusentes = i
            Fin si
       Fin bucle

       Si NumAusentes > 0 luego  //falta esta condición en tu código.
           Random rand = new Random()
           n =  rand.nextInt(Numausentes-1) +1
       
           System.out.println(":" + temp[n])
           return temp[n];
       Si no
           devolver 0
      Fin si
Fin Funcion


-----------------------
Siguiente el error: Si miras la cascada de llamadas hasta el error, (dentro del programa desde main) se llama inicialmente a la función 'GeneradorAleatorio', la cual llama a su vez a 'SeleccionarValorAzar' y en esta se invoca a la función: 'Random.nextInt', que verás que es la última función ejecutada (es la que origina el error)...
CitarException in thread "main" java.lang.IllegalArgumentException: bound must be positive
   at java.util.Random.nextInt(Random.java:388)
Básicamente el error está generado por la elección del número al azar. En el caso de este juego, los valores deben estar comprendidos siempre entre 1 y 9, y específicamente en cada momento concreto entre 1 y 'numausentes'. Ya que lo que elegimos es el índice de aquel array de ausentes y devolvemos el valor contenido en ese indice del array.

Ahora miro el código, para ver por qué dicha función trata de elegir un número negativo.... bien pego la línea donde se origina el error:
Citarn = + rand.nextInt(temp.length);
...de entrada, el valor pasado a rand.nextInt, no es correcto.
Sabemos que ese array tiene 10 elementos, porque procede de la función TomarAusentes, pero no son elegibles todos los índices, solo son elegibles desde el índice 1 hasta el índice de 'numausentes' (que algunas veces podrá ser 9). Justo lo acabo de explicar en el punto anterior.
Recuerda que el array de TomarAusentes, podría no arrojar valores, porque todos los valores estén ocupados; algunos en la fila, otros en la columna y otros en el bloque.

En ese caso, no hay que forzar a elegir un valor al azar, directamente la función SeleccionarValorAzar  (más arriba puse su pseudocódigo) devuelve 0. Y la función que recibe el resultado (GeneradorAleatorio), ya tiene previsto el caso para solucionar el bloqueo (ese '0', indica el bloqueo).

NOTA: que pongo parcialmente el código de la función (no conviene poner todo un libro, solo para citar 2 párrafos):
             ...  
               valor  = SeleccionarValorAzar(matriz, fila, columna);
               if (valor > 0) {
                   matriz[fila][columna] = valor;
                   columna++;
               }else{
                  //ResolverBloqueo
               fin si
...


Citar
...por otro lado el metodo 'generarSudoku' ya lo hice si tenias razon era algo muy sencillo probe el codigo hasta donde me devuelve los valores ausentes y todo esta correcto pero aun asi me sigue presentando el bloqueo y solo me llena aproximadamente unos 36 a 44 valores de ahi no me pasa...

Si, bueno, yo lo que veo es que has pueto el límite de intentos en 5, yo lo puse en 12 y luego lo bajé a 10... y lo pongo a generar sudokus (y al tiempo dibujar cada valor generado) durante una hora o algo más y tras 15500 sudokus calculados, lo he parado... es decir no se bloquea. Cambia el número de intentos a 10...

----------------

p.d.: Como ejercicio de optimización, te aclaro que todas las funciones de: getFila, getColumna, getBloque, UnificarArrays y TomarAusentes, puede ser muy optimizado en apenas 5 bucles (uno detrás del otro) usando siempre el mismo y único array, para los 3 get y otro para las otra dos secciones...

Editame

#18
Nebire amigo una pregunta

es correcto hacer esto

public static void GeneradorAleatorio() {
   .
   .
   .
GeneradorDePistas(matriz);  // aqui invoco la funcion y le mando la matriz que ya tiene el sudoku resuelto
}


la idea es copiar esa matriz a una matriz2 para trabajar sobre ella lo de las pistas, es decir la cantidad de numeros que va a salir en el sudoku que vamos a resolver

public static void GeneradorDePistas(int matriz[][]){
       
       int matriz2 [][] = new int [9][9];
       
       for (int i = 0; i < 9; i++) {
           for (int j = 0; j < 9; j++) {
               matriz[i][j] = matriz2[i][j];
           }
       }
       
       System.out.println("");
       System.out.println("");
       for (int i = 0; i < 9; i++) {
           System.out.println("");
           for (int j = 0; j < 9; j++) {
               System.out.print(matriz2[i][j] + "\t");
           }
       }
   }


al ejecutarlo de esta funcion no me imprime la copia si no una matriz de solo ceros
Edilberto Tapias Mercado
Estudiante Ing. Telematica

Editame

olvida esa pregunta es algo muy tonto tenia que matriz[][] = matriz2[][] claro por eso me imprimia ceros le esta asignando valores de la segunda matriz q estaba vacia que tonteria ...
Edilberto Tapias Mercado
Estudiante Ing. Telematica