Game of Life, de Conway
Essa classe foi criada para executar o [http://www.math.com/students/wonders/life/life.html Game of Life] em uma matriz de 0s e 1s, onde 1 representa uma célula "viva". Já existe código para o Game of Life em Python (bem, em qualquer linguagem que você pensar, pois é um problema matemático clássico) mas eu estou querendo desenvolver por conta própria e ver quão longe eu chego, principalmente em termos de desempenho e funcionalidade.
Estou usando essa classe para implementar uma [http://www20.brinkster.com/rodviking/game.png versão gráfica] do Life usando PyQt e Numarray. Caso tenha interesse nesse código também, contate-me através do link no fim da página
Por enquanto o código não está otimizado pois meu enfoque é primeiro ter meu programa funcionando pra depois melhorar o desempenho (que está razoável), mas estou aberto a sugestões, em especial nos métodos "applyRules" e "countNeighbours" que é onde estão os "gargalos".
Em breve essa classe também irá suportar o carregamento de arquivos de "pattern" (extensão .lif), que inclui regras dinâmicas.
Código
1 from numarray import *
2
3 class LifeGame:
4
5 def countNeighbours (self, x, y):
6 total = 0
7
8 #count the living neighbours (=1) on the row above
9 if x > 0:
10 total += self.world[x-1, y]
11 if y > 0:
12 total += self.world[x-1, y-1]
13 if y < self.num_cols - 1:
14 total += self.world[x-1, y+1]
15
16 #count the living neighbours on the left and right
17 if y > 0:
18 total += self.world[x, y-1]
19 if y < self.num_cols - 1:
20 total += self.world[x, y+1]
21
22 #count the living neighbours on the row below
23 if x < self.num_rows - 1:
24 total += self.world[x+1, y]
25 if y > 0:
26 total += self.world[x+1, y-1]
27 if y < self.num_cols - 1:
28 total += self.world[x+1, y+1]
29 return total
30
31 def emptyGrid (self):
32 return zeros([self.num_rows, self.num_cols])
33
34 def printGrid (self, world):
35 print world
36
37 def playLife (self, world, debug=False):
38 self.world = world
39 self.num_rows = len(world)
40 self.num_cols = len(world[0])
41
42 if debug:
43 print "Original grid:"
44 self.printGrid(world)
45
46 result = self.emptyGrid()
47 for row in range(self.num_rows):
48 for col in range(self.num_cols):
49 result [row, col] = self.applyRules(row, col)
50
51 if debug:
52 print "Result grid:"
53 self.printGrid(result)
54 return result
55
56
57 def applyRules (self, x, y):
58 # - Rule 1: if the cell is "alive" (1), it stays
59 # alive only if it has 2 or 3 neighbours ('if' block)
60 # - Rule 2: if a cell is "dead" (0), it becomes
61 # alive if it has exactly 3 neighbours ('else' block)
62 cell = 0
63 sum_neighb = self.countNeighbours(x,y)
64 if self.world[x,y] == 1:
65 if 2 <= sum_neighb <= 3:
66 cell = 1
67 else:
68 if sum_neighb == 3:
69 cell = 1
70 return cell
71
72 if __name__ == '__main__':
73 #initialize grids
74 testworld = array([[0, 0, 0, 0, 0, 0, 0, 0],
75 [1, 1, 1, 0, 0, 0, 0, 0],
76 [0, 0, 0, 0, 0, 0, 0, 0],
77 [0, 0, 0, 0, 0, 0, 0, 1],
78 [0, 0, 0, 0, 0, 0, 1, 1]])
79
80 #play Life!
81 lg = LifeGame()
82 for i in range(2):
83 print "-" * 20
84 print "Iteration", i
85 testworld = lg.playLife(testworld, True)
86
Volta para CookBook.