Pythonのススメ11
はじめに
Pythonでプログラムを書くにあたり、文法や言語仕様などの個人的なメモを記載する。今回のネタはライフゲーム。
Tkinterという、PythonのGUIツールを使ってライフゲームの実装を行った。
ライフゲーム
生命の誕生、進化、淘汰などのプロセスを簡易的なモデルで再現したシミュレーションゲームで、イギリスの数学者ジョン・ホートン・コンウェイによって考案された。セル・オートマトンの一種と言われているが、難しいことは置いといて、ライフゲームには以下のようなルールがある。
生物の誕生
死んでいるセルの周囲に生きているセルが3つあれば、次の世代に生物が誕生する。
生物が継続して生存
生きているセルの周囲に生きているセルが2つ以上3つ以下あれば、次の世代に生物は継続して生存する。
過疎状態
周囲に生きているセルが1つ以下しかなければ、次の世代には死滅する。
過密状態
生きているセルの周囲に生きているセルが4つ以上あれば、過密により死滅する。
上記4つの制約(いずれもシンプル)を守ったうえでゲームを実装する。
ライフゲームのソースコード
今回作成したソースコードは以下の通り。乱数を使って状態を初期化し、300ミリ秒ごとに上記制約から次の状態を判断し描画している。
(ループを多用しすぎている感があるので、とりあえず動くものは出来たが、リファクタリングの価値はまだあると思っている)
from tkinter import * from random import randint COLS, LOWS = [70, 50] CW = 10 data = [] CELL_NEXT_TURN_VAL_EXIST = 1 CELL_NEXT_TURN_VAL_NON_EXIST = 0 TIME_INTERVAL = 300 win = Tk() cv = Canvas(win, width=700, height=500) cv.pack() """ Canvasの初期化メソッド. 0か1の乱数を発生し、1の場合は青色の円を描写する. """ def initializeCanvas(): tmp = [] for col in range(0, COLS): for low in range(0, LOWS): tmp.append(randint(0, 1)) data.append(tmp) tmp = [] paintCanvas(data) """ 次ターンでセルが生存しているかどうか. """ def isExistNextTurn(col, low, data): targetPointList = [[-1, -1], [0, -1], [1, -1], [-1, 0], [1, 0], [-1, 1], [0, 1], [1, 1]] currentPositionValue = data[col][low] result = 0 for targetPoint in targetPointList: x = col + targetPoint[0] y = low + targetPoint[1] if (0 <= x < COLS) and (0 <= y < LOWS): if data[x][y] == 1: result += 1 # 次ターンで「誕生」 if currentPositionValue == 0 and result == 3: return True # 次ターンで「存続」 elif currentPositionValue == 1 and 2 <= result <= 3: return True # 次ターンで「消滅」 else: return False def getNextTurnCellData(data): result = [] tmp = [] for col in range(0, COLS): for low in range(0, LOWS): if isExistNextTurn(col, low, data): tmp.append(CELL_NEXT_TURN_VAL_EXIST) else: tmp.append(CELL_NEXT_TURN_VAL_NON_EXIST) result.append(tmp) tmp = [] return result def paintCanvas(data): cv.delete("all") for col in range(0, COLS): for low in range(0, LOWS): if data[col][low] == 1: cv.create_oval(col * CW, low * CW, col * CW + CW, low * CW + CW, fill="blue") else: cv.create_oval(col * CW, low * CW, col * CW + CW, low * CW + CW, fill="white") def game_loop(data): data = getNextTurnCellData(data) paintCanvas(data) win.after(TIME_INTERVAL, game_loop, data) # 指定時間後に再度描画 initializeCanvas() win.after(TIME_INTERVAL, game_loop, data) # 指定時間後に再度描画 win.mainloop()
終わりに
本投稿では、Pythonでライフゲームの実装をしたことを述べた。守るべき制約はあるものの、いずれもシンプルなものであり、工夫次第でいくらでもプログラムできる。
今回記載したソースコードでとりあえず動くが、ループを多用しすぎている感がある。
もっと良い書き方があると思っているので、気が向いたらリファクタリングをしてみようと思う。
参考文献
・ライフゲーム - Wikipedia・ゼロからはじめるPython(9) 生物集団の栄枯盛衰"ライフゲーム"を作ってみよう | マイナビニュース
・ゼロからはじめるPython(8) ゲームで覚えるPythonプログラミング - Tkinterで始めよう | マイナビニュース