Juego de la vida de Conway (Implementación de Python)

Game Of Life de Conways es un método de automatización celular creado por John Conway. Este juego fue creado con la biología en mente, pero se ha aplicado en varios campos, como gráficos, generación de terreno, etc.

life_game

El «juego» es un juego de cero jugadores, lo que significa que su evolución está determinada por su estado inicial, que no requiere más entrada. Uno interactúa con el Juego de la Vida creando una configuración inicial y observando cómo evoluciona, o, para “jugadores” avanzados, creando patrones con propiedades particulares.
Cómo funciona el juego 
Debido a que el Juego de la Vida se basa en una cuadrícula de nueve cuadrados, cada celda tiene ocho celdas vecinas, como se muestra en la figura. Se accede a una celda determinada (i, j) en la simulación en una cuadrícula [i][j], donde i y j son los índices de fila y columna, respectivamente. El valor de una celda dada en un instante de tiempo dado depende del estado de sus vecinos en el paso de tiempo anterior. El Juego de la vida de Conway tiene cuatro reglas. 
 

  1. Si una celda está ENCENDIDA y tiene menos de dos vecinos que estén ENCENDIDOS, se APAGA
  2. Si una celda está ENCENDIDA y tiene dos o tres vecinos que están ENCENDIDOS, permanece ENCENDIDA.
  3. Si una celda está ENCENDIDA y tiene más de tres vecinos que están ENCENDIDOS, se APAGA.
  4. Si una celda está APAGADA y tiene exactamente tres vecinos que están ENCENDIDOS, se enciende.

Entonces, como sabemos cómo funciona, lo siguiente que debemos averiguar es cómo hacer que funcione.

Acercarse 

  1. Inicializar las celdas en la cuadrícula.
  2. En cada paso de tiempo en la simulación, para cada celda (i, j) en la cuadrícula, haga lo siguiente:
    1.  Actualice el valor de la celda (i, j) en función de sus vecinos, teniendo en cuenta las condiciones de contorno.
    2.  Actualice la visualización de los valores de la cuadrícula.

Después de que terminemos aquí, pongamos nuestras manos en el código.

Requisitos 

  1. entumecido
  2. matplotlib
  3. análisis de argumentos
  4. Pygame

Implementación: ahora comencemos 

Python3

# Python code to implement Conway's Game Of Life
import argparse
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
 
# setting up the values for the grid
ON = 255
OFF = 0
vals = [ON, OFF]
 
def randomGrid(N):
 
    """returns a grid of NxN random values"""
    return np.random.choice(vals, N*N, p=[0.2, 0.8]).reshape(N, N)
 
def addGlider(i, j, grid):
 
    """adds a glider with top left cell at (i, j)"""
    glider = np.array([[0,    0, 255],
                       [255,  0, 255],
                       [0,  255, 255]])
    grid[i:i+3, j:j+3] = glider
 
def addGosperGliderGun(i, j, grid):
 
    """adds a Gosper Glider Gun with top left
       cell at (i, j)"""
    gun = np.zeros(11*38).reshape(11, 38)
 
    gun[5][1] = gun[5][2] = 255
    gun[6][1] = gun[6][2] = 255
 
    gun[3][13] = gun[3][14] = 255
    gun[4][12] = gun[4][16] = 255
    gun[5][11] = gun[5][17] = 255
    gun[6][11] = gun[6][15] = gun[6][17] = gun[6][18] = 255
    gun[7][11] = gun[7][17] = 255
    gun[8][12] = gun[8][16] = 255
    gun[9][13] = gun[9][14] = 255
 
    gun[1][25] = 255
    gun[2][23] = gun[2][25] = 255
    gun[3][21] = gun[3][22] = 255
    gun[4][21] = gun[4][22] = 255
    gun[5][21] = gun[5][22] = 255
    gun[6][23] = gun[6][25] = 255
    gun[7][25] = 255
 
    gun[3][35] = gun[3][36] = 255
    gun[4][35] = gun[4][36] = 255
 
    grid[i:i+11, j:j+38] = gun
 
def update(frameNum, img, grid, N):
 
    # copy grid since we require 8 neighbors
    # for calculation and we go line by line
    newGrid = grid.copy()
    for i in range(N):
        for j in range(N):
 
            # compute 8-neighbor sum
            # using toroidal boundary conditions - x and y wrap around
            # so that the simulation takes place on a toroidal surface.
            total = int((grid[i, (j-1)%N] + grid[i, (j+1)%N] +
                         grid[(i-1)%N, j] + grid[(i+1)%N, j] +
                         grid[(i-1)%N, (j-1)%N] + grid[(i-1)%N, (j+1)%N] +
                         grid[(i+1)%N, (j-1)%N] + grid[(i+1)%N, (j+1)%N])/255)
 
            # apply Conway's rules
            if grid[i, j]  == ON:
                if (total < 2) or (total > 3):
                    newGrid[i, j] = OFF
            else:
                if total == 3:
                    newGrid[i, j] = ON
 
    # update data
    img.set_data(newGrid)
    grid[:] = newGrid[:]
    return img,
 
# main() function
def main():
 
    # Command line args are in sys.argv[1], sys.argv[2] ..
    # sys.argv[0] is the script name itself and can be ignored
    # parse arguments
    parser = argparse.ArgumentParser(description="Runs Conway's Game of Life simulation.")
 
    # add arguments
    parser.add_argument('--grid-size', dest='N', required=False)
    parser.add_argument('--mov-file', dest='movfile', required=False)
    parser.add_argument('--interval', dest='interval', required=False)
    parser.add_argument('--glider', action='store_true', required=False)
    parser.add_argument('--gosper', action='store_true', required=False)
    args = parser.parse_args()
     
    # set grid size
    N = 100
    if args.N and int(args.N) > 8:
        N = int(args.N)
         
    # set animation update interval
    updateInterval = 50
    if args.interval:
        updateInterval = int(args.interval)
 
    # declare grid
    grid = np.array([])
 
    # check if "glider" demo flag is specified
    if args.glider:
        grid = np.zeros(N*N).reshape(N, N)
        addGlider(1, 1, grid)
    elif args.gosper:
        grid = np.zeros(N*N).reshape(N, N)
        addGosperGliderGun(10, 10, grid)
 
    else:   # populate grid with random on/off -
            # more off than on
        grid = randomGrid(N)
 
    # set up animation
    fig, ax = plt.subplots()
    img = ax.imshow(grid, interpolation='nearest')
    ani = animation.FuncAnimation(fig, update, fargs=(img, grid, N, ),
                                  frames = 10,
                                  interval=updateInterval,
                                  save_count=50)
 
    # # of frames?
    # set output file
    if args.movfile:
        ani.save(args.movfile, fps=30, extra_args=['-vcodec', 'libx264'])
 
    plt.show()
 
# call main
if __name__ == '__main__':
    main()

Sin pasar ningún argumento de línea de comando. 
 

Ahora, aumentemos un poco las cosas, veamos qué sucede si agrega actualizaciones de la animación cada 500 milisegundos y configura las dimensiones 32X32 y también usa el patrón de deslizamiento inicial.

python 'filename.py' --grid-size 32 --interval 500 --glide

Puede intentar manipular este código para crear una simulación diferente usando esto.

Enlaces de referencia: 

  1. Código Github para este artículo
  2. Libro: Python Playground: Geeky Projects for the Curious Programmer
  3. docs-numpy
  4. documentos matplotlib

Este artículo es una contribución de Subhajit Saha . Si le gusta GeeksforGeeks y desea contribuir, también puede enviar su artículo por correo electrónico a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks. 

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *