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
        text_env = self.load_from(directory)
        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.")

    def load_from(self, directory):
        """ 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.
        """
        stdscr.addstr( 3, self.env.width+3,
                "LifeCount: %d" % self.env.life_count)
        stdscr.addstr( 5, self.env.width+3,
                "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:
                        stdscr.addstr( y, x, "_" )
            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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした