Help us understand the problem. What is going on with this article?

# Python に Curses ライブラリがあったので，シンプルなライフゲームを作ってみるテスト

More than 3 years have passed since last update.

# 1.この記事を読んで学べること・学べないこと

- Python における Curses 利用の初歩の初歩。
- ライフゲーム製作の一例。

- 優れたPython コードの書き方。
- 優れたライフゲームのアルゴリズム。

# 2.実際のコード

lifegame.py
```class Life:

def __init__(self, state=False):
"""
State means whether the life is alive or not.
Count means how many lives there are around the life.
Survive means whether the life survives this turn.
"""
self.count = 0
self.state = state
self.survive = False

def rule(self):
""" The core rule of this life game. """
if self.state:
if self.count in {2,3}:
self.survive = True
else:
self.survive = False
else:
if self.count is 3:
self.survive = True
else:
self.survive = False

def update(self):
""" Return True or False.
Update the state of the life after checking if it will
survive or not.
"""
self.state = self.survive
self.count = 0
return self.survive

class Environment(list):

def __init__(self, directory):
""" Initialize the array with loaded text data. """
self.life_count = 0
super().__init__(self)
for y in range(self.height):
self.append([])
for x in range(self.width):
if self.is_there_a_life_in( text_env[y][x] ):
self[y].append(Life(True))
else:
self[y].append(Life(False))

def is_there_a_life_in(self, string):
""" Return True or False.
Text data to load must be composed of two characters '*' and
'_'. '*' means there is life. '_' means life is dead.
"""
if string is "*":
return True
elif string in {"_", None}:
return False
else:
raise TypeError("Undefined Char Used.")

""" Return list of string.
Load text data from file and calculate size of where lives
are simulated.
"""
self.width = 0
text_env = []
for char_list in self.parse_map(directory, "r"):
if self.width < len(char_list):
self.width = len(char_list)
text_env.append(char_list)
self.height = len(text_env)
return text_env

def parse_map(self, directory, mode):
""" Strips '\n' off read line. """
for line in open(directory, mode):
yield list(line.rstrip('\n'))

def how_many_lives(self):
""" Count up the lives around the life. """
for y in range(self.height):
for x in range(self.width):
for j, i in self.surround(y, x):
if self[j][i].state:
self[y][x].count += 1
self[y][x].rule()

def surround(self, y, x):
""" Generate coordinates around the life. """
from itertools import product
Y = ( y-1, y, y+1 )
X = ( x-1, x, x+1 )
for j,i in product(Y, X):
j = j % self.height
i = i % self.width
if (j, i) == (y, x):
continue
else:
yield (j, i)

def update(self):
""" Update each cell and count the number of life in the
Environment.
"""
self.life_count = 0
for y in range(self.height):
for x in range(self.width):
if self[y][x].update():
self.life_count += 1

class LifeGame:

def __init__(self, directory):
self.env = Environment(directory)
self.turn = 0

from curses import wrapper
wrapper(self.main) # main メソッドを stdscr オブジェクトを与えて呼び出す

def next_turn(self):
self.env.how_many_lives()
self.env.update()

def show_status(self, stdscr):
""" Print number of life in the environment and how many
turn has passed.
"""
"LifeCount: %d" % self.env.life_count)
"Generation: %d" % self.turn)

def main(self,stdscr):

while True:
stdscr.clear()　# コンソール画面の初期化（黒板を消すの感じ）
for y in range(self.env.height):
for x in range(self.env.width):
if self.env[y][x].state:
stdscr.addstr( y, x, "*" ) # コンソールに出力するメソッド
else:
self.show_status(stdscr)
stdscr.refresh() # 出力内容の反映
if stdscr.getch(): # Enter 入力待ち
self.next_turn()
self.turn += 1

if __name__=='__main__':

LifeGame("./map.txt")

```

これに例えば，

map.txt
```_*_
__*
***
```

こんなデータを与えてあげると，Enter を押すごとに変わりゆく様子を観察できる。

# 3.雑感

前に Ruby で Curses に挑んだときは挫折してしまったのだけれど，Python でやってみたらなんかできちゃった。Python が素敵なのか，その頃より少し技術力が上がったのか...

Why not register and get more from Qiita?
1. We will deliver articles that match you
By following users and tags, you can catch up information on technical fields that you are interested in as a whole
2. you can read useful information later efficiently
By "stocking" the articles you like, you can search right away