Pythonでライフゲーム

Pocket

Pythonでライフゲームをやってみました。
初期状態を与えるとGIFを生成します。
初期状態を与えない場合はランダムになります。
描画にはPillowを使いました。

from PIL import Image, ImageDraw
import random

def main():
  size = 10 # 1マスのピクセル
  margin = 5 # 余白のピクセル
  num_cols = 20
  num_rows = 20
  color_bg = "white"
  color_life = "black"
  num_pages = 200

  # 初期状態を指定する場合
  cells_start = [
    [0, 0, 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1],
    [0, 1, 1, 1]
  ]
  # 初期状態をランダムにセットする場合
  cells_start = make_start_cells(num_cols, num_rows)

  width = size * num_cols + margin * 2
  height = size * num_rows + margin * 2
  images = []

  cells = [[0] * num_cols for i in range(num_rows)]

  # 初期状態を反映。
  for r in range(num_rows):
    for c in range(num_cols):
      if r < len(cells_start) and c < len(cells_start[r]):
        cells[r][c] = cells_start[r][c]

  for x in range(num_pages):
    im = Image.new('RGB', (width, height), color_bg)
    draw = ImageDraw.Draw(im)

    cells = make_next_cells(cells)
    for r in range(num_rows):
      for c in range(num_cols):
        item = cells[r][c]
        if item == 1:
          x0 = margin + size * c
          y0 = margin + size * r
          x1 = x0 + size
          y1 = y0 + size
          draw.rectangle((x0, y0, x1, y1), fill = color_life, outline = None, width = 0)
    images.append(im)

  images[0].save('lifegame.gif',
    save_all = True,
    append_images = images[1 : ],
    optimize = False,
    duration = 100,
    loop = 1 # 0だと無限
  )

def make_next_cells(cells):
  num_rows = len(cells)
  num_cols = len(cells[0])
  cells_next = [[0] * num_cols for i in range(num_rows)]
  for r in range(num_rows):
    for c in range(num_cols):
      num_lives = 0
      for j in range( - 1, 2):
        for i in range( - 1, 2):
          if not (i == 0 and j == 0):
            a = (c + i) % num_cols
            b = (r + j) % num_rows
            if cells[b][a] == 1:
              num_lives += 1

      if cells[r][c] == 0 and num_lives == 3 : # 誕生
        cells_next[r][c] = 1
      elif cells[r][c] == 1 and 2 <= num_lives <= 3 : # 生存
        cells_next[r][c] = 1
      elif cells[r][c] == 1 and (num_lives <= 1 or 4 <= num_lives) : # 過疎、過密
        cells_next[r][c] = 0
  return cells_next

def make_start_cells(num_cols, num_rows):
  num_lives_to_set = int(num_cols * num_rows * 0.5) # 0.5はマスの半分を埋める。
  cells = [[0] * num_cols for i in range(num_rows)]
  for i in range(num_lives_to_set):
    r = random.randint(0, num_rows - 1)
    c = random.randint(0, num_cols - 1)
    cells[r][c] = 1
  return cells

if __name__ == "__main__":
  main()

[ 2023年3月5日 | カテゴリー: Python | タグ: , ]

« | »

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

送信してください。


タグ

カテゴリー

最近の投稿

最近のコメント

固定ページ

アーカイブ

stabucky

写真

メタ情報