ライフゲーム(C++版)

C++にてライフゲームを作成した。
全ソースのダウンロード

ビルド方法

Unix系OSにてビルドすることを想定している。
以下のコマンドが必要。

  • g++
  • make

以下コマンドを実行することによってビルド可能。

%cd ./LifeGame/C++/source  
%make 

ビルドが成功すると以下のバイナリファイルが出来上がる。

  • LifeGame

実行方法

コマンドラインから以下を実行する。

%./LifeGame

実行すると以下のような画面となる。  
ライフゲーム実行

このLifeGameはcursesを利用している。
このLifeGame内でのコマンドを以下に示す。

q: LifeGame終了
s: LifeGameスタート
p: LifeGame一時停止
i: セルの生死を設定(LifeGame一時停止状態の場合有効)
k: カーソルを上へ移動
j: カーソルを下へ移動
h: カーソルを左へ移動
l: カーソルを右へ移動

※カーソルの移動はviと同じ

プログラムソース

このプログラムはデザインパターンのオブザーバーパターンを利用している。
doxygenにてプログラムソース内のコメントからドキュメントを作成した。

UML

クラス図とシーケンス図を作成した。

UML作成にはastah* communityを利用した。

オブザーバーパターン(デザインパターン)適用例

オブザーバーパターン適用例(TinyClock GUI版)

概要

  • デザインパターンのオブザーバーパターンを時計アプリへの適用例をPythonコードで示す。
  • デジタル時計とアナログ時計を表示するアプリを作成した。 GUIで表示することとする。
  • このアプリをTinyClockと呼ぶこととする。
  • TinyClockはMVC(Model-View-Controller)で作成することとする。(実際にはModel-View)

実行

実行方法

  • 実行方法は、コマンドラインから以下を実行。
    • %python TinyClockMain_gui.py

実行イメージ

  • TinyClockMain_guiを実行すると以下のように表示される。
    TinyClock(GUI版)実行イメージ

TinyClock(GUI版) Python全ソースコード

以下URLに全ソースコードを保存している。
TinyClock(GUI版)

ディレクトリ構成

ソースコードのディレクトリ構成を以下に示す。

.
└── sources // ソースコードファイルを保存したディレクトリ
├── Lib
│ └── Observer.py // Observerパターン Pythonソースコード

├── Model
│ ├── Lib -> ../Lib // シンボリックリンク(1つ上のディレクトリのLib)
│ └── TinyClockModel.py // 時計本体部 Pythonソースコード

├── View
│ ├── GUI // GUI mainwindow.ui以外使用しない
│ │ ├── GUI.pro // Qt Creatorファイル
│ │ ├── GUI.pro.user
│ │ ├── main.cpp
│ │ ├── mainwindow.cpp
│ │ ├── mainwindow.h
│ │ └── mainwindow.ui // GUI メインウィンドウ XML(Qt Creatorで自動生成される)
│ │
│ ├── Lib -> ../Lib // シンボリックリンク(1つ上のディレクトリのLib)
│ ├── TinyClockView.py // 時計表示部(データ保持)
│ ├── TinyClockViewGUI.py // 時計表示部(GUI)
│ └── mainwindow.py // mainwindow.uiをPythonソースコードへ変換したもの

└── main_gui.py // GUI用 main関数(本ファイルをpythonで実行するとデジタル時計とアナログ時計をGUI表示する)

UML

クラス図とシーケンス図を以下に示す。

クラス図

TinyuClock(GUI版)クラス図

シーケンス図

TinyClock(GUI版)シーケンス図

TinyClockModel Pythonソースコード(一部抜粋)

  • TinyClockModelクラスは、MVCモデルのModel部である。
  • TinyClockModelクラスは、Sujectクラスを継承する。
  • TinyClockModelクラスのset_timeメソッドで以下を行う。
    • 現在時刻取得
    • Subjectクラスから継承しているnotifyメソッドを呼ぶ
  • notifyメソッドを呼ぶことによって、登録されている全Observerへ通知を行う。
  • ソースコードの詳細はTinyClockModel.pyを参照。

TinyClockModelクラスのソースコード一部抜粋を以下に示す。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class TinyClockModel(Subject):
"""
@brief 時計本体部 クラス.
@note Subjectクラスを継承.
時刻を取得し, 表示部へ通知する.
"""


# (中略) #

def set_time(self):
"""
@brief 現在時刻を設定.
@return なし.
@note 現在時刻をobserverへ更新を通知.
"""

self._now = datetime.datetime.today()
self.notify(self)

TinyClockView Pythonソースコード(一部抜粋)

  • TinyClockViewクラスは、MVCモデルのView部である。
  • TinyClockViewクラスは、Observerクラスを継承する。
  • TinyClockViewクラスは、表示データを保持するクラスである。
  • TinyClockViewクラスのupdateメソッドでは、以下を行う。
    • Subjectクラスからの通知を受け取る
    • 表示用データの保存メソッドであるset_timeを呼ぶ
  • ソースコードの詳細はTinyClockView.pyを参照。

TinyClockViewクラスのソースコード一部抜粋を以下に示す。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class TinyClockView(Observer):
"""
@brief 時計表示部(表示データ保持).
@note Observerクラスを継承.
"""


# (中略) #

def update(self, modifier=None):
"""
@brief Subjectから通知を受け取るメソッド.
@param modifier 更新情報.
@note Observerクラスのメソッドをオーバーライド.
"""

self.set_time(modifier)

TinyClockViewGUI Pythonソースコード(一部抜粋)

TinyDigitalClockView

  • TinyDigitalClockViewクラスは、デジタル時計のGUI表示部である。
  • TinyDigitalClockViewクラスは、メンバー変数としてTinyClockViewクラスを持つ。
  • TinyDigitalClockViewクラスのdraw_viewメソッドは、デジタル時計を描画する。
  • ソースコードの詳細はTinyClockViewGUI.pyを参照。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class TinyDigitalClockView(QtGui.QWidget):
"""
@brief デジタル時計 GUI表示部 クラス.
@note 以下クラスを継承.
TinyClockView
QtGui.QWidget
"""

def __init__(self, parent=None):
"""
@brief 初期化.
"""

QtGui.QWidget.__init__(self)
self.m_TinyClockView = TinyClockView()

def draw_view(self):
"""
@brief デジタル時計を描画.
"""

#時間を設定.
theTime = QtCore.QTime(self.m_TinyClockView.hour,
self.m_TinyClockView.min,
self.m_TinyClockView.sec)
self.m_DateTimeEdit.setTime(theTime)

# (中略) #

TinyAnalogClockView

  • TinyAnalogClockViewクラスは、アナログ時計のGUI表示部である。
  • TinyAnalogClockViewクラスは、メンバー変数としてTinyClockViewクラスを持つ。
  • TinyAnalogClockViewクラスのdraw_viewメソッドは、アナログ時計を描画する。
  • ソースコードの詳細はTinyClockViewGUI.pyを参照。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class TinyAnalogClockView(QtGui.QWidget):
"""
@brief アナログ時計 GUI表示部 クラス.
@note 以下クラスを継承.
TinyClockView
QtGui.QWidget
"""

def __init__(self, parent=None):
"""
@brief 初期化.
"""

#スーパークラスを初期化.
QtGui.QWidget.__init__(self, parent=parent)

self.m_TinyClockView = TinyClockView()

def draw_view(self):
"""
@brief アナログ時計を描画.
"""

#クリア.
self._draw_clear()
#長針を描画.
self._draw_hour_needle(self.m_TinyClockView.hour)
#短針を描画.
self._draw_min_needle(self.m_TinyClockView.min)
#秒針を描画.
self._draw_sec_needle(self.m_TinyClockView.sec)
#日付を更新.
self._draw_date()
#選択を解除.
self.m_DateEdit.setCurrentSectionIndex(self.m_DateEdit.NoSection)

#再描画指示(再描画イベントを発行)
self.repaint()

# (中略) #

mainwindow.py Pythonソースコード

  • GUI部分はQtを利用している。Qt Creatorを利用している。
  • Qt Creatorでフォームをデザインするとmainwindow.uiが作成される。
  • mainwindow.uiはXMLである。
  • mainwindow.uiからmainwindow.pyのPythonソースコードに変換した。
  • Mac OSXでは以下のコマンドで変換可能。
    • %/Library/Python/2.7/site-packages/PyQt4/uic/pyuic.py -o mainwindow.py mainwindow.ui

TinyClockMain_gui Pythonソースコード

  • Subjectクラスのattachメソッドで、時計本体部と表示部を接続している。
  • タイマーを設定し、以下を実行する。
    • 時刻設定
    • デジタル時計再描画
    • アナログ時計再描画
  • ソースコードの詳細はTinyClockMain_gui.pyを参照。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class ClockViewWidget(QtGui.QMainWindow, Ui_MainWindow):
"""
@brief TinyClock GUI版を表示する為のウィジェット.
"""


def __init__(self, *args, **kw):
"""
@brief 初期化.
"""

#スーパークラスの初期化.
QtGui.QMainWindow.__init__(self, *args, **kw)
self.setupUi(self)

#時計本体部を生成.
self.ClockModel = TinyClockModel()

#デジタル時計表示部を生成.
self.DigitalClock = TinyDigitalClockView()
self.DigitalClock.setup_ui(self.dateTimeEdit)

