Created
January 7, 2021 22:33
-
-
Save shiracamus/80b8b236bc177416940c80eeb4be81a6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
import time | |
DEPOP = 1 # 過疎条件 | |
OVERCROW = 4 # 過密条件 | |
ALIVE_LOWER = 3 # 発生条件(下限) | |
ALIVE_UPPER = 3 # 発生条件(上限) | |
ETERNAL = False # セルの永続化フラグ | |
INITIALIZE_ALIVE_RATE = 20 # 初期セルの生存率(%) | |
class LifeGame: | |
def __init__(self, width, height): | |
self.width = width | |
self.height = height | |
self.cells = self.generate(self.init_life) | |
def next_generation(self): | |
"""世代交代""" | |
self.cells = self.generate(self.next_life) | |
def __iter__(self): | |
"""生命体セルのイテレータを返す(for文のinで使用)""" | |
return iter(self.cells) | |
def generate(self, life): | |
"""生命体セルを生成する""" | |
return tuple(tuple(life(x, y) for x in range(self.width)) | |
for y in range(self.height)) | |
def init_life(self, x, y): | |
"""初期の生命体の値""" | |
if random.randint(1, 100) <= INITIALIZE_ALIVE_RATE: | |
return random.randint(0, 9) | |
return 0 | |
def next_life(self, x, y): | |
"""次世代の生命体の値""" | |
life = self.cells[y][x] | |
neighbor_alives = self.count_neighbor_alives(x, y) | |
if life == 0: | |
if ALIVE_LOWER <= neighbor_alives <= ALIVE_UPPER: | |
life = 1 | |
elif life == 9: | |
if not ETERNAL: | |
life = 0 # 寿命で死亡 | |
else: | |
if DEPOP < neighbor_alives < OVERCROW: | |
life += 1 | |
else: | |
life = 0 | |
return life | |
def count_neighbor_alives(self, x, y): | |
"""周囲のセルの生存数を数える""" | |
return sum(1 | |
for ny in (y - 1, y, y + 1) | |
if 0 <= ny < self.height | |
for nx in (x - 1, x, x + 1) | |
if 0 <= nx < self.width | |
if (ny, nx) != (y, x) | |
if self.cells[ny][nx] != 0) | |
def main(): | |
lifegame = LifeGame(79, 23) | |
for _ in range(100): | |
print('\033[2J\033[H') | |
for cells in lifegame: | |
print(*cells, sep='') | |
time.sleep(1) | |
lifegame.next_generation() | |
if __name__ == '__main__': | |
main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time | |
import matplotlib.pyplot as plt | |
from lifegame_model import LifeGame | |
# 各変数の設定 | |
# グラフの描画サイズ | |
WIDTH = HEIGHT = 1000 | |
# 描画時のセルの間隔 | |
# 各軸のセルの数は描画サイズ÷セルの間隔で求められます。 | |
SPACE = 5 | |
# セル描画時の大きさ係数 | |
SIZE_FACTOR = 5 | |
class LifeGameView: | |
def __init__(self): | |
# インタラクティブモード オン | |
plt.ion() | |
# 描画領域の初期化 | |
fig, ax = plt.subplots() | |
ax.set_xlim(0, WIDTH + SPACE) | |
ax.set_ylim(0, HEIGHT + SPACE) | |
ax.set_aspect('equal') | |
ax.grid(False) | |
# マウスクリックで終了するためのイベントの設定 | |
fig.canvas.mpl_connect('button_press_event', stop) | |
# scatter(散布図)オブジェクトの作成 | |
width = WIDTH // SPACE | |
height = HEIGHT // SPACE | |
x = [*range(1, WIDTH + 1, SPACE)] * height | |
y = [y for y in range(1, HEIGHT + 1, SPACE) for x in range(width)] | |
color = ['b'] * width * height | |
scale = [0] * width * height | |
self.sc = ax.scatter(x, y, c=color, s=scale, alpha=0.3, edgecolors='none') | |
def draw(self, lifegame): | |
scale = [] | |
color = [] | |
# セルの状態を元に描画設定を作成 | |
for cells in lifegame: | |
for life in cells: | |
scale.append(life * SIZE_FACTOR) | |
color.append('bbbbbggggr'[life]) | |
# 描画の設定と再描画 | |
self.sc.set_sizes(scale) | |
self.sc.set_color(color) | |
self.sc.figure.canvas.draw_idle() | |
self.sc.figure.canvas.flush_events() | |
def stop(event): | |
print('Program is over.') | |
main.loop = False | |
def main(): | |
view = LifeGameView() | |
lifegame = LifeGame(WIDTH // SPACE, HEIGHT // SPACE) | |
main.loop = True | |
while main.loop: | |
lifegame.next_generation() | |
view.draw(lifegame) | |
# 処理が早すぎて困る場合のスリープ(秒) | |
# time.sleep(0.01) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment