ゲームに学ぶフレームワーク #3.9: モジュール分割:リファクタリング

前の記事記事一覧次の記事

ゲームに学ぶ Jython/Swing フレームワーク《Jython2.5》
モジュール分割:リファクタリング

《著》森こねこ+小粒ちゃん《監修》小泉ひよ子とタマゴ倶楽部
第1版♪2003/05/23 ● 第2版♪2009/04/03

■ 概要

アプリケーションを作成する過程を通して、Jython/Swing によるフレームワークを習得します。

典型的なオセロゲームから始めて、蜂の巣(6角形)状の盤面を作り、3人で対戦できるゲームへと進化させます。

《Note》JPython1.1.x/Jython2.1.x 用に作成したセミナー課題を、Jython2.5 で再構成しました。

事例:モジュールを起動する

モジュールを起動すると、次のようなウィンドウが現れます。ここでは、空いたマス目というだけでなく「隣接する石の色が異なる」なら石を置けることと、その石が交互に(黒/白)変化することを確認します。

$ jython2.5.0 -i step08/othelloEx.py 


初期設定された4つの石の上には、他の石(黒/白)を置けません。また、隣接する石に異なる色がないマス目にも置けません。


最初に、空いたマス目には「黒」石を置けます。ただし、挟んだはずの「白」が「黒」に変化しないのは問題です。


次に、空いたマス目には「白」石を置けます。置ける石が「黒」から「白」に変化したのを確認できます。


ただし、前述した事例と違って、このような石の配置はできなくなります。


》作業中です《

事例:Java の世界を Jython から観察する

実行中の Java アプリケーションの状態を、Jython の対話モードで確認できるので便利です。

>>> view = Xview
>>> view
java.awt.Canvas[canvas0,0,0,200x128]

大域変数 Xview を介して、Canvas を参照できます。すると、キャンバスの大きさ(幅x高さ)が 200x128 になっているのが分かります。ここで、次に示すコードの断片と比較してください。すると、幅 150 のウィンドウを指定したのに対して、実際にはキャンバスの幅が狭くなっているのが分かります。

事例:コードの解説

■ モジュール:othelloModel.py
class Model(object):
    def __repr__(self):
        s = self.state
        return "%s(%d,%d,%r)"%(self.__class__.__name__,
            self.geom.x, self.geom.y, ("BW"[not s], "_")[s == None])

石の状態(黒/白)を確認できます。

《Note》3項演算子に代わる「定石」を踏襲しています。

■ モジュール:othelloView.py
class GameBoard(Canvas):
    ...
    _offset = [(x, y)
        for y in range(-1, 2)
        for x in range(-1, 2)
        if x or y
        ]    
    def _mouseClicked(self, e):
        point = Point(e.x, e.y)
        for k, stone in self.stones.items():
            if stone.geom.contains(point):
                break
        if self.isValid(k, stone):
            stone.state = self._current
            self._current = not self._current
            self.repaint()
        else:
            raise Exception("*** (x.x) too bad ***")

    def isValid(self, k, e):
        return e.state == None and self.detect(k, e)

リファクタリングにより、条件式を独立したメソッド isValid として抽出します。

    def detect(self, key, model):
        s = []
        X, Y = key
        state = not self._current
        for x, y in self._offset:
            m = self.items[(X+x, Y+y)]
            if m.state == state:
                s.append(((X+x, Y+y), m))
        return s

隣接(8連結性)するマス目の中から、異なる色を持つ石だけを収集します。

contents