Serie ficheros virtuales

 

javascript ficheros virtuales

 

Cuadrados mágicos y Sudokus

  1 Introducción

  2 Cuadrados latinos y mágicos

  3 Algoritmo para construir cuadrados mágicos

  4 Sudokus

  5 Resumen del procedimiento sudoku

  6 Ejemplo de paso de los sudokus triviales a los usuales

  7 La estructura de soporte

  8 Funciones de conversión de longitud fija

  9 Implementación de la biblioteca de servicios “sudoku_ficherosvirtuales_com”

  10 Interfaz de presentación

  11 Código fuente

 

                                                                                                          ________

1 Introducción

 Este capítulo se dedicará a desarrollar un programa de generación de cuadrados latinos, cuadrados mágicos y sudokus en javascript, siguiendo los pasos de la implementación para C ANSI presentada en el capítulo homónimo del blog base.

 Concretamente, en los siguientes epígrafes de este capítulo presentaremos la definición de cuadrados latinos y mágicos con ejemplos y métodos para construirlos, a continuación contemplaremos los sudokus presentando ejemplos e introduciendo métodos para construirlos partiendo de un cuadrado latino y luego acometeremos su implementación, así se definirá una base de datos virtual que servirá de soporte del código para generar cuadrados latinos, al que le agregaremos la codificación de replicación que genera sudokus triviales y el código de transformación para obtener los sudokus no triviales. Esta codificación se escribió anteriormente en C ANSI y en VBA y ahora la traduciremos a javascript.

 El modulo central se codificará como una biblioteca de servicios que hereda su código del SRmagic original y que luego se utilizaran como soporte para presentar un ciclo continuo de autogeneración de sudokus en una esquina del sitio ficherosvirtuales.com; la presentación heredará las hojas de estilo del desarrollo en VBA para excell citado.

 Aquí se presentará una codificación extractada centrada en el propósito de mostrar la conversión de los desarrollos originales a javascript.

                                                                                                           ________

2 Cuadrados latinos y mágicos

 

 Un cuadrado latino es una matriz  N * N, en la cual los enteros  1, 2, .. N^2 aparecen todos exactamente una vez.

 Un cuadrado mágico es un cuadrado latino con N impar en el que todas las filas, columnas y diagonales principales suman lo mismo.

 

 Veamos un ejemplo

 


 


 

 


Y un ejemplo extremo

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Si se prescinde de la propiedad de la igualdad de suma para las diagonales tendríamos ejemplos de cuadrados latinos como los siguientes

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

o en el ejemplo extremo    

 


  
                                                                                                         
________

 3 Algoritmo para construir cuadrados mágicos

  

Un algoritmo para construir un cuadrado mágico es el siguiente

 

  Se coloca 1 en el medio de la fila superior

 

  Después de colocar el entero K (K=1,2,...,N*N), hay que moverse una fila hacia arriba y una columna hacia la derecha para colocar el siguiente entero K+1

 

 

 Esta regla general tiene las siguientes excepciones de desbordamiento:

 

  Si un movimiento lleva por encima de la primera fila, hay que colocar K+1 abajo del todo de la columna destino

  Si un movimiento se sale por la derecha, hay que colocar K+1 en esa fila por la izquierda

 

 

Por último, si un movimiento lleva a una celda ya ocupada o si el movimiento se sale por arriba y por la derecha, K+1 se coloca justo debajo de donde estuviera K

 

                                                                                                          ________

 

4 Sudokus

Un sudoku es una matriz  N * N, con N = n * n y n impar, en la cual los enteros  1, 2, .. N aparecen todos exactamente una vez en cada fila y en cada columna y en cada subcubo n * n.

 

Veamos un ejemplo de tamaño N = 9 = 3*3:



 


 

 

  Y uno de 25:

 


 

Con la aplicación de ficheros virtuales la resolución del problema del cuadrado mágico origen es tan sencilla como con series de un tamaño dado, pero permite su extensión a problemas ampliados como el del sudoku de una forma natural.

 

                                                                                                          ________

 

 

5 Resumen del procedimiento sudoku

 

El procedimiento se resume en  los siguientes pasos:

 

                                                                         __

1) Construir un cuadrado latino de tamaño n = \/ N, esto es una matriz  n * n, en la cual los enteros 1, 2, … n * n aparecen todos exactamente una vez.

 

 

2) Expandirlo a un sudoku trivial, desplegando filas y columnas y evitando repeticiones, siguiendo el siguiente esquema, del que más adelante se presenta un ejemplo detallado:

 

    La expansión de arriba abajo despliega las columnas empezando por ejemplo por la nº 2 y colocándola debajo de la nº 1, la 3 debajo de la 2, la N bajo la N-1 y por último la 1 bajo la N.

     

    La expansión de izquierda a derecha sigue un mecanismo similar pero para las filas, así, se toma  la 1ª y se coloca a continuación de la 2ª, etc.

 

 

3) Transformar el sudoku aplicando intercambios de parejas de cifras encolumnadas, comenzando un ciclo de intercambios entre las columnas y filas que mantengan bien la suma en filas, o bien la de columnas, y que acabe al reencontrar la posición de partida, consiguiéndose un sudoku equivalente pero con cifras distintas de las de partida.

 

Veámoslo con un ejemplo numérico de transformación de filas:

 

 

Punto de partida:             2  7  9    8  4  5    1  3  6       Suma  45

                                       4  5  8    3  6  1    7  9  2                  45

 

 

Ciclo de progreso mediante permutaciones que mantienen la suma por columna, buscando una combinación con las mismas sumas por filas de partida, expulsando en cada paso la repetición que se crea hasta que deja de producirse:

 

                                       4  7  9    8  4  5    1  3  6      Suma   47

                                       2  5  8    3  6  1    7  9  2                  43

 

                                       4  7  9    8  6  5    1  3  6      Suma  49

                                       2  5  8    3  4  1    7  9  2                 41

 

                                       4  7  9    8  6  5    1  3  6       Suma  49

                                       2  5  8    3  4  1    7  9  2                  41

 

Punto final:

                                       4  7  9    8  6  5    1  3  2       Suma  45

                                       2  5  8    3  4  1    7  9  6                  45

 

 

Por tanto hemos pasado de:

 

                                       2  7  9   8  4  5    1  3  6        Suma  45

                                       4  5  8    3  6  1    7  9  2                  45

                                  a:

                                       4  7  9    8  6  5    1  3  2       Suma  45 

                                       2  5  8    3  4  1    7  9  6                  45

 

 

proceso con el que vamos rompiendo poco a poco la fácil predicción de las cifras de partida.

 

El ciclo de búsqueda es cerrado debido a las restricciones de unicidad en filas y columnas, lo que garantiza que si se parte de una cifra, se acabará alcanzando en la otra fila la misma cifra en una columna distinta.

 

4) Revisar el sudoku obtenido y rechazar alternativamente los que presenten parejas repetidas en filas o columnas posteriores, pues de conocerse a priori que no se eluden son de fácil predicción.  

    En las implementaciones en lenguajes compilados este punto puede implementarse directamente por su rapidez. En los lenguajes interpretados como VBA para excell o en javascript debe incluirse un mecanismo de tope temporal para evitar bucles aparentes y la detención del módulo por el navegador.

 

   Se rechazarían normalmente entonces resultados parciales como los siguientes:

  6  5  1    2  3  8

 2  3  7    4  5  9   . . .

 9  4  8    7  1  6

 

   ó

 

  6  5  1

 2  3  7     

 9    4  8  

 

 1  3  4

 6  7

 5    2  9 

 . . .

 

                                                                                                          ________

 

 

6 Ejemplo de paso de los sudokus y seudosudokus triviales a los usuales

 

Partiendo de la implementación inicial se puede agregar algo más de código al programa base y desarrollar el punto 2 del procedimiento que se acaba de indicar obteniendo un generador de SUDOKUS triviales como en la figura que se muestra, de tamaño base 3 y de presentación 3^2=9:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Conseguido mediante la replicación de cada subfila y cada subcolumna de un cuadrado latino base. En nuestro caso se ha replicado como sigue

 

Se toma el cuadrado latino base

 

        4  9  2

    8    1  6

    3    5  7

 

Se replica como primera fila una cualquiera de las filas distinta de la primera

 

        4  9  2      3  5  7

    8    1  6     

    3    5  7

 

Se toma como segunda fila una de las otras dos restantes

 

        4  9  2      3  5  7

        8  1  6      4  9  2

    3    5  7

 

Termina la replicación del segundo cuadrado añadiendo la fila final que queda

 

        4  9  2      3  5  7

        8  1  6      4  9  2

    3  5  7      8  1  6

 

Para el tercer cuadrado se toman las filas que completan la replicación

 

        4  9  2      3  5  7     8  1  6

        8  1  6      4  9  2     3  5  7

    3  5  7      8  1  6     4  9  2

 

 La replicación puede continuar de la misma forma por columnas hasta completar el desarrollo. Se trata por construcción de un sudoku pero su adivinación es inmediata.

Para evolucionar a un sudoku usual hay que aplicar transformaciones de intercambio de ítems particulares que mantengan las condiciones globales que se han indicado antes.

En el programa se implementará el desarrollo de un cuadrado latino para lograr un sudoku trivial de partida utilizando los métodos que se acaban de comentar y a continuación se le aplicará una transformación de intercambio de parejas, aceptándose el resultado si el sudoku resultante no es del tipo fácil que se ha mostrado, repitiéndose las transformaciones de intercambio de parejas mientras sea preciso.

                                                                                                          ________

 

 

El siguiente tamaño adecuado para un sudoku completo sería 5, de presentación 25, como en la imagen que sigue en donde ya se ha aplicado la transformación.

 


 


  

