elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


 


Tema destacado: ¿Eres nuevo? ¿Tienes dudas acerca del funcionamiento de la comunidad? Lee las Reglas Generales


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  Java (Moderadores: Debci, Leyer)
| | | |-+  Codigo para crear SUDOKUS
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: 1 2 [3] Ir Abajo Respuesta Imprimir
Autor Tema: Codigo para crear SUDOKUS  (Leído 3,826 veces)
NEBIRE


Desconectado Desconectado

Mensajes: 576


Ver Perfil
Re: Codigo para crear SUDOKUS
« Respuesta #20 en: 14 Agosto 2017, 19:15 »

Sobre las pistas, piensa que teniendo ya resuelto el sudoku, obtener las pistas es simplemente decidir que valores del sudoku dejar ó a la inersa cuales retirar, lo que resulte más breve.

También es preciso saber que si las pistas son menos del 20% de los valores, tiene múltiples soluciones.

Entonces:
- Si un sudoku, tiene una sola solución; la validación la harás con tu matriz del sudoku (resuelta). Comprobando en un bucle que el array Sudoku() (tu le llamas Matriz() ), coincide uno a uno con el array User(). El array User() inicialmente es copia del array Pistas() (por si decide restablecer, se copia de nuevo Pistas() en User()...)
- En cambio si tienes múltiples soluciones, la validación sería recurrir a 1 bucle donde reclamas los ausentes de cada fila, bloque y columna, será validado siempre que en todos los casos dé 0 ausentes.

Código:
Buleano = Funcion ValidarSudokuDeMultiplesSoluciones
    buleano ausentes

    Bucle para k desde 0 a 8
        ausentes = Ausencia (Presencia( GetFila(k) ))
        Si ausentes = false Devolver False //y salir de la función
               
        ausentes = Ausencia (Presencia( GetColumna(k) ))
        Si ausentes = false Devolver False //y salir de la función

        ausentes = Ausencia (Presencia( GetBloque(k) ))
        Si ausentes = false Devolver False //y salir de la función
    Fin bucle
    Devolver True // aparecen todos, una sola vez en fila, columna y bloque.
Fin funcion

NOTA que:
Citar
ausentes = Ausencia (Presencia( Getxxxx(k)))
es una llamada a otra función con la salida de la interna...
Es decir, primero se llama a 'GetXXXX(k) que nos devuelve el array solicitado del array User(). OJO: del array User, no del array Sudoku (Matriz, la llamas tu).
Luego que devuelve ese array es el parámetro de entrada para invocar a la función Presencia(array), y la salida de esta, que también devuelve un array pero de 10 elementos, es usada como la entrada de la función Ausencia(array) que devuelve finalmente un valor buleano.
Es equivalente a esto mismo (pero requiere entonces declarar un array dentro de la función, para recibir y pasar a la siguiente función y más líneas de código).
   
Citar
   array tipo byte Arr() // sería antes del bucle.

   Arr = GetFila(k)
   Arr = Presentes(arr)
   ausentes = Ausencia(arr)

   Si ausentes = false Devolver False //y salir de la función

Esta función ya la conoces, es equivalente a la segunda parte de unificar arrays:
Código:
Array byte = Funcion Presencia(array tipo byte Arr() )
    array tipo byte Tmp(0 a 9) // 10 elementos.

    Bucle para k = 0 a 8
        tmp( arr(k)) = arr(k)
    Fin Bucle
    Devolver Tmp
Fin Funcion

Esta función también la conoces, pero aquí en vez de devolver el array con los ausentes, devolvemos si hay o no ausentes (o la cantidad de ausentes y en destino convertirlo en False si es mayor que 0).
Código:
Buleano = Funcion Ausencia(array tipo byte Presentes() )
    Bucle para k desde 1 a 9 //OJO: 10 elementos, hasta 9
        Si (Presentes(k) <> k) luego
            Devolver FALSE //y salir de la función
        Fin si
    Fin bucle
    Devolver True
Fin funcion

Un último consejo... mira de optimizar el código una vez te funciones bien. Estas dos funciones, podrían llamar a otras que realicen el trabajo 8ya en el código previo) y  aquí solo evaluar el resultado y devolverlo...

