読者です 読者をやめる 読者になる 読者になる

Cattleya's Diary

勉強してきたことの備忘録として更新していきます。書いてるのは大学生です。

Pythonでライフゲームを作った(Life Game on Terminal by Python programming)

Programming

 最近ライフゲームというボードゲーム(?)があることを知り、自分もプログラムを書いて遊んでみた。

ライフゲームとは

 生命の誕生、進化、淘汰などのプロセスを簡易的なモデルで再現したシミュレーションゲームの1つ。格子状のボードを用意し、その一つ一つを細胞に見立てる。各細胞は「生」か「死」のいずれかの状態を持ち、周囲の細胞の状態により、次の状態が決定される。

ある細胞Xは周囲の細胞8つの内、生きた細胞の個数Cによって次の状態が決まる。

  • 過疎: C ≦ 1 の場合、Xの次の状態は「死」となる。
  • 維持: C = 2 の場合、Xの状態は変化しない。
  • 誕生: C = 3 の場合、Xの次の状態は「生」となる。
  • 過密: C ≧ 4 の場合、Xの次の状態は「死」となる。

ボードの領域外の細胞は「死」であるものとして扱った。

# lifegame.py

import time
import subprocess
import copy
from termcolor import *


class Board():

    def __init__(self, size, init_state):
        self.size = size
        self.current_state = init_state
        self.next_state = [[-1 for i in range(self.size)] for j in
                           range(self.size)]

    def __check_state(self):
        for i in range(self.size):
            for j in range(self.size):
                if self.next_state[i][j] != self.current_state[i][j]:
                    return True
        print('It is still life!')
        return False

    def __gen_next_state(self):

        def __count_living_cell(current_state, i, j):
            living_cell = 0
            for x in range(i - 1, i + 2):
                if x < 0 or x > self.size - 1:
                    continue
                for y in range(j - 1, j + 2):
                    if y < 0 or y > self.size - 1:
                        continue
                    living_cell += current_state[x][y]
            return living_cell - current_state[i][j]

        for row in range(self.size):
            for col in range(self.size):
                count = __count_living_cell(self.current_state, row, col)
                if count <= 1:
                    self.next_state[row][col] = 0
                elif count == 2:
                    self.next_state[row][col] = self.current_state[row][col]
                elif count == 3:
                    self.next_state[row][col] = 1
                else:
                    self.next_state[row][col] = 0
        if self.__check_state():
            self.current_state = copy.deepcopy(self.next_state)
        else:
            exit()

    def __show_state(self):
        for i in range(self.size):
            for j in range(self.size):
                if self.current_state[i][j] == 1:
                    value = 9632; color = 'green'
                else:
                    value = 9633; color = 'white'
                cprint('{}'.format(chr(value)), color, end='')
            print()
        time.sleep(1)

    def __check_extinction(self):
        for i in range(self.size):
            for j in range(self.size):
                if self.current_state[i][j] == 1:
                    return True
                else:
                    continue
        return False

    def run(self):
        t = 0
        while t < 1000:
            subprocess.call('clear')
            print('time: {}'.format(t))
            self.__show_state()
            if self.__check_extinction():
                self.__gen_next_state()
                t += 1
            else:
                print('Game Over ...')
                break
# main.py
#! /usr/bin/python

import lifegame
import random

def main():
    size = int(input('Enter the board size. :'))
    init_state = [[random.choice([1, 0]) for i in range(size)] for j in range(size)]
    game = lifegame.Board(len(init_state), init_state)
    game.run()

if __name__ == "__main__":
    main()

termcolorモジュールで色つけたけど、やっぱりPyQtとかTkinterとか使ってGUIにしたほうが見栄えも良さそう。出力をGUIにできるよう改良中。 f:id:nk06c-c-gw:20160718141849p:plain