Pythonでライフゲームを作りました
セルの初期状態をランダムに作成します。
結果はカレントディレクトリにGIFアニメーションで出力されます。
設定値
盤の大きさ:lifegame.pyのBOARD_SIZE
世代数:lifegame.pyのGENERATIONS
初期状態の生きているセルの割合:lifegame.pyのLIFE_RATE
GIFで表示するセルの大きさ:my_gif.pyのSQUARE_SIZE
GIFで表示する1世代の表示時間:DURATION(ミリ秒)
lifegame.py
import copy import my_gif import random #その座標がboardの範囲内にあるか? def is_on_board(row, column): return (0 <= row < BOARD_SIZE) and (0 <= column < BOARD_SIZE) #その座標に隣接するcellのリストを返す def adjacent_cells(row, column): cells = [] if is_on_board(row - 1, column - 1): cells.append((row - 1, column - 1)) if is_on_board(row - 1, column): cells.append((row - 1, column)) if is_on_board(row - 1, column + 1): cells.append((row - 1, column + 1)) if is_on_board(row, column - 1): cells.append((row, column - 1)) if is_on_board(row, column + 1): cells.append((row, column + 1)) if is_on_board(row + 1, column - 1): cells.append((row + 1, column - 1)) if is_on_board(row + 1, column): cells.append((row + 1, column)) if is_on_board(row + 1, column + 1): cells.append((row + 1, column + 1)) return cells #その座標の隣接するcellの中で生きているcellの数を返す def get_number_of_living_cells(board, row, column): n = 0 for r, c in adjacent_cells(row, column): if board[r][c] == LIFE: n += 1 return n #その座標の次の世代の状態を返す def next_state(board, row, column): number_of_living_cells = get_number_of_living_cells(board, row, column) if number_of_living_cells == 3: return LIFE elif number_of_living_cells == 2: return board[row][column] else: return DEATH #そのboardの次の世代のboardを返す def make_next_board(board): next_board = [[DEATH for i in range(BOARD_SIZE)] for j in range(BOARD_SIZE)] for row in range(BOARD_SIZE): for column in range(BOARD_SIZE): next_board[row][column] = next_state(board, row, column) return next_board #各世代のboardのリストを返す def make_boards_list(board): boards_list = [] boards_list.append(board) for i in range(GENERATIONS): next_board = make_next_board(board) boards_list.append(next_board) board = copy.deepcopy(next_board) return boards_list #生死の状態をランダムに作成したboardを返す def initialize_board(rate): board = [[DEATH for i in range(BOARD_SIZE)] for j in range(BOARD_SIZE)] for row in range(BOARD_SIZE): for column in range(BOARD_SIZE): if random.random() < rate: board[row][column] = LIFE else: board[row][column] = DEATH return board #main DEATH = 0 LIFE = 1 BOARD_SIZE = 10 GENERATIONS = 20 LIFE_RATE = 0.2 my_gif.make_gif(make_boards_list(initialize_board(LIFE_RATE)))
GIFアニメーションを作成するモジュール(my_gif.py)
from PIL import Image, ImageDraw SQUARE_SIZE = 20 DURATION = 500 def square_positions(row, column): x1 = column * SQUARE_SIZE y1 = row * SQUARE_SIZE x2 = column * SQUARE_SIZE + SQUARE_SIZE y2 = row * SQUARE_SIZE + SQUARE_SIZE return (x1, y1, x2, y2) def make_image(data): data_size_width = len(data[0]) data_size_height = len(data) image_size_width = SQUARE_SIZE * data_size_width image_size_height = SQUARE_SIZE * data_size_height im = Image.new("RGB", (image_size_width, image_size_height), 'white') draw = ImageDraw.Draw(im) for row in range(data_size_height): for column in range(data_size_width): if data[row][column] == 0: draw.rectangle(square_positions(row, column), fill='white') else: draw.rectangle(square_positions(row, column), fill='black') return im def make_gif(data_list): images = [] for data in data_list: images.append(make_image(data)) images[0].save('lifegame.gif', save_all=True, append_images=images[1:], duration=DURATION)