No pongo el pseudocódigo de lo que sería la función: 'ValidarSudokuDeUnaSolaSolucion', porque es bastante sencilla.
Ya sabes que puedes ponerle el nombre que quieras a las funciones, siempre que el propio nombre revele su intencionalidad... sin necesidad de llegar a ser tan largo y explícito como: 'ValidarSudokuDeUnaSolaSolucion', que tiene por objeto además ser auto-explicativo... podría ser 'ValidarSolucionSimple' y el otro 'ValidarSolucionMultiple'...

Recuerda que deberás tener varios arrays, como mínimo estos 3:
- El de la Solución (que se genera cuando creas el sudoku).
- El de Pistas (que es una selección-extracción de la solución).
- Y el del Usuario (que inicialmente es copia del array Pistas), y que es donde el usuario va introduciendo los valores que él mismo decida.
Por tanto tras crear el Sudoku (la solución, el array Matriz) satisfactoriamente), tras ello invoca a sendas funciones para inicializar ambos arrays adicionales (pistas y User). Crear el de User también conviene que sea una función aparte, porque si el usuario reclama 'Resetear' la partida, entre otras cosas deberás volver a clonar el array Pistas() en User().


En línea

Editame

Desconectado Desconectado

Mensajes: 11


Todo radica en la Humildad !


Ver Perfil
Re: Codigo para crear SUDOKUS
« Respuesta #21 en: 14 Agosto 2017, 20:38 »

Hola amigo

Tenia pensado que solo fuera soluciones unicas por lo tanto el valor minimo de elementos que deben aparecer es de 17 pistas o valores para cada sudoku, si es menos que 17 ya seria de solucion multiple que por ahora no lo tengo comtemplado. por esta razon y tratando de adelantar habia pensado en la dificultad del juego asignado valores o pistas que mostrar para cada una. pero aun no tengo muy claro como hacer para mostrar dicha cantidad de valores de forma aleatoria en la matriz en esas estoy vamos a ver como me va cualquier cosa te sigo avisando.

Buen dia bendiciones.


En línea

Edilberto Tapias Mercado
Estudiante Ing. Telematica
NEBIRE


Desconectado Desconectado

Mensajes: 576


Ver Perfil
Re: Codigo para crear SUDOKUS
« Respuesta #22 en: 15 Agosto 2017, 05:49 »

Te respondo por aquí el mensaje privado (útil para todos).

Bien, las pistas pueden ir en efecto entre 17 y las que quieras.
Probablemente alguien que no sea muy entusiasta de las matemáticas y todo lo que sea pensar, necesite la mitad de las casilla como pistas, incluso alguna más...

Yo propondría un límite de 45 pistas como máximo y un mínimo de 17 (para que en efecto tenga una única solución).
Esto implica de alguna manera establecer niveles de dificultad. El nivel de dificultad, va a depender de 3 factores básicos:
A - Número de pistas (cuantas menos, más difícil).
B - Distribución en el 'mapa'.
C - Destribución de valores.

Lo básico es centrarse en el número de pistas, pero de soslayo miramos las otras dos posibilidades.

B - Supongamos que aportamos 27 pistas y que estas se colocan usando exactamente 3 bloques (el 1º, el 5º y el 9º)... esta distribución es algo distinta a si las colocamos de forma aleatoria.
C - Supongamos ahora que las pistas, nos centramos en que valores vamos a colocar (no importa dónde para este caso). Supongamos que sigue siendo 27 pistas, no es lo mismo proporcionar los nueves valores 2,3 y 4 que proporcionar 3 pistas de cada valor (111,222,333,444,555,666,777,888,999), y es disitnto de si los valores son elegidos al azar, puede que haya tres 9, y cuatro 1, pero solo un 5.

Estos dos casos (B y C) es para estudiarlos más a fondo. Su estudio exhaustivo escapa de la ayuda a proporcionar en el foro. A falta de ello es mejor dividirlo en 2 grupos, si son elegidos al azar les concedemos un valor de 'no difícil' y si los elegimos pensando en 'putear' al usuario, le concederíamos un valor de 'difícil'.

Queda por tratar el caso A (el número de pistas). hay que repartirlos en tantos grupos como niveles de dificultad. El reparto no debería ser 'fijo', es decir que aumente la misma cantidad de pistas a medida que baja la dificultad. Ya que esto sería una serie aritmética y es más razonable y ajustado a la realidad una serie serie geométrica.

En matemáticas, una serie se deifne por: un rango de valores llamados términos o medios interpolados, los valores extremos del rango, y la proporción entre cada elemento en el rango, llamada razón.
Si tienes oxidada tus matemáticas, repásalas... busca progresiones aritméticas y progresiones geométricas...

