《付録》HoneyCell.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
#===============================================================================
## --------------------               
class CombCell(object):
    def __init__(self):
        self.matrix = {}
        
    def addCell(self, cell):
        self._addMatrix(cell)
    
    def addNeighbors(self, cell, x, y):
        self._addMatrix(cell)
        cell.addNeighbors(x, y, self.matrix)
        
    def _addMatrix(self, cell):
        self.matrix[cell.name] = cell

## --------------------               

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

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

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

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


隣接するオブジェクト群を管理する

ゲーム盤を構成する各セルを一元管理するのが、Board です。


class Board(object):
    def __init__(self):
        self.matrix = {}

インスタンス属性 self.matrix は、各セルの名前(キー要素)とその実体(値要素)との対を管理します。このとき、キー要素は重複しない文字列を、値要素は Ostone の傘下にあるオブジェクトを対象にします。

   def addCell(self, cell):
        self._addMatrix(cell)

引数に指定されたセル cell を、追加登録します。

    def addNeighbors(self, cell, x, y):
        self._addMatrix(cell)
        cell.addNeighbors(x, y, self.matrix)

引数に指定されたセル cell を登録するとともに、その cell と隣接する他のセルとの対応関係を更新します。

    def _addMatrix(self, cell):
        self.matrix[cell.name] = cell

引数に指定されたセル cell をもとに、キーには重複しない文字列 cell.name を、値には cell そのものを登録します。

隣接するオブジェクト群を相互に設定する

新たなテストケースに沿って、隣接するオブジェクト群を相互に設定する必要が生じます。

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

クラス属性 _bounds は、隣接するオブジェクト群との相対位置を把握するのに「一度だけ」利用します。ここでは、オブジェクト群の点対称性を利用して、二段階を経て初期設定しています。相互の位置関係を形成した後はマトリックス管理のもとで、特定の座標系には依存せずに、オフセット位置だけで参照できるようになるので便利です。

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

インスタンス属性 self.neighbors を介して、隣接するオブジェクト群を管理します。

    def mouseDown(self, sender, e):
        on, off = Brushes.Magenta, Brushes.Black
        for e in self.neighbors:
            if not e: continue
            s = e.shape.Stroke
            e.shape.Stroke = (on, off)[s == on]

マウス操作をしたときに、隣接するオブジェクト群を強調(色の変化)します。これらはトグルになっていて、on/off 状態変化を繰り返します。

    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)

隣接するオブジェクト群との相対位置を用いて、相互参照可能です。つまり、自身 self が隣接するオブジェクト群を把握するとともに、自身の存在を相手からも把握できるように設定します。

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

隣接するオブジェクト群を消去して、初期設定に備えます。

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

隣接するオブジェクト群として、新たに cell を追加します。

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


関連記事

Last updated♪2009/12/01

《付録》HoneyComb2.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 System.Windows import *
from System.Windows.Media import *
from System.Windows.Shapes import *

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

    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)       ;
        if Stroke: self.shape.Stroke = Stroke;
        if Fill  : self.shape.Fill   = 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):
        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,
            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):
        on, off = Brushes.Magenta, Brushes.Black
        for e in self.neighbors:
            if not e: continue
            s = e.shape.Stroke
            e.shape.Stroke = (on, off)[s == on]

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

    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)
    
## --------------------