Si la pantalla no permite alcanzar el siguiente tamaño de base 7, que se expandiría a 49 columnas, se pueden construir seudo sudokus como el que se muestra a continuación


 


 

en donde se conjugan 3 cuadrados seudomágicos en vez de los 7 necesarios por falta de espacio en pantalla


                                                                                                         
________

7 La estructura de soporte

La estructura de soporte del fichero virtual base del desarrollo es una transcripción de la utilizada en el desarrollo en C ANSI.

 

Consiste en un soporte de clave para las celdas(i,j), su valor k = 1 ... N y estado visual a = 0/1 activo así como perspectivas lógicas para facilitar la extracción de las celdas activas y desactivas, llevada a cabo como sigue:

 

 

      // Estructura del formato de registro del fichero de soporte del sudoku

      //          0         1         2         3         4         5         6         7

      //          0123456789012345678901234567890123456789012345678901234567890123456789012  Base 0

      //                   1         2         3         4         5         6         7

      //          1234567890123456789012345678901234567890123456789012345678901234567890123  Base 1

 

      var aDS0 = "0000000000000000000000000000000000000000000000000000000000000000000000000"; // Item nulo

     

              // "1000000001100000000111000000001100000000121000000001100000000110000000011"; // Item muestra

              //           i         ja(1=D,2=A)i         jd(2=D,1=A)i         j         ka(0=Desactivo,1=Activo)

              //          10        101        10        101        10        10        10

              //  ------------------20-------------------21-------------------21---------11 Longitud total: 73

 

 

Esta estructura se concreta en objetos auxiliares que implementan métodos de conversión directa e inversa a String de forma que puedan compararse y ordenarse.

 

     

      var aDSc = [" "];             // Work paso de datos en formato alfanumérico

      var DSc = new KD(0, 0, 0, 0); // Work paso de datos en formato objeto

 

                                                                                                          ________

 

 

La función objeto asociada se define como sigue:

     

 

      // Ds del fichero de soporte del sudoku

     

      function KD(i, j, k, a)

