Serie ficheros virtuales 

 

 

C Ficheros Virtuales

 

 

 

A.II Ejemplos

 

 

A.II.2 El juego de la vida

 

A.II.2.0 Introducción

A.II.2.1 Reglas del juego de la vida de Jhon H.Conway

A.II.2.2 Definición de la estructura de soporte de la implementación

A.II.2.3 Implementación de la evolución generacional

A.II.2.4 Implementación de controles de visualización

 

                                                                                                       ________           

                                                                       

A.II.2.0 Introducción

 

Este capítulo se dedicará a desarrollar un programa de generación de poblaciones de autómatas celulares bajo la reglas del juego de la vida de Jhon H.Conway

 

Se comenzará introduciendo las reglas del juego y a continuación se definirá una base de datos virtual para su implementación.

 

La implementación se llevará a cabo para un programa de pantalla MsVisual C++ 6.

 

En la segunda zona del libro se sintetizará la programación en una DLL que servirá para esta pantalla y para el modelo COM y NET, posteriormente  se desarrollarán interfaces en Visual Basic Net.

 

Se presentará una codificación extractada que se retomará posteriormente haciéndola evolucionar hacia la segregación de servicios en la DLL SRjvida y su presentación posterior en pantallas que utilicen los modelos MsC++6, COM o NET.

 

Se sigue pues el principio base establecido en el capítulo anterior: Base de datos, algorítmica, codificación núcleo que se sintetizará en los servicios de una DLL, y codificación de los interfaces de presentación.

 

                                                                                                      ________


 

A.II.2.1 Reglas del juego de la vida de Jhon H.Conway

 

Estas reglas, inventadas por John H.Conway, modelan la vida de una sociedad de autómatas celulares del plano.

 

 

Para el modelado, hay que tener en cuenta que cada celda del plano puede contener un organismo y que cada celda tiene ocho vecinas que la rodean.

 

 

En cada generación los nacimientos y muertes siguen unas sencillas reglas:

 

·      Un organismo nace en cualquier celda vacía que tenga exactamente 3 vecinos

·      Un organismo muere por aislamiento si tiene menos de 2 vecinos

·      Un organismo muere por superpoblación si tiene más de 3 vecinos

·      El resto de celdas no se modifica

 

 

 

 

Veamos un ejemplo concreto de evolución de algunas figuras

 

 

           @          @       @

@@@       @ @        @ @      @

@ @       @ @

 

 

 

@         @@         @@       @@       @@      @@    @@      @@     @@     @@

@@        @@         @@       @@       @@      @@    @@      @@     @@     @@

 

 

 

                     @       @@@       @       @

  @       @@@      @@ @@     @@@      @ @      @

@@ @@    @@ @@              @@ @@

 @ @     @@ @@     @   @     @@@     @   @     @             @      @      

  @        @        @@@      @@@               @     @@@     @      @      @@@

                              @       @@@      @             @      @      

 

 

 

Y ahora una pantalla de muestra

 

 

                                                                                                      ________

 

 

A.II.2.2 Definición de la estructura de soporte

 

Para una implementación de este modelo la herramienta de los ficheros virtuales es particularmente apropiada, pues se desarrollarán accesos por una vía de acceso principal en (i,j) y otra en (j,i) además de utilizar una instancia de base de datos principal y otra de trabajo asociada a la evolución en curso, ambas basadas en la siguiente definición de la estructura de soporte:

 

 

 

 

// Estructura de claves del fichero de soporte del escenario

 

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

{

long li; // Indice i del nodo

long lj; // Indice j del nodo

};

 

 

 

 

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

{

long lj; // Indice j del nodo

long li; // Indice i del nodo

};

 

 

 

 

// Estructura de datos del fichero de soporte del escenario

 

struct sDsD // Estructura de datos asociados

{

short int a;// 0,1 Activo

};

 

 

 

 

// Estructura de soporte del fichero virtual utilizado en la evolución de escenarios

 

static struct sDsKD

{

struct sDsK DK; // Clave ij

struct sDsK01 DK01; // Clave ji

struct sDsD DD; // Datos

} DSc, DSa; // Escenario en curso y anterior

 

 

 

 

Disponiendo de esta base de datos, la implementación surge de forma natural; así, para pasar de una generación a la siguiente, se volcará la situación actual al duplicado de trabajo, incluyendo los puntos frontera, y a continuación se leerá este duplicado temporal aplicándose a cada ítem el conjunto de reglas del juego.

 

 

El epígrafe siguiente se dedica a presentar la implementación del proceso que se acaba de resumir.

 

                                                                                                      ________

 

 

A.II.2.3 Implementación de la evolución generacional

 