Entonces decidamos cuantos niveles de dificultad queremos tener?. ¿3, 4, 5, 6, 7?. Supongamos 5. Entonces lo primero es crear la serie. Luego esto se fija en un array. el array lo que va a contener será el número de pistas donde comienza ese nivel de dificultad...
Por ejemplo si la serie fuera aritmetica y la razón 5, el array NivDificultad podría tener estos valores.
NivDificultad(0) = 17
NivDificultad(1) = 23
NivDificultad(2) = 29
NivDificultad(3) = 35
NivDificultad(4) = 41
NivDificultad(5) = 47 // este no entra en nivel, es el punto límite.

Entonces si está en el nivel 0 (el más difícil, aunque puede invertirse el número y el más alto expresar más dificultad), se elige una cantidad entre:
NivDificultad(0) y NivDificultad(1)-1
...es decir si elige al azar un número entre 17 y 22
Si nivel 1 entre 23 y 28, etc...

pero... pero hemos elegido una progresión geométrica... Así que cada grupo no tendrá la misma cantidad de valores, pero el enfoque del array y su uso, es el mismo.

Código:
Array Byte = Funcion InterpolacionGeom(Niveles, Minimo, Maximo)
    Decimal Razon, n, p //números con decimales.
    Array Byte Im(0 a Niveles) //Uno más, para guardar el valor final

    razon = RazonGeometrica(Maximo, Minimo, Niveles-1)

    Im(k) = Minimo
    p = im(0)
    Bucle para k desde 1 hasta Niveles-1
       n = p   // Im(k-1) //ídem d elo que se comenta abajo, se pierde precisión y no se alcanza el valor máximo ni lo reparte bien.
       p = (n * razon)
       Im(k) = valor entero de p
       // im(k) = entero de (im(k - 1) * Razon)  
       //podría valer esto, que es una sola línea, pero perdemos precisión en cada iteración. El problema sería tanto mayor cuannto más ciclos tuviere el bucle.
    Fin bucle
    Im(Niveles) = Maximo  //si el código del bucle fue bien esta línea sería inenecesaria,
     //pero si los decimales varían uno arriba o abajo, esto lo fija al punto exacto.
    
    Devolver array Im
Fin Funcion