{

     

            // Definición C original

           

            //static struct sDsKD

            //{

            // struct sDsK DK;     // Clave principal

            // struct sDsK01 DK01; // Clave activos-desactivos

            // struct sDsK02 DK02; // Clave desactivos-activos

            // struct sDsD DD;     // Datos

            //}

                                                                                                          ________

           

           

            // Ds de claves del fichero de soporte del sudoku

           

           

            // Clave principal (i,j)

           

            function K(i, j)

            {

           

                  // Definición C original

                 

                  //struct sDsK   // Estructura de claves de acceso a nodos (i,j)

                  //{

                  // long li;     // Indice i del nodo

                  // long lj;     // Indice j del nodo

                  //};    

                 

                 

                  // Funciones de conversión asociadas

                 

                 

                  // K --> toString

                 

                  function toString()

                  {

                        var ci = " ";  // Paso de clave i

                        var cj = " ";  // Paso de clave j

                        var cij = " "; // Paso de clave ij. Valor de retorno

     

                 

                        // Construye conversión de clave a string normalizado de longitud fija

                       

                        ci = SRRCAL_lLexi(this.i); // (Ver epígrafe siguiente)

                        cj = SRRCAL_lLexi(this.j);

                        cij = ci + cj;

                       

                        return cij;

                  }

                 

                 

                  // Recíproco

                 

                  function Parse(cK)

                  {

                        var ci = " "; // Paso de clave i

                        var cj = " "; // Paso de clave j

                 

                        ci = cK.substr(0, 10);

                        this.i = SRRCAL_lLexiR(ci);

                       

                        cj = cK.substr(10, 10);

                        this.j = SRRCAL_lLexiR(cj);

                       

                        return;

                  }

                 

                 

                  // Definición de objeto clave principal

                 

                  this.i = i;

                  this.j = j;

                  this.toString = toString;

                  this.Parse = Parse;

                 

                  return;

            }

                                                                                                          ________

           

           

            // Ds de claves para conteo de activos-desactivos

           

            function K01(a, i, j)

            {

           

                  // Definición C original

                 

                  //struct sDsK01 // Estructura de claves activo-desactivos

                  //{

                  // long a;      // 1=Desactivo, 2=Visualmente activo

                  // long li;     // Indice i del nodo

                  // long lj;     // Indice j del nodo

                  //};

                 

                 

                  // Funciones de conversión asociadas

                 

                  // K01 --> toString

                 

                  function toString()

                  {

                        var ci = " ";   // Paso de clave i

                        var cj = " ";   // Paso de clave j

                        var cij = " ";  // Paso de clave ij

                        var caij = " "; // Valor de retorno

                 

                 

                        // Construye conversión de clave a string normalizado

                       

                        ci = SRRCAL_lLexi(this.i);

                        cj = SRRCAL_lLexi(this.j);

                        cij = ci + cj;

                        caij = this.a + cij;

                       

                        return caij;

                  }

                 

                 

                  // Reciproco

                 

                  function Parse(cK01)

                  {

                        var ci = " "; // Paso de clave i

                        var cj = " "; // Paso de clave j

 

                        this.a = cK01.substr(0, 1);

                       

                        ci = cK01.substr(1, 10);

                        this.i = SRRCAL_lLexiR(ci);

                       

                        cj = cK01.substr(11, 10);

                        this.j = SRRCAL_lLexiR(cj);

                       

                        return;

                  }

                 

                 

                  // Definición de objeto clave activo-desactivos

                 

                  if (a == "0") this.a = "1";  // K01: 1=Desactivo, 2=Visualmente activo

                  else          this.a = "2";

                  this.i = i;

                  this.j = j;

                  this.toString = toString;

                  this.Parse = Parse;

                 

                  return;

            }

 

                                                                                                          ________

           

           

            // Ds de claves para conteo de desactivos-activos

           

            function K02(a, i, j)

            {

           

                  // Definición C original

                 

                  //struct sDsK02 // Estructura de claves desactivos-activos

                  //{

                  // long a;      // 1=Visualmente activo, 2=Desactivado

                  // long li;     // Indice i del nodo

                  // long lj;     // Indice j del nodo

                  // char cEOF;   // Marca EOF

                  //};    

                 

                 

                  // Funciones de conversión asociadas

                 

                  // K02 --> String

                 

                  function toString()

                  {

                        var ci = " ";   // Paso de clave i

                        var cj = " ";   // Paso de clave j

                        var cij = " ";  // Paso de clave ij

                        var caij = " "; // Valor de retorno

                 

                 

                        // Construye conversión de clave a string normalizado

                       

                        ci = SRRCAL_lLexi(this.i);

                        cj = SRRCAL_lLexi(this.j);

                        cij = ci + cj;

                        caij = this.a + cij;

                       

                        return caij;

                  }

                 

                 

                  // Reciproco

                 

                  function Parse(cK02)

                  {

                        var ci = " "; // Paso de clave i

                        var cj = " "; // Paso de clave j

                 

                        this.a = cK02.substr(0, 1);

                       

                        ci = cK02.substr(1, 10);

                        this.i = SRRCAL_lLexiR(ci);

                       

                        cj = cK02.substr(11, 10);

                        this.j = SRRCAL_lLexiR(cj);

                       

                        return;

                  }

                 

                 

                  // Definición de objeto clave activo-desactivos

                 

                  if (a == "0") this.a = "2"; // K02: 1=Visualmente activo, 2=Desactivado

                  else          this.a = "1";

                  this.i = i;

                  this.j = j;

                  this.toString = toString;

                  this.Parse = Parse;

                 

                  return;

            }

                                                                                                          ________

           

            // Ds de datos del fichero de soporte del cuadrado

           

            function D(k, a)

            {

           

                  // Definición C original

                 

                  //struct sDsD   // Estructura de datos asociados

                  //{

                  // long lk;     // Valor de k del nodo

                  // short int a; // 0,1 Visualmente activo

                  //}; 

                 

                 

                  // Funciones de conversión asociadas

                 

                  // D --> String

                 

                  function toString()

                  {

                        var ck = " ";  // Paso de dato k

                        var cka = " "; // Valor de retorno

                       

                        // Construye conversión de datos a string normalizado

                       

                        ck = SRRCAL_lLexi(this.k);

                        cka = ck + this.a;

                       

                        return cka;

                  }

                 

                 

                  // Reciproco

                 

                  function Parse(cD)

                  {

                        var ck = " "; // Paso de importe k

                       

                        ck = cD.substr(0, 10);

                        this.k = SRRCAL_lLexiR(ck);

                       

                        this.a = cD.substr(10, 1);

                       

                        return;

                  }

                 

                 

                  // Definicion de objeto datos

                 

                  this.k = k;

                  this.a = a;

                  this.toString = toString;

                  this.Parse = Parse;

                 

                  return;

            }

           

           

            // Funciones de conversión asociadas    

           

            // KD --> String

           

            function toString()

            {

                  var cKD = " ";    // Valor de retorno

                 

                  var cK = " ";     // Paso de KD.K

                  var sK = new K(this.K.i, this.K.j);

                       

                  var cK01 = " "; // Paso de KD.K01

                  var sK01 = new K01(this.D.a, this.K01.i, this.K01.j);

               

                  var cK02 = " "; // Paso de KD.K02

                  var sK02 = new K02(this.D.a, this.K02.i, this.K02.j);

               

                  var cD = " ";   // Paso de KD.D

                  var sD = new D(this.D.k, this.D.a);

 

                  cK   = sK.toString();

                  cK01 = sK01.toString();

                  cK02 = sK02.toString();

                  cD   = sD.toString();

                 

                  cKD  = cK + cK01 + cK02 + cD;

                 

                  return cKD;

            }

           

           

            // Recíproco

           

            function Parse(cKD)

            {

                  var cK = " ";     // Paso de KD.K

                  var sK = new K();

                       

                  var cK01 = " "; // Paso de KD.K01

                  var sK01 = new K01();

               

                  var cK02 = " "; // Paso de KD.K02

                  var sK02 = new K02();

               

                  var cD = " ";   // Paso de KD.D

                  var sD = new D();

           

                  cK = cKD.substr(0, 20);

                  sK.Parse(cK);

                 

                  cK01 = cKD.substr(20, 21);

                  sK01.Parse(cK01);

                 

                  cK02 = cKD.substr(41, 21);

                  sK02.Parse(cK02);

                 

                  cD = cKD.substr(62, 11);

                  sD.Parse(cD);

                 

                 

                  this.K.i = sK.i;

                  this.K.j = sK.j;

                 

                  this.K01.a = sK01.a;

                  this.K01.i = sK01.i;

                  this.K01.j = sK01.j;

                 

                  this.K02.a = sK02.a;

                  this.K02.i = sK02.i;

                  this.K02.j = sK02.j;

                 

                  this.D.k = sD.k;

                  this.D.a = sD.a;

                 

                  return;

            }

           

                                                                                                          ________

           

 

 

        // Definición de objeto estructura de registro completo

 

        this.K = K;

        this.K01 = K01;

        this.K02 = K02;

        this.D = D;

       

        this.toString = toString;

        this.Parse = Parse;

 

        var sK   = new K(i, j);

        var sK01 = new K01(a, i, j);

        var sK02 = new K02(a, i, j);

        var sD   = new D(k, a);

 

        this.K.i = sK.i;

        this.K.j = sK.j;

                 

        this.K01.a = sK01.a;

        this.K01.i = sK01.i;

        this.K01.j = sK01.j;

                 

        this.K02.a = sK02.a;

        this.K02.i = sK02.i;

        this.K02.j = sK02.j;

                 

        this.D.k = sD.k;

        this.D.a = sD.a;

           

           

        return;

      }

     

                                                                                                          ________

 

