El Juego de la Vida

We used a one-dimensional array to store the list of cell states before, and for the Game of Life, we can use a two-dimensional array.

We’ll begin by initializing each cell of the board with a random state: 0 or 1.

Configuración para ejecutar el lenguaje Processing


In [4]:
from metakernel import register_ipython_magics
register_ipython_magics()

Código del Juego de la Vida


In [16]:
%%processing

// Una implementacion basica del Juego de la Vida de John Conway
// Codigo basado en:
// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com

// Configuracion del tablero
int refreshRate = 3; // Velocidad de refresco (refrescos por segundo)

// Configuracion de las celulas
int statesSize = 2; // Numero de estados posibles (2 = Inactivo o activo)
int[] statesColor = new int[]{255, 0}; // Color de cada estado (0=negro, 255=blanco)
int[] statesProbability = new int[]{50, 50}; // Probabilidad inicial de cada estado, en porcentaje (la suma debe ser 100)

// Configuracion de las reglas del Juego de la Vida
int ruleMax_neighbors = 3; // Regla de sobrepoblacion (la celula se muere cuando vecinos_activos > ruleMax_neighbors)
int ruleMin_neighbors = 2; // Regla de soledad (la celula se muere cuando vecinos_activos < ruleMin_neighbors)
int ruleRep_neighbors = 3; // Regla de reproducción (la celula se activa cuando vecinos_activos = ruleRep_neighbors)

// Objeto con los datos del tablero
GOL gol;

// Inicio
void setup() {
    checkParams(); // Comprobacion de que los parametros son correctos
    size(640, 320); // Dimensiones del tablero (pixels)
    frameRate(refreshRate); // Velocidad de refresco
    gol = new GOL();
}

// Dibujar
void draw() {
    gol.generate(); // Calcular siguiente generacion
    gol.display(); // Mostrar nuevo tablero
}

// Reiniciar el tablero cuando se pulsa el raton
void mousePressed() {
    gol.init();
}

// Comprobar si hay algun error en los parametros de configuracion
void checkParams() {
    if (statesSize!=statesProbability.length) {
        println("El vector de probabilidades debe tener una longitud de "+str(statesSize)+" estados.");
    }
    int total = 0;
    for (int i=0; i<statesProbability.length; i++) { total=total+statesProbability[i]; }
    if (total!=100) {
        println("El vector de probabilidades debe sumar 100.");
    }
}


// Clase para mostrar un tablero del Juego de la Vida 
class GOL {

  int w = 8; // Anchura de cada celula (pixeles)
  int columns, rows; // Numero de filas y columnas del tablero
  int[][] board; // Tablero: Estados de cada una de las celulas.

  GOL() {
    // Iniciamos filas, columnas y tablero
    columns = width/w;
    rows = height/w;
    board = new int[columns][rows];
    // Iniciamos el tablero
    init();
  }

  // Iniciar los datos del tablero
  void init() {
    int[] probabilityCumulative = new int[statesSize];
    probabilityCumulative[0] = statesProbability[0];
      for (int i=1; i<statesSize; i++) {
        probabilityCumulative[i] = probabilityCumulative[i-1]+statesProbability[i];
    }
    int aux;
    for (int i =1;i < columns-1;i++) {
      for (int j =1;j < rows-1;j++) {
          //board[i][j] = int(random(2));
          aux = int(random(100));
          for (int k=statesSize-1; k>=0; k--) {
              if (aux<probabilityCumulative[k]) {
                  board[i][j] = k;
              }
          }
      }
    }
  }

  // Calcular una nueva generacion
  void generate() {

    int[][] next = new int[columns][rows];

    // Loop through every spot in our 2D array and check spots neighbors
    for (int x = 1; x < columns-1; x++) {
      for (int y = 1; y < rows-1; y++) {

        // Add up all the states in a 3x3 surrounding grid
        int neighbors = 0;
        for (int i = -1; i <= 1; i++) {
          for (int j = -1; j <= 1; j++) {
            neighbors += board[x+i][y+j];
          }
        }

        // A little trick to subtract the current cell's state since
        // we added it in the above loop
        neighbors -= board[x][y];

        // Rules of Life
        if      ((board[x][y] == 1) && (neighbors <  ruleMin_neighbors)) next[x][y] = 0; // Loneliness
        else if ((board[x][y] == 1) && (neighbors >  ruleMax_neighbors)) next[x][y] = 0; // Overpopulation
        else if ((board[x][y] == 0) && (neighbors == ruleRep_neighbors)) next[x][y] = 1; // Reproduction
        else                                                             next[x][y] = board[x][y]; // Stasis
      }
    }

    // Next is now our board
    board = next;
  }

  // Dibujar el tablero
  void display() {
    for ( int i = 0; i < columns;i++) {
      for ( int j = 0; j < rows;j++) {
        fill(statesColor[board[i][j]]);
        stroke(0);
        rect(i*w, j*w, w, w);
      }
    }
  }
}