Skip to content

Instantly share code, notes, and snippets.

@chemacortes
Last active September 19, 2022 09:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chemacortes/6257951 to your computer and use it in GitHub Desktop.
Save chemacortes/6257951 to your computer and use it in GitHub Desktop.
Juego de la vida de Conway realizado en numpy y animado con matplotlib. Basado en el artículo de Juan Luis Cano (@Juanlu001) en http://pybonacci.wordpress.com/2012/11/30/juego-de-la-vida-de-conway-con-python-usando-numpy/

El juego de la vida de Conway

Aunque hay muchas variantes del juego de la vida, nos vamos a centrar en la que publicó originalmente Conway en 1970.

El juego de la vida es un juego de cero jugadores, lo que quiere decir que su evolución está determinada por el estado inicial y no necesita ninguna entrada de datos posterior (Wikipedia).

Las reglas son las siguientes:

  • El tablero es una rejilla de celdas cuadradas (n x m) que tienen dos posibles estados: viva y muerta.
  • Cada célula tiene ocho células vecinas: se cuentan también las de las diagonales.
  • En cada paso, todas las células se actualizan instantáneamente teniendo en cuenta la siguiente regla:
    • Cada célula viva con 2 o 3 células vecinas vivas sobrevive.
    • Cada célula con 4 o más células vecinas vivas muere por superpoblación. Cada célula con 1 o ninguna célula vecina viva muere por soledad.
    • Cada célula muerta con 3 células vecinas vivas nace.
# coding: utf-8
"""Juego de la vida de Conway.
Author: Chema Cortés <ch3m4@ch3m4.org>
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from matplotlib import animation
class Board(object):
def __init__(self, n, m):
self.T = np.zeros((n,m), dtype=int)
# Matrices generadoras
self.A = np.roll(np.identity(n),1,0) + np.roll(np.identity(n),-1,0)
self.B = np.roll(np.identity(m),1,1) + np.roll(np.identity(m),-1,1)
self.C = np.identity(m) + self.B
def clear(self):
self.T = np.zeros(self.T.shape, dtype=int)
def fill_random(self):
self.T = np.random.randint(2,size=self.T.shape)
def pos_pattern(self, patstr, x, y, rot=0, flip=False):
pat = np.array([[1 if c=='x' else 0 for c in l] for l in patstr.split()])
if flip: pat = np.fliplr(pat)
pat = np.rot90(pat, rot)
h,v = pat.shape
self.T[x:x+h,y:y+v] = pat
def step(self):
# Células vivas en el vecindario.
# A·T + T·B + A·T·B == (A·T)·(1+B) + T·B == A·T·C + T·B
V = np.dot(np.dot(self.A,self.T),self.C) + np.dot(self.T,self.B)
# Sobrevive si hay dos vecinos. Se genera una nueva si hay tres.
self.T = np.select([V==3,V+self.T==3],[1,1],0)
class Anim(animation.TimedAnimation):
def __init__(self, board, generations=200, interval=10):
fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(111)
ax.axis('off')
self.board = board
self.generations = generations
self.img = ax.imshow(board.T, interpolation="none", cmap=cm.gray_r)
animation.TimedAnimation.__init__(self, fig, interval=interval, blit=True)
def _init_draw(self):
self.img.set_data(np.zeros(self.board.T.shape))
def _draw_frame(self, framedata):
self.board.step()
self.img.set_data(self.board.T)
def new_frame_seq(self):
return iter(xrange(self.generations))
# Some patterns
glider="""
-x-
--x
xxx
"""
ship="""
x--x-
----x
x---x
-xxxx
"""
r_pentomino="""
-----
--xx-
-xx--
--x--
-----
"""
#Gosper glider gun
gun="""
--------------------------------------
-------------------------x------------
-----------------------x-x------------
-------------xx------xx------------xx-
------------x---x----xx------------xx-
-xx--------x-----x---xx---------------
-xx--------x---x-xx----x-x------------
-----------x-----x-------x------------
------------x---x---------------------
-------------xx-----------------------
--------------------------------------
"""
pat_minimal="""
----------
-------x--
-----x-xx-
-----x-x--
-----x----
---x------
-x-x------
"""
one_line="""
-----------------------------------------
-xxxxxxxx-xxxxx---xxx------xxxxxxx-xxxxx-
-----------------------------------------
"""
if __name__ == "__main__":
tablero = Board(100,100)
# tablero.fill_random()
tablero.pos_pattern(gun,30,11, 1)
tablero.pos_pattern(gun,40,50, 2)
anim = Anim(tablero)
# anim.save("juego_vida.avi", fps=10)
plt.show()
@astrojuanlu
Copy link

Me ha hecho gracia lo de Muñoz pero soy Juan Luis Cano jeje :P

@chemacortes
Copy link
Author

Yups! Corregido. Aunque la cuenta de twitter que pones en Pybonacci pone Muñoz.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment