ライフゲーム | Pythonでなんか作ってみる

ライフゲーム

時々ふとライフゲームを作りたくなる。
Cでも書いた。Javaでも書いた。ならばPythonでも書かねばならぬだろう。


def born_cell(point,cells):
for pos in positions(point):
if pos not in cells:
cells[pos] = {'own':0,'side':0}
if pos == point:
cells[pos]['own'] += 1
else:
cells[pos]['side'] += 1

def positions(point):
for dx in (-1,0,1):
for dy in (-1,0,1):
yield (point[0]+dx, point[1]+dy)

def next(cells):
new_cells={}
for pos,cell in cells.iteritems():
if (cell['own'] > 0 and cell['side'] == 2) or cell['side'] == 3:
born_cell(pos,new_cells)
return new_cells

def lifegame(cells):
yield cells
while 1:
cells = next(cells)
yield cells

def create(init_str):
new_cells={}
x,y = 0,0
for line in init_str.splitlines():
for pos in line:
if pos=='o':born_cell((x,y),new_cells)
x += 1
y += 1
x = 0
return new_cells

def view(cells, lt=(0,0),rb=(9,9)):
"cellsを2次元文字列で表示する"
for y in xrange(lt[1], rb[1]+1):
for x in xrange(lt[0], rb[0]+1):
cell = cells.get((x,y), {'own':0})
if cell['own'] == 1:
print 'o',
else:
print '.',
print

実際にライフゲームの処理を担うのは最初の4つの関数 born_cell, positions, nextそれにlifegameである。
createは文字列形式の初期配置からcellのデータ構造を作成する関数。viewはその逆をして表示する関数である。

以下のように使う。

>>> cells=create("""\
.o.
..o
ooo""")
>>> for cell in lifegame(cells):
view(cell)
print
. o . . . . . . . .
. . o . . . . . . .
o o o . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .

. . . . . . . . . .
o . o . . . . . . .
. o o . . . . . . .
. o . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .

表示はアレだがグライダーが飛んでいく・・・。
ちなみに、セルのデータ構造は配列ではなく、辞書になっているので表示されていなくても無限にグライダーは飛んでいってる。
表示の簡易化のために初期配置を(0,0)にした(0,0)-(9,9)を表示しているだけなので、そこんところを何とかすればメモリの許す限り広大なライフゲームが出来るはず。