Al igual que se hizo en el capítulo anterior dedicado a los cuadrados mágicos y sudokus, en este capítulo nos centraremos en la codificación núcleo de la pantalla que genera las evoluciones generacionales del juego de la vida.

 

Este código principal se convertirá en servicios de una DLL que se aplicará a la pantalla origen y los modelos COM y NET. Como parte del proceso, también se transcribirán las rutinas auxiliares prácticamente sin cambios como rutinas internas de la DLL.

 

Al retomar en la segunda zona del libro la implementación de esta DLL, se presentará el conjunto completo de las rutinas internas y externas desarrolladas.

 

Pero ahora sólo se presentarán los aspectos centrales de la codificación del algorítmico que se acaba de introducir, centrados en la rutina de generación principal siguiente,

 

   

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

      // Generación

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

   long PrGen(long N)
   {


    // Paso 1.
Vuelca situación actual como anterior y limpia situación actual

    lresul = SRRCW_CPY("PVIDAC", "PVIDAA");




    // Paso 2. Genera la envoltura de exploración de la población anterior

    lresul = 0;

    for(k=1;;++k)
    {
     er = SRRCW_READ("PVIDAC", k, &DSc);
     if (er) break;

     i = DSc.DK.li - ISUM;
     j = DSc.DK.lj - JSUM;

     lresul += PrEvolAnt(i, j);
    }



    // Paso 3. Limpia destino

    er = SRRCW_CLRF("PVIDAC");




    // Paso 4. Núcleo algorítmico. Reglas del "juego de la vida de John H.Conway"

    for(k=1;;++k)
    {
     er = SRRCW_READ("PVIDAA", k, &DSa);
     if (er) break;

     i = DSa.DK.li - ISUM;
     j = DSa.DK.lj - JSUM;

     a = DSa.DD.a;


     // Recupera el número de vecinos ocupados
 
     nvec = PrNvec(i, j);



     // Si una celda vacía tiene 3 vecinos exactamente, se ocupa

     if (!a && nvec == 3)
     {
      lresul = PrWriteC(i, j, 1);
      continue;
     }


     // Si una celda ocupada tiene menos de 2 vecinos, muere por aislamiento

     if (a && nvec < 2) continue;



     // Si una celda ocupada tiene + 3 vecinos, muere por superpoblación

     if (a && nvec > 3) continue;



     // El resto de celdas se mantiene como estaba

     if (!a) continue;

     lresul = PrWriteC(i, j, 1);
    }



    // Devuelve el tamaño poblacional

    er = SRRCW_INF("PVIDAC", &iDimC, &lDimD, &lNÍTEM, &lBAJAS, &lNIDD);

    return (lNÍTEM - lBAJAS);
   }

                                                                                                      ________

 

 

Rutina que se integra en el botón principal del programa:

 

 

   void CPvidaDlg::OnBUTTONok()
   {

    // Restaura los datos de pantalla

    OnBUTTONResetContent();



    // Generación. Da tantos pasos como se soliciten vía m_NG

    for (i=0;i<m_NG;++i)
    {

     // Actualiza el contador de muestras

     ++m_N;


     // Genera nueva muestra

     m_P = PrGen(m_N);
    }


    // Representación

    CPvidaDlg::OnBUTTONabid();

    return;
   }
                                                                                                      ________

 

 

A.II.2.4 Implementación de controles de visualización

 

Los demás procedimientos permiten el control del recuadro de visualización.

 

Puesto que la población nace en el recuadro origen pero no se le pone ninguna limitación a su deambular, se necesitan rutinas de búsqueda de extremos para permitir controles de navegación del mínimo al máximo de la extensión poblacional disponible en cada momento.

 

Así, los controles de búsqueda de la presentación del recuadro más inferior invocan a las funciones siguientes, en donde se lee el mínimo en I o el mínimo en J usando la vía de acceso principal ij o su transpuesta ji:

 

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

// Lee posición mínima actual en i

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

long PrMinI(void)

{

 

  // Lee posición mínima actual en i y la devuelve

 

  er = SRRCW_READ("PVIDAC", 1, &DSc);

 

  return DSc.DK.li;

}

 

 

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

// Lee posición mínima actual en j

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

long PrMinJ(void)

{

 

  // Lee y pasa posición mínima actual en j (en el fichero lógico)

 

  er = SRRCW_READ("PVIDAC01", 1, &DSc);

 

  return DSc.DK.lj;

}

 

El código expuesto refleja la algorítmica principal del programa, a la que volveremos posteriormente al acometer la tarea de su segregación para construir la DLL SRjvida que servirá para atender tanto a esta pantalla, como a los interfaces bajo COM y NET en lenguaje Visual Basic. El código completo de esta serie se encuentra en el apéndice

"C5 Relación de programas de muestra desarrollados en el libro"

 

                                                                                                       _______