#アナログ時計表示部を生成.
self.AnalogClock = TinyAnalogClockView(self.widget)
self.AnalogClock.setup_ui(self.dateEdit)

#時計 本体部 と 表示部(データ保持部) を接続
self.ClockModel.attach(self.DigitalClock.m_TinyClockView)
self.ClockModel.attach(self.AnalogClock.m_TinyClockView)

#タイマーを設定.
self.timer = QtCore.QTimer(parent=self)
self.timer.setInterval(1*1000)

#タイマーを設定(時計本体部と接続. 1000msec毎に時刻を設定).
self.timer.timeout.connect(self.ClockModel.set_time)

#タイマーを設定(デジタル時計時計表示部と接続. 1000msec毎に時刻を表示).
self.timer.timeout.connect(self.DigitalClock.draw_view)

#タイマーを設定(アナログ時計時計表示部と接続. 1000msec毎に時刻を表示).
self.timer.timeout.connect(self.AnalogClock.draw_view)

#タイマースタート.
self.timer.start()


def main():
"""
@brief TinyClock GUI版 main処理.
"""

app = QtGui.QApplication(sys.argv)

panel = ClockViewWidget()

main_window = QtGui.QMainWindow()
main_window.setGeometry(0, 0, panel.width(), panel.height())
main_window.setWindowTitle("TinyClock")
main_window.setCentralWidget(panel)
main_window.show()

app.exec_()

オブザーバーパターン(デザインパターン)適用例

オブザーバーパターン適用例(TinyClock Console版)

概要

  • デザインパターンのオブザーバーパターンを時計アプリへの適用例をPythonコードで示す。
  • デジタル時計とアナログ時計を表示するアプリを作成した。
  • このアプリをTinyClockと呼ぶこととする。
  • TinyClockはMVC(Model-View-Controller)で作成することとする。(実際にはModel-View)

実行

実行方法

  • 実行方法は、コマンドラインから以下を実行。
    • %python TinyClockMain_console.py
  • プログラムは無限ループになっているので、C-cで強制終了。

実行イメージ

  • TinyClockMain_consoleを実行すると以下のように表示される。
    TinyClock(console版)実行イメージ

TinyClock(console版) Python全ソースコード

以下URLに全ソースコードを保存している。
TinyClock(Console版)

ディレクトリ構成

ソースコードのディレクトリ構成を以下に示す。

.
└── sources // ソースコードファイルを保存したディレクトリ
├── Lib
│ └── Observer.py // Observerパターン Pythonソースコード

├── Model
│ ├── Lib -> ../Lib // シンボリックリンク(1つ上のディレクトリのLib)
│ └── TinyClockModel.py // 時計本体部 Pythonソースコード

├── View
│ │
│ ├── Lib -> ../Lib // シンボリックリンク(1つ上のディレクトリのLib)
│ └── TinyClockView.py // 時計表示部(データ保持)

└── TinyClockMain_console.py // コンソール用 main関数(本ファイルをpythonで実行するとコンソールに時刻を表示する)

UML

クラス図とシーケンス図を以下に示す。

クラス図

TinyuClock(console版)クラス図

シーケンス図

TinyClock(console版)シーケンス図

TinyClockModel Pythonソースコード(一部抜粋)

  • TinyClockModelクラスは、MVCモデルのModel部である。
  • TinyClockModelクラスは、Sujectクラスを継承する。
  • TinyClockModelクラスのset_timeメソッドで以下を行う。
    • 現在時刻取得
    • Subjectクラスから継承しているnotifyメソッドを呼ぶ
  • notifyメソッドを呼ぶことによって、登録されている全Observerへ通知を行う。
  • ソースコードの詳細はTinyClockModel.pyを参照。

TinyClockModelクラスのソースコード一部抜粋を以下に示す。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class TinyClockModel(Subject):
"""
@brief 時計本体部 クラス.
@note Subjectクラスを継承.
時刻を取得し, 表示部へ通知する.
"""


# (中略) #

def set_time(self):
"""
@brief 現在時刻を設定.
@return なし.
@note 現在時刻をobserverへ更新を通知.
"""

self._now = datetime.datetime.today()
self.notify(self)

TinyClockView Pythonソースコード(一部抜粋)

  • TinyClockViewクラスは、MVCモデルのView部である。
  • TinyClockViewクラスは、Observerクラスを継承する。
  • TinyClockViewクラスは、表示データを保持するクラスである。
  • TinyClockViewクラスのupdateメソッドで以下を行う。
    • Subjectクラスからの通知を受け取る
    • 表示用データの保存メソッドであるset_timeを呼ぶ
  • ソースコードの詳細はTinyClockView.pyを参照。

TinyClockViewクラスのソースコード一部抜粋を以下に示す。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class TinyClockView(Observer):
"""
@brief 時計表示部(表示データ保持).
@note Observerクラスを継承.
"""


# (中略) #

def update(self, modifier=None):
"""
@brief Subjectから通知を受け取るメソッド.
@param modifier 更新情報.
@note Observerクラスのメソッドをオーバーライド.
"""

self.set_time(modifier)

TinyClockMain_console Pythonソースコード

  • TinyClockMain_consoleは、以下クラスをインスタンス化し、制御する。
    • TinyClockModel
    • TinyClockView
  • 時計本体部(TinyClockModel)を以下でインスタンス化
    • theModel = TinyClockModel()
  • アナログ時計及びデジタル時計をインスタンス化している。
    • theAnalogClockView = TinyClockView()
    • theDigitalClockView = TinyClockView()
  • Subjectクラスのattachメソッドで、時計本体部と表示部を接続している。
  • 時計表示用にスレッドを生成し、各時計独立で表示するようにしている。
  • ソースコードの詳細はTinyClockMain_console.pyを参照。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def main():
"""
@brief TinyClock console版 main処理
@note 以下を別スレッドを生成して時刻を表示する.
アナログ時計
デジタル時計
スリープを使用してスレッドを切り替えている為,
スレッドの同期はとっていない.
"""

#時計本体部を生成.
theModel = TinyClockModel()
#アナログ時計表示部を生成.
theAnalogClockView = TinyClockView()
#デジタル時計表示部を生成.
theDigitalClockView = TinyClockView()

#時計 本体部と表示部接続.
theModel.attach(theAnalogClockView)
theModel.attach(theDigitalClockView)

#アナログ時計表示部のスレッドを生成.
theAnalogClockViewThread= threading.Thread(target=refresh_view, name="AnalogClock", args=[theAnalogClockView])
theAnalogClockViewThread.setDaemon(True)
theAnalogClockViewThread.start()

#デジタル時計表示部のスレッドを生成.
theDigitalClockViewThread = threading.Thread(target=refresh_view, name="DigitalClock", args=[theDigitalClockView])
theDigitalClockViewThread.setDaemon(True)
theDigitalClockViewThread.start()

while 1:
theModel.set_time()
#1秒スリープ.
time.sleep(1.0)

オブザーバーパターン(デザインパターン)

デザインパターンのオブザーバーパターンのメモ

  • オブザーバーパターンを使用すると疎結合なアプリケーションを作成可能。
     (GUIのアプリケーションでよく使用されている。)
  • オブザーバーパターンは、「通知者」から「観測者」に状態を通知する。
  • オブザーバーパターンのメリットとしては、観測者は通知を受け取った場合に動作する。
     (ポーリングしなくともよい。)
  • 通知者をSubjectクラス、観測者をObserverクラスとする。
  • Subjectクラスは、Observerクラスを持つ。
  • Subjectクラスは、Observerクラスを複数持ってもよい。この場合、SubjectクラスはすべてのObserverクラスへ通知を行う。

Observerパターンのクラス図

ObserverPattern クラス図

ObserverクラスのPythonソースコード

  • Observerクラスは、Subjectクラスから通知を受け取る。
  • 抽象クラスの為、インスタンスは作成しないこと。
  • Subjectクラスからの通知は、updateメソッドで受け取る。
  • updateメソッドは、継承したクラスでオーバーライドする。
  • ソースコードの詳細はObserver.pyを参照。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Observer(object):
"""
@brief オブザーバークラス.
更新があった場合, Subjectから通知を受け取るクラス.
@note 抽象クラス. インスタンスは作成しないこと.
"""


def update(self, modifier=None):
"""
@brief Subjetから通知を受け取るメソッド.
@param modifier 更新情報.
@note 本メソッドは継承したクラスでオーバーライドすること.
"""

raise NotImplementedError

SubjectクラスのPythonソースコード(一部抜粋)

  • Subjectクラスは、登録されているObserverクラス全てに通知をする。
  • Observerクラスを登録するには、attachメソッドを使用する。
  • Observerクラスに通知するには、notifyメソッドを使用する。
  • ソースコードの詳細はObserver.pyを参照。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Subject(object):
"""
@brief サブジェクトクラス.
更新があった場合, Observerへ通知するクラス.
"""


def __init__(self):
"""
@brief 初期化.
@param メンバー変数 self._observerList 登録されたオブザーバーリスト.
"""

self._observerList = []

def attach(self, observer):
"""
@brief Observerを登録する.
@param observer 登録するオブザーバー.
@return なし.
"""

if not observer in self._observerList:
self._observerList.append(observer)

def notify(self, modifier=None):
"""
@brief Observerへ更新を通知するメソッド.
@param modifier 更新情報.
"""

for observer in self._observerList:
if observer != modifier:
observer.update(self)

参考文献

17.Observer パターン | TECHSCORE(テックスコア)