《付録》HoneyComb3.py

# -*- coding: utf-8 -*-
#===============================================================================
#    Copyright (C) 2000-2008, 小泉ひよ子とタマゴ倶楽部
#
# Change History: WPF examples
#    2008/01/25, IronPython 1.1.1 (download)
#    2008/08/22, IronPython 1.1.2 (download)
#    2008/03/16, ver.2.0, WPF
#    2008/00/00, ver.2.1, IronPython 1.1.2 
# Change History: Games
#    1988/05, Smalltalk
#    2004/09, Java
#    2005/02, C#
#    2005/03, Jython
#===============================================================================

from hexagon import HexStone
from HoneyContext import *

## --------------------               
class Ostone(object):
    _bounds = (1, -2), (2, 0), (1, 2),
    _bounds = list(_bounds)+[(-x, -y) for x, y in _bounds]

    onColor  = Cyan ;
    offColor = Black;

    def __init__(self, client, x, y, state, Stroke=None, Fill=None):
        self.client = client
        self.name  = self._name (x, y)
        self.shape = self._shape(x, y, Stroke, Fill)
        self.neighbors = [None]*6

    def __repr__(self):
        return self.name
        
    def _name(self, x, y):
        s1 = s2 = "_%d"
        if x<0: x = -x; s1 = "_"+s1; 
        if y<0: y = -y; s2 = "_"+s2; 
        return (s1+s2)%(x, y)

    def _shape(self, x, y, Stroke, Fill):
        gap = 1
        x = HexStone._dx + x * (HexStone._width +gap)
        y = HexStone._dy + y * (HexStone._height+gap)

        s = Polygon(
            Name=self.name,
            HorizontalAlignment=HorizontalAlignment.Center,
            VerticalAlignment=VerticalAlignment.Center,
            Stroke=Stroke,
            Fill=Fill,
            Points=self.pointCollection([Point(x+dx*2, y+dy*2)
                for dx, dy in HexStone(x, y, False).vertices]),
            )
        s.MouseDown += self.mouseDown
        s.MouseUp   += self.mouseUp
        return s

    def mouseDown(self, sender, e):
        print ">>>", sender.Name, sender.Fill

    def mouseUp(self, sender, e):
        self._turnOff()
        self._reset()

        off, on = self.offColor, self.onColor;
        s = self.shape.Stroke                ;
        self.shape.Stroke = (off, on)[s == off]

        self._setUp()
        self._turnOn()

    def update(self, offset):
        self._turnOff()
        target = self.neighbors[offset]
        if target:
            self._setUp([self]+target._detect(offset)) 
            self._turnOn()
        
    def _detect(self, offset):
        s = [self]
        pivot = self.neighbors[offset]
        if pivot:
            s += pivot._detect(offset)
        return s

    def _reset(self):
        self.client.reset(self)

    def _setUp(self, targets=None):
        if not targets: targets = self._detect(0)
        self.client.setUp(targets)

    def _turnOn(self):
        self._turn(self.onColor)
        
    def _turnOff(self):
        self._turn(self.offColor)
        
    def _turn(self, color):
        self.client.turnOver(color)

    def pointCollection(self, vertices):
        s = PointCollection()
        for e in vertices:
            s.Add(e)
        return s

    def addNeighbors(self, x, y, matrix):
        self._clearNeighbor()
        for i, (dx, dy) in enumerate(self._bounds):
            e = matrix[self._name(x+dx, y+dy)]
            e.neighbors[(i+3)%6] = self
            self._addNeighbor(e)

    def _clearNeighbor(self):
        self.neighbors = []

    def _addNeighbor(self, cell):
        self.neighbors.append(cell)

## --------------------               
class CombStone(Ostone):
    def __init__(self, client, x, y):
        super(self.__class__, self).__init__(client, x, y, state=False,
            Stroke=Brushes.Black, Fill=Brushes.Green)

class BlackStone(Ostone):
    def __init__(self, client, x, y):
        super(self.__class__, self).__init__(client, x, y, state=False,
            Stroke=Brushes.Black, Fill=Brushes.Black)

class WhiteStone(Ostone):
    def __init__(self, client, x, y):
        super(self.__class__, self).__init__(client, x, y, state=False,
            Stroke=Brushes.Black, Fill=Brushes.White)
    
class NullStone(Ostone):
    def __init__(self, client, x, y):
        super(self.__class__, self).__init__(client, x, y, state=False,
            Stroke=Brushes.Gray, Fill=None)
    
## --------------------               

第7章 オセロゲーム(trinity/hexagon)8/24, IronPython

記事一覧 C#.use(better, IronPython=”WPF”)

IronPython で学ぶ WPF プログラミングの世界

《著》小粒ちゃん《監修》小泉ひよ子とタマゴ倶楽部
第3版♪2008/04/28


等方向に隣接するオブジェクト群を検出する

ゲーム版に生息するオブジェクト群は、自分と隣接する存在だけを知っています。また、これらのオブジェクト群はマトリックス管理のもとで、特定の座標系には依存しません。


相手の領地を奪うときには、特定の方向に自分の領地があるかを知る必要があります。その場合にも「オフセット」を使って、任意の方向にある他のオブジェクト群の存在を把握できます。


たとえば、左下方向にあるオブジェクトを知るには、オフセット位置3にあるコレクション内の要素だけを、順に参照すればよいことが分かります。

《NOTE》これらは離散系の極座標と見なせます。つまり、整数だけを値とする極座標として表現されます。□

《TIPS》伝統的な手法(2次元配列などを使う)と比べてみるのも一興です。ここで着目して欲しいのは「要求仕様の変更に際して柔軟に対処できるか」ということです。もしそうでないなら、再考の余地があります。□

オリジナル仕様に準拠した(Smalltalk/Smalltalk 版、Swing/Jython 版)では、隣接するオブジェクト群をコレクションを介して管理しています。すると、今回の仕様変更では、その要素数が8から6へと変化しただけだと分かります。つまり、要求仕様の変更に際して、柔軟に対処できることを再確認したことになります。

class Ostone(object):
    def mouseUp(self, sender, e):
        self._turnOff()
        self._reset()
        off, on = self.offColor, self.onColor;
        s = self.shape.Stroke                ;
        self.shape.Stroke = (off, on)[s == off]
        self._setUp()
        self._turnOn()

マウス操作をしたときに、等方向に隣接するオブジェクト群を強調(色の変化)します。

    def update(self, offset):
        self._turnOff()
        target = self.neighbors[offset]
        if target:
            self._setUp([self]+target._detect(offset)) 
            self._turnOn()

マウス操作に伴って、等方向に隣接するオブジェクト群を強調(色の変化)します。これらの変化は、時計回り(反時計回り)に on/off を繰り返します。

    def _detect(self, offset):
        s = [self]
        pivot = self.neighbors[offset]
        if pivot:
            s += pivot._detect(offset)
        return s

同じオフセット値 offset を持ち、等方向に隣接するオブジェクト群を順に獲得します。これを再帰呼び出し _detect によって実現しています。

》こちらに移動中です《
TOP


関連記事

Last updated♪2009/12/02