Il Game of Life, concepito dal matematico britannico John Horton Conway nel 1970, è un automa cellulare a due dimensioni che ha catturato l’immaginazione di matematici, informatici e appassionati di giochi per oltre cinquant’anni. Con le sue semplici regole che governano la nascita, la morte e la sopravvivenza delle cellule su una griglia, il Game of Life genera una sorprendente varietà di pattern e comportamenti complessi. In questo articolo, esploreremo le regole del gioco, alcuni dei suoi pattern più noti e come implementarlo in Python.
Le regole del Game of Life
Il Game of Life si svolge su una griglia bidimensionale di celle quadrate, ognuna delle quali può essere “viva” (1) o “morta” (0). Le celle interagiscono con i loro otto vicini, che sono le celle direttamente adiacenti orizzontalmente, verticalmente e diagonalmente. A ogni passo temporale, o generazione, le seguenti quattro regole vengono applicate simultaneamente a tutte le celle:
- Una cella viva con meno di due vicini vivi muore per isolamento.
- Una cella viva con due o tre vicini vivi sopravvive alla generazione successiva.
- Una cella viva con più di tre vicini vivi muore per sovraffollamento.
- Una cella morta con esattamente tre vicini vivi diventa viva per riproduzione.
Pattern interessanti nel Game of Life
Le semplici regole del Game of Life danno origine a una vasta gamma di pattern e comportamenti. Alcuni dei più noti sono:
- Configurazioni oscillanti: pattern che si ripetono periodicamente dopo un certo numero di generazioni, come il Blinker, il Toad, il Beacon e il Pulsar.
- Navi spaziali: pattern che si spostano attraverso la griglia mentre oscillano, come il Glider e il Lightweight Spaceship (LWSS).
- Pattern stabili: configurazioni che non cambiano nel tempo, come il Block e la Beehive.
- Cannoni: pattern che producono navi spaziali o altri pattern in modo periodico, come il Glider Gun di Gosper.
Implementazione del Game of Life in Python
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def inizializza_griglia(n):
griglia = np.random.choice([0, 1], n*n, p=[0.5, 0.5]).reshape(n, n)
return griglia
def conta_vicini_vivi(griglia):
vicini_vivi = np.zeros(griglia.shape, dtype=int)
for x in range(-1, 2):
for y in range(-1, 2):
if x == 0 and y == 0:
continue
vicini_vivi += np.roll(np.roll(griglia, y, axis=0), x, axis=1)
return vicini_vivi
def aggiorna_griglia(griglia):
nuova_griglia = griglia.copy()
vicini_vivi = conta_vicini_vivi(griglia)
nuova_griglia[(griglia == 1) & (vicini_vivi < 2)] = 0
nuova_griglia[(griglia == 1) & (vicini_vivi > 3)] = 0
nuova_griglia[(griglia == 0) & (vicini_vivi == 3)] = 1
return nuova_griglia
def aggiorna_frame(*args):
global griglia
griglia = aggiorna_griglia(griglia)
img.set_array(griglia)
return [img]
def main():
global griglia, img
n = 50 # Dimensione della griglia
generazioni = 100 # Numero di generazioni
griglia = inizializza_griglia(n)
fig, ax = plt.subplots()
img = ax.imshow(griglia, cmap='binary')
ax.set_xticks([])
ax.set_yticks([])
anim = FuncAnimation(fig, aggiorna_frame, frames=generazioni, interval=200, blit=True)
plt.show()
if __name__ == '__main__':
main()
Per implementare il Game of Life in Python, è possibile utilizzare la libreria numpy per rappresentare e manipolare la griglia e la libreria matplotlib per visualizzare l’evoluzione del gioco nel tempo. Il codice può essere organizzato nelle seguenti funzioni:
- inizializza_griglia: crea una griglia iniziale con celle viventi e morte casuali.
- conta_vicini_vivi: calcola il numero di vicini vivi per ogni cella della griglia.
- aggiorna_griglia: applica le regole del Game of Life alla griglia corrente per ottenere la griglia della generazione successiva.
- visualizza: mostra la griglia corrente con matplotlib