8 Funciones de conversión de longitud fija

 

Para poder comparar los objetos auxiliares que emulan a las celdas del cuadrado, se precisan métodos de conversión directa e inversa a String de forma que puedan compararse y ordenarse utilizando los propios métodos String.

 

Para facilitar esta tarea, se introducen las funciones de conversión alfanumérica de longitud fija que siguen

 

     

      // Conversor de clave a formato alfanumérico

     

      function SRRCAL_lLexi(Num)

{

            var lKTE = 1000000000; // Constante de normalización para long's

            var AlfaNum = " ";     // Valor de retorno

 

            AlfaNum = lKTE + Num + "";

            return AlfaNum;

      }

 

 

     

      // Conversor reciproco

     

      function SRRCAL_lLexiR(AlfaNum)

{

            var lKTE = 1000000000; // Constante de normalización para long's

            var Num = 0;           // Valor de retorno

 

            Num = parseInt(AlfaNum) - lKTE;

            return Num;

      }

                                                                                                          ________

 

 

9 Implementación de la biblioteca de servicios “sudoku_ficherosvirtuales_com”

 Para codificar la implementación en javascript primero se ha convertido el código C ANSI “SRmagic” original de la serie de la manera expuesta anteriormente, y luego se ha encapsulado siguiendo lo indicado en el capítulo previo.

 Tras estos pasos resulta una biblioteca de servicios en javascript donde se exportan los métodos relacionados al final del módulo como “this.método”. En estas bibliotecas, cada método exportado se ha codificado previamente como función resultante de traducir la colección de funciones del programa de servicio original.

 

 Veamos ahora un extracto del procedimiento seguido tomando como ejemplo el método SRmagic.open:

 

function sudoku_ficherosvirtuales_com()