Generalmente, todos los lenguajes de programación disponen de raíz cuadrada, pero no de raíz cúbica, raíz cuarta ni raíz 125, etc...
Sin embargo, si poseen potenciación y la radicación se define como el inverso de las potencias, al igual que la división es el inverso de las multiplicaciones y la resta el inverso de la suma.
Esto es lo que hacemos aquí:
Código:
Decimal = Funcion RazonGeometrica(Maximo, minimo, Terminos) // terminos intermedios entre ambos extremos
   Devolver ((Maximo/Minimo) elevado a la (1/ (Terminos+1))
Fin Funcion

Una vez que imprimas el resultado del array devuelto, no te vas a sorprender mucho, porque son pocos niveles, también puedes fijar los valores del array 'manualmente', te evitas ambas funciones... pero dejas de aprender cosas.

Tu ya sabiendo que el usuario ha elegido x nivel, seleccionas al azar el número de pistas en cada partida:
NumPistas = Seleccional azar un valor entre( NivDificultad(Dificultad) y NivDificultad(Dificultad+1) -1 )

Y por hoy vale...

p.d.: Espón donde tengas dudas, para no dar vueltas a cosas que no pudierna interesarte e ir al grano.
« Última modificación: 15 Agosto 2017, 06:13 por NEBIRE » En línea

NEBIRE


Desconectado Desconectado

Mensajes: 576


Ver Perfil
Re: Codigo para crear SUDOKUS
« Respuesta #23 en: 15 Agosto 2017, 17:36 »

Tengo una mala noticia...

A pesar de que dicen que si hay más de x pistas, un sudoku solo tiene una solución, puedo demostrar que es falso... sin la necesidad de sesudas matemáticas, basta uno donde se demuestre que efectivamente tiene dos soluciones y x pistas.

En la siguiente imagen, se ve un sudoku correctamente resuelto:
Cada fila hay, bloque y columna cumple la condición. Sin embargo, no me lo da por bueno, si comparo el Sudoku que crea el usuario (en este caso yo), con la solución interna.

Marcado en rojo (y rodeado en azul a mano), las discrepancias que existen con la solución que se generó para el sudoku (en amarillo las pistas, que como se ve son 30ytantas.

En la solución 'real', donde pone 8 es 6 y donde pone 6 es 8 (en ambos casos). Sin embargo este mapa es legítimamente correcto, luego:
queda demostrado como falso
que exista una única solución posible,
cuando el número de pistas es superior a 17.



En consecuencia, es razonable que la solución se verifique no por comparación de la solución almacenada, si no por comprobación de todas las filas, columnas y bloques.

En algún punto hay que poner alguna función que permita al usuario pasar los valores que va marcando y podría ser algo como esto (yo he preferido una propiedad)

Código:
Byte = Propiedad Leer Valor(X, Y)
   n = ((Y * c_Nueve) + X)
   Devolver User(n)
Fin Propiedad

Propiedad Escribir Valor(X, Y, V)
        byte n
        TiposDeValor  t  //una enumeración para indicar al dibujar que tipo de tinta usar
        
        n = ((Y * c_Nueve) + X)
        Si (Pistas(n) = 0) luego  //Si la casilla es una pista, no se toca
            Si (User(n) = 0) luego  //la casilla está ocupada ya?
                Si (v > 0) luego ' que se llena
                    Faltas = (Faltas - 1)  //Descontamos una falta cuando se ingresa un valor, si antes estaba vacía.
                    t = VALOR_TIPO_USER  //la casilla tendrá un valor (1-9)
                Sino
                    t = VALOR_TIPO_VACIO // la casilla se dejará libre.
                Fin si
            Sino  // la casilla ya está ocupada, aquí se cambiará valor o se borrará.
                Si (v = 0) luego
                    Faltas += 1 // antes había un valor, ahora se borra, aumentan las faltas uno más...
                    t = VALOR_TIPO_VACIO // la casilla se dejará libre.
                Sino
                    t = VALOR_TIPO_USER  // se remplaza el valor actual por otro.
                Fin si
            Fin si
            
            User(n) = v  //Asignamos el valor recibido
            
            //valor, casilla(x,y), tipo de tinta a usar
            Disparar Evento DibujarValor(v, X, Y, t)  
            
            Si (Faltas = 0) luego  // Solo se verifica el sudoku, cuando se hayan entrado todos los valores.
                Si (VerificarSudoku = True) luego                    
                    Disparar Evento FinDePartida(True) //True, porqueel mismo evento con False, puede usarse si el usuario decide Resetear la partida.
                Fin si
            Fin si
        Fin si
    Fin Propiedad



Ésta (la siguiente) es una función intermedia, que llama a una u otra para verificar si la solución es corecta, visto lo visto (verificado que NO SIEMPRE existe una UNICA solución), es preferible descartarla e  invocar siempre a  ValidarSolucionMultiple. Y en consecuencia no e spreciso mantener en memoria el array de la solución una vez generado y obtenido las pistas (dicho de otro modo, dicho array podría ser reutilizado para las pistas, eso al gusto)
Código:
Buleano = Funcion VerificarSudoku
    Si  (SolucionUnica = True) luego
        VerificarSudoku = ValidarSolucionSimple
    Sino
        VerificarSudoku = ValidarSolucionMultiple
    Fin si
Fin Funcion

Como decía más arriba:
En consecuencia, es razonable que la solución se verifique no por comparación de la solución almacenada, si no por comprobación de todas las filas, columnas y bloques.
« Última modificación: 15 Agosto 2017, 17:39 por NEBIRE » En línea

Páginas: 1 2 [3] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Código para crear un Sniffer
Programación General
hackballi 4 7,232 Último mensaje 31 Mayo 2005, 19:35
por pepel
CODIGO PARA CREAR UN CALENDARIO
Desarrollo Web
dardman 1 644 Último mensaje 14 Septiembre 2006, 18:50
por Morris
codigo sencillo para crear combo box
Programación C/C++
DJINVACION2005 3 1,961 Último mensaje 20 Junio 2008, 00:16
por Flakito81
ayuda para crear un codigo
Programación C/C++
carwen 2 1,505 Último mensaje 22 Octubre 2011, 02:34
por carwen
Codigo Rxbot para crear botnet
Hacking Avanzado
isigr 0 1,066 Último mensaje 30 Enero 2013, 08:05
por isigr
Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines