Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで作るコンウェイのライフゲーム:基本ルールと実装方法を徹底解説


1970年頃、イギリスの数学者ジョン・ホートン・コンウェイによって考案された「ライフゲーム(Game of Life)」は、生物の集団が見せるカオス的でありながらも秩序のある増殖の様子を表現する、シンプルな一連のルールです。盤面は「生存」セルと「死亡」セルで構成される二次元グリッドとして表現されます。

ライフゲームの基本ルール

  • 過密(Overpopulation):あるセルの周囲に3つより多い生存セルが存在する場合、そのセルは次の世代で死滅します(OFF)。

  • 維持(Static):周囲に2つまたは3つの生存セルが存在する場合、そのセルは次の世代でも生存し続けます(ON)。

  • 過疎(Underpopulation):周囲に2つ未満の生存セルしか存在しない場合、そのセルは次の世代で死滅します(OFF)。

  • 繁殖(Reproduction):死んでいるセルの周囲にちょうど3つの生存セルが存在する場合、そのセルは次の世代で誕生します(ON)。

Pythonで作るコンウェイのライフゲーム:基本ルールと実装方法を徹底解説

Pythonで作るコンウェイのライフゲーム:基本ルールと実装方法を徹底解説 このセルは次のタイムスタンプで死滅します

Pythonで作るコンウェイのライフゲーム:基本ルールと実装方法を徹底解説 このセルは次のタイムスタンプで生存します

Pythonで作るコンウェイのライフゲーム:基本ルールと実装方法を徹底解説 このセルは生存中です

Pythonで作るコンウェイのライフゲーム:基本ルールと実装方法を徹底解説 このセルは死亡しています

これらのルールを各世代ごとに順番に適用していくと、予想を超える美しいパターンが次々と生まれます。

実装の手順

i. 空のユニバース(盤面)を初期化する
ii. シード(初期状態)でユニバースを満たす
iii. 各セルについて、近傍セルの状態をもとに次のタイムスタンプでの生死を判定する
iv. 手順iiiの生存判定関数を、ユニバース内のすべてのセルに適用する
v. 手順iii~ivを、目標の世代数に達するまで繰り返す

環境準備(インストール)

コンウェイのライフゲームを作成するには、matplotlibとnumpyの配列ライブラリを使用します。いずれもpipコマンドで簡単にインストールできます。

$pip install numpy matplotlib

ライフゲームの実装プログラム

それでは、上記のルールに従って実際にプログラムを書いてみましょう。以下がライフゲームの実装例です。

# 必要なライブラリのインポート

import numpy as np
import matplotlib.pyplot as plt

import argparse
import time

#-------------------------------------------------------------------------
class Board(object):
    def __init__(self, size, seed='Random'):
        if seed == 'Random':
            self.state = np.random.randint(2, size=size)
        self.engine = Engine(self)
        self.iteration = 0

    def animate(self):
        i = self.iteration
        im = None
        plt.title("Conway's Game of Life")
        while True:
            if i == 0:
                plt.ion()
                im = plt.imshow(self.state, vmin=0, vmax=2, cmap=plt.cm.gray)
            else:
                im.set_data(self.state)
            i += 1
            self.engine.applyRules()
            print('Life Cycle: {} Birth: {} Survive: {}'.format(i, self.engine.nBirth, self.engine.nSurvive))
            plt.pause(0.01)
            yield self

#-------------------------------------------------------------------------

class Engine(object):
    def __init__(self, board):
        self.state = board.state

    def countNeighbors(self):
        state = self.state
        n = (state[0:-2,0:-2] + state[0:-2,1:-1] + state[0:-2,2:] +
             state[1:-1,0:-2] + state[1:-1,2:] + state[2:,0:-2] +
             state[2:,1:-1] + state[2:,2:])
        return n

    def applyRules(self):
        n = self.countNeighbors()
        state = self.state
        birth = (n == 3) & (state[1:-1,1:-1] == 0)
        survive = ((n == 2) | (n == 3)) & (state[1:-1,1:-1] == 1)
        state[...] = 0
        state[1:-1,1:-1][birth | survive] = 1
        self.nBirth = np.sum(birth)
        self.nSurvive = np.sum(survive)

#-------------------------------------------------------------------------

def main():
    ap = argparse.ArgumentParser(add_help=False) # 引数パーサーの初期化
    ap.add_argument('-h', '--height', help='Board Height', default=256)
    ap.add_argument('-w', '--width', help='Board Width', default=256)
    args = vars(ap.parse_args()) # 引数の取得
    bHeight = int(args['height'])
    bWidth = int(args['width'])
    board = Board((bHeight, bWidth))
    for _ in board.animate():
        pass

#-------------------------------------------------------------------------

if __name__ == '__main__':
    main()

実行結果

Console:
Life Cycle: 1 Birth: 7166 Survive: 10621
Life Cycle: 2 Birth: 7930 Survive: 8409
Life Cycle: 3 Birth: 7574 Survive: 8756
Life Cycle: 4 Birth: 7114 Survive: 8406
Life Cycle: 5 Birth: 7005 Survive: 8126
Life Cycle: 6 Birth: 6644 Survive: 7926
Life Cycle: 7 Birth: 6266 Survive: 7711
Life Cycle: 8 Birth: 6132 Survive: 7427
Life Cycle: 9 Birth: 5957 Survive: 7322
Life Cycle: 10 Birth: 5769 Survive: 7290
Life Cycle: 11 Birth: 5585 Survive: 6937
Life Cycle: 12 Birth: 5381 Survive: 6791
Life Cycle: 13 Birth: 5208 Survive: 6686
Life Cycle: 14 Birth: 5063 Survive: 6563
….
…

このような出力は、ターミナルでCtrl-Cを押してプログラムを停止するまで表示され続けます。

グラフィカル表示

Pythonで作るコンウェイのライフゲーム:基本ルールと実装方法を徹底解説

セルは刻々と変化しながら、非常に美しいパターンを描き出します。

また、設定を変更したりスライダーの値を調整したりすることで、表示されるプロットを自由にカスタマイズすることも可能です。

Pythonで作るコンウェイのライフゲーム:基本ルールと実装方法を徹底解説


  1. 【Python】Tkinterで作るカラーゲーム – 30秒で文字の色を当てるGUIゲーム開発

    GUIアプリケーションの開発において、Pythonの標準ライブラリ「Tkinter」は非常に人気が高く、初心者でも扱いやすいツールです。追加のインストール作業なしに使えるため、Tkinterを活用すればシンプルなGUIゲームでも手軽に開発できます。 この記事では、Tkinterを使った「カラーゲーム」の作り方を紹介します。このゲームでは、画面に表示される単語の文字色をプレイヤーが入力し、正解するたびにスコアが1点ずつ加算されます。制限時間は30秒で、使用される色は赤(Red)、青(Blue)、緑(Green)、ピンク(Pink)、黒(Black)、黄(Yellow)、オレンジ(Orange)、

  2. PythonでのCX_Freezeの使い方:スクリプトを実行ファイル(EXE)に変換する方法

    はじめに 何か面白いものを作りたいという欲求は人間の本能であり、完成したものは誰かに共有したくなるものです。Pythonでもその願いを叶えられます。ただし、作成したPythonスクリプトをそのまま共有するには、相手のマシンにも同じバージョンのPythonと、プログラムで使用しているすべてのモジュールがインストールされている必要があります。 そこで役立つのがCX_Freezeです。このツールを使えば、Pythonがインストールされていない環境でも動作するスタンドアロンの実行ファイル(.exe)を作成できます。 CX_Freezeのインストール まず、コマンドプロンプトで以下のコマンドを実行し、c