{

      //------------------------------------------------------------------------------

      // Variables globales

      //------------------------------------------------------------------------------

     

      var w = new w_ficherosvirtuales_com();

     

      . . .

 

 

//-----------------------------------------------------------------------------

// Procedimientos internos

//-----------------------------------------------------------------------------

     

      . . .

 

//-----------------------------------------------------------------------------

// Procedimientos soporte de miembros exportados

//-----------------------------------------------------------------------------

 

( Se presenta ahora el código completo de la función “SRmagic_Open” que luego se exporta como método  [this.] “Open”  al final del módulo)

 

//-----------------------------------------------------------------------------

      // SRmagic_Open: Apertura de proceso

      //

      //

      // A invocar en la carga de una aplicación que utilice sudoku_ficherosvirtuales_com

      //

      //

      // Precondición: Ninguna

      //

      // Postcondición:

      //

      //  Se crean los ficheros virtuales soporte de proceso. Si ya existieran se inicializan

      //

      //  Los ficheros son

      //

      //  "PMAGIC" Matriz del sudoku definido segun la estructura KD

      //  

      //  "PMAGIC01" Logico por activo-desactivos para facilitar conteos

      //   El representante DSc se utiliza como parámetro de paso

      //

      //  "PMAGICP" Vector de soporte de evaluación de parejas para

      //   determinar si el sudoku generado es fácil o difícil

      //

      //  "PMAGICR" Vector de soporte de muestreo sin repetición de n elementos

      //  

      // Parametros: Ninguno

      //

      // Retorno: Identificador (NID) del fichero PMAGICR generado

      //          Se utiliza como discriminante

      //          Si es nulo indica error de generación por memoria agotada

      //         

      //-----------------------------------------------------------------------------

      function SRmagic_Open()

      {

            var lNID = 0;   // Retorno. Nid asignado a fichero PMAGICR

            var lNID01 = 0; // Nid asignado a fichero PMAGIC01

            var lNID02 = 0; // Nid asignado a fichero PMAGIC02

           

           

            // Filtro

           

            lNID = w.NID("PMAGICR");

            if (lNID) return lNID;

           

           

           

            // Crea ficheros virtuales de soporte

           

            // Estructura del formato de registro del fichero de soporte del sudoku

            //  0         1         2         3         4         5         6         7

            //  0123456789012345678901234567890123456789012345678901234567890123456789012

            //           1         2         3         4         5         6         7

            //  1234567890123456789012345678901234567890123456789012345678901234567890123

            // "0000000000000000000000000000000000000000000000000000000000000000000000000"; // Item nulo

            // "1000000001100000000111000000001100000000121000000001100000000110000000011"; // Item muestra

            //           i         ja(1=D,2=A)i         jd(2=D,1=A)i         j         ka(0=D,1=A)

            //          10        101        10        101        10        10        10

            //                    20                   21                   21         11 T:73

           

           

            // Inicia un nuevo fichero virtual de soporte principal,

           

            lNID = w.NEW("PMAGIC", 20, 73);

           

           

            // su lógico por activo-desactivos,

           

            lNID01 = w.CRTLF("PMAGIC01", "PMAGIC", 21, 21);

           

           

            // y su lógico por desactivo-activos

           

            lNID02 = w.CRTLF("PMAGIC02", "PMAGIC", 42, 21);

           

           

            // Inicia un nuevo fichero virtual de soporte de evaluación de parejas

            // para determinar si el sudoku resultante es fácil o difícil

           

            lNID = w.NEW("PMAGICP", 20);

           

           

            // Inicia un nuevo fichero virtual de soporte aleatorio sin repetición

           

            lNID = w.NEW("PMAGICR", 10);

           

           

            return lNID;

      }

     

      . . .

 

 

     

      // Miembros de sudoku_ficherosvirtuales_com exportados

     

      this.Open  = SRmagic_Open;

      this.Close = SRmagic_Close;

     

      this.lLexi  = SRRCAL_lLexi;

      this.lLexiR = SRRCAL_lLexiR;

     

      this.Activar      = SRmagic_Activar;

      this.ActivarTodas = SRmagic_ActivarTodas;

      this.Chain        = SRmagic_Chain;

      this.DesActivar   = SRmagic_DesActivar;

     

      this.Gen = SRmagic_Gen;

     

      this.NumActivas        = SRmagic_NumActivas;

      this.NumActivasColumna = SRmagic_NumActivasColumna;

      this.NumActivasFila    = SRmagic_NumActivasFila;

      this.NumDesactivas     = SRmagic_NumDesactivas;

     

      this.RandCuadrado = SRmagic_RandCuadrado;

      this.RandImpar    = SRmagic_RandImpar;

      this.Random       = SRmagic_Random;

     

      this.Read          = SRmagic_Read;

      this.ReadActiva    = SRmagic_ReadActiva;

      this.ReadDesActiva = SRmagic_ReadDesactiva;

     

      this.SumaColumna = SRmagic_SumaColumna;

      this.SumaFila    = SRmagic_SumaFila;

     

      this.VerActiva = SRmagic_VerActiva;

     

      return;

}

 

                                                                                                          ________

 

 El nombre de la biblioteca sigue el convenio de nombre de dominio invertido sudoku_ficherosvirtuales_com para garantizar la unicidad.

 

 El desarrollo del interfaz de presentación en pantalla de no sigue este estricto convenio con sus propias funciones, puesto que se trata de un desarrollo más específico, y se conforma con anteponer el prefijo SK, como abreviatura de SUDOKU, para evitar la colisión con otros desarrollos del mismo interfaz de pantalla.

 

                                                                                                          ________

 

10 Interfaz de presentación

 
En el blog hermano VBA Ficheros virtuales se implementó una versión para excell del programa para generar cuadrados mágicos y sodokus, con los servicios centrales de generación  implementados como complemento excell y la presentación visual dejándola de cuenta de una hoja como la siguiente

 

 

Si utilizamos en esta hoja la opción de salvar como página web podemos copiar las instrucciones css para poder reproducir la presentación en un desarrollo javascript dinámico.

 

 

De hecho, en el sitio web principal de la serie se presenta un sudoku animado en la esquina superior izquierda con un resultado gráfico como sigue:

 

 

 

 

 

El código css resultante asociado se puede consultar en el epígrafe final del capítulo dedicado al código fuente.

 

 

En cuanto al propio código del interfaz, se divide en dos partes. La primera se asocia a un frame padre auxiliar oculto y en ella radica la generación de los sudokus y el repositorio de datos utilizando ficheros virtuales. La segunda gestiona la presentación alimentándose de los datos almacenados en el frame padre. Aquí presentaremos el código principal, al final del capítulo se puede enlazar al conjunto del código.

 

                                                                                                          ________

 

 

El código html de la carga principal consta de dos partes sencillas. Primero la estructura de marcos principal: AutoMagic.html

 

 

<HTML>

 

<SCRIPT LANGUAGE="Javascript" SRC="w_ficherosvirtuales_com.js"></SCRIPT>        [soporte de ficheros virtuales para paso de datos]

<SCRIPT LANGUAGE="Javascript" SRC="sudoku_ficherosvirtuales_com.js"></SCRIPT>   [soporte de servicios sudoku]

<SCRIPT LANGUAGE="Javascript" SRC="AutoMagic.js"></SCRIPT>                      [parte de programación de cabecera]

 

<HEAD>

<TITLE>Sudoku Ficheros Virtuales</TITLE>

</HEAD>

 

<FRAMESET id="AutoCabecera" COLS="300, *">   

 

  <FRAME SRC="AutoMagic_Izquierda.html" NAME="Izquierda" MARGINWIDTH="7" MARGINHEIGTH="7" scrolling="no">  [Esta parte ejecuta la programación]

 

  <FRAME SRC="Cabecera.html" NAME="Derecha" MARGINWIDTH="10" MARGINHEIGTH="0">                             [Esta parte es estática]

 

</FRAMESET>

 

 

</HTML>

 

                                                                                                          ________

 

 

El código que ejecuta la programación (AutoMagic_Izquierda.html) también es muy simple porque lo que hace es invocar la rutina de carga PrSKGeneracionAuto que genera la presentación final:

 

<HTML>

 

<SCRIPT LANGUAGE="Javascript" SRC="AutoMagic_Detalle.js"></SCRIPT>

 

<HEAD>

<TITLE>Magic Izquierda</TITLE>

 

<link rel="stylesheet" type="text/css" href="AutoMagic.css">

 

</HEAD>

 

<BODY BGCOLOR='#F0F8FF' onload='PrSKGeneracionAuto()'>

</BODY>

 

</HTML>

 

                                                                                                          ________

 

 

 

Ahora presentaremos la rutina principal del frame padre (AutoMagic.js):

 

 

// Variables globales

 

var s = new sudoku_ficherosvirtuales_com(); // Soporte generación Sudokus

var wSK = new w_ficherosvirtuales_com();    // Soporte infraestructura ficheros virtuales (Para paso de datos a la hoja hija)

 

 

//-------------------------------------------------------------------------------------

// Proceso Principal: PrSKGeneracion

//

// Descripcion: (Re)generación de Sudokus

//

// Parametros:

// (entrada)  N : Dimensión del sudoku

//

// Retorno:   Ninguno

// 

//-------------------------------------------------------------------------------------

function PrSKGeneracion(N)

{

 var C = 0;      // Cuenta_Sudokus

 var n = 0;      // sqrt(N)

 var m = 0;      // N/2

 var lResul = 0; // Control de resultados intermedios

 

 

 // Time inicial

 

 var DateIni = new Date();

 

 

 

 // (Re)generación de sudoku

 

 s.Open();

 

 s.Gen(1, N);

 

 PrSKGuardaN(N);

 

 

 

 // Actualiza contadores

 

 C = PrSKLeeCuentaSudokus();

 ++C;

 

 lResul = PrSKGuardaCuentaSudokus(C);

 

 lResul = PrSKGuardaCuentaIteraciones(0);

 

 

 

 // Salva celdas activas originales (Para poder pintarlas de azul)

 

 lResul = PrSKSalvaPMAGICO();

 

 

 

 // Time final

 

 var DateFin = new Date();

 

 

 

 // Graba DifTime

 

 lResul = PrSKGrabaDifTime("TOTAL", DateIni, DateFin);

 

 

 

 // Fin de proceso

 

 return;

}

                                                                                                          ________

 

 

El juego de detalle en AutoMagic_Detalle.js consta de dos procesos principales. El autoarranque que invoca la hoja de carga, y la evolución automática posterior.

 

La primera tiene el siguiente código

 

 

//-------------------------------------------------------------------------------------

// Proceso Principal: PrSKGeneracionAuto

//

// Descripcion: Generacion automatica de sudokus

//

//-------------------------------------------------------------------------------------

function PrSKGeneracionAuto()

{

 

 // Dimension dft Sudoku

 

 var N = 9;

 

 

 // Regeneracion

 

 parent.PrSKGeneracion(N);

 

 

 // AutoPresentacion

  

 clearTimeout(ID_Timeout_SKAutoMostrarResultados);

 ID_Timeout_SKAutoMostrarResultados = setTimeout("PrSKMostrarResultados()", 1000);

 

 

 return;

}

                                                                                                          ________

 

Que continua en

 

 

//-------------------------------------------------------------------------------------

// Funcion: PrSKMostrarResultados

//

// Descripcion: Pruebas de Magic. Presenta resultados

//

//-------------------------------------------------------------------------------------

function PrSKMostrarResultados()

{

       var lResul = 0; // Control de resultados intermedios

 

      

       // Lee parametros

      

       var N = parent.PrSKLeeN();

 

       var NActivas = parent.s.NumActivas(); // Num.celdas activas actual

      

 

 

       // Construye el documento de resultados a visualizar (Con autobucle de activaciones)

 

       document.writeln("<HTML>");

 

       document.writeln("<HEAD>");

            

       document.writeln("<TITLE>AutoMagicSudokus</TITLE>");

            

       document.writeln('<link rel="stylesheet" type="text/css" href="AutoMagic.css">');

            

       document.writeln("</HEAD>");

            

      

       document.writeln("<BODY onload='PrSKAutoActivar()'>");

            

       document.writeln("<" + "SCRIPT LANGUAGE='Javascript' SRC='AutoMagic_Detalle.js'><" + "/SCRIPT>");

            

       document.writeln("<a name='_top'></a>");

            

         

                   

       // Muestra Sudoku

            

       if (NActivas <= N * N - 1) PrSKMuestraSudoku(0); // Visible

       else                       PrSKMuestraSudoku(1); // Completo

            

 

 

       // Cierra el documento construido

      

       document.writeln("<BR>");

       document.writeln("</BODY>");

       document.writeln("<HTML>");

            

       document.close();

      

       return;

}

                                                                                                          ________

 

 

Aparecen dos nuevas rutinas. PrSKMuestraSudoku que presenta el sudoku construido y PrSKAutoActivar que va desvelando automáticamente las celdas ocultas. Con estas rutinas, cuyo detalle no se va a presentar aquí para evitar extendernos en exceso, se cerraría la codificación, que puede consultarse en detalle en el siguiente epígrafe.

 

                                                                                                          ________

 

 

11 Código fuente

 

 

A continuación se presentan los enlaces para consultar el detalle completo del código. Se indica entre paréntesis el formato de extensión original de los ficheros de código que se presentan:

 

 

Servicios de soporte de los ficheros virtuales : http://jsc.ficherosvirtuales.com/AutoMagic_Web/w_ficherosvirtuales_com(.js)

Servicios de soporte de sudokus . . . . . . .  : http://jsc.ficherosvirtuales.com/AutoMagic_Web/sudoku_ficherosvirtuales_com(.js)

 

Código de cabecera del interfaz de presentación: http://jsc.ficherosvirtuales.com/AutoMagic_Web/AutoMagic(.js)

Código de detalle del interfaz de presentación : http://jsc.ficherosvirtuales.com/AutoMagic_Web/AutoMagic_Detalle(.js)

 

Código de cabecera del control de temporizador : http://jsc.ficherosvirtuales.com/AutoMagic_Web/ControlTemporizador(.js)

Código de detalle del control de temporizador  : http://jsc.ficherosvirtuales.com/AutoMagic_Web/ControlTemporizador_Detalle(.js)

Hoja de estilo asociada . . . . . . . . . . .  : http://jsc.ficherosvirtuales.com/AutoMagic_Web/ControlTemporizador(.css)

 

Hoja html de prueba . . . . . . . . . . . . .  : http://jsc.ficherosvirtuales.com/AutoMagic_Web/AutoMagic(.html)

Hoja de estilo asociada . . . . . . . . . . .  : http://jsc.ficherosvirtuales.com/AutoMagic_Web/AutoMagic(.css)

 

Hoja frame izquierda  . . . . . . . . . . . .  : http://jsc.ficherosvirtuales.com/AutoMagic_Web/AutoMagic_Izquierda(.html)

Hoja frame derecha  . . . . . . . . . . . . .  : http://jsc.ficherosvirtuales.com/AutoMagic_Web/Cabecera(.html)

Hoja de estilo asociada . . . . . . . . . . .  : http://jsc.ficherosvirtuales.com/AutoMagic_Web/Cabecera(.css)

 

 

 

 

                                                                                                          ________