《付録》Tetrimino.py
# -*- coding: utf-8 -*- #=============================================================================== # Copyright (C) 2000-2008, 小泉ひよ子とタマゴ倶楽部 # # Change History: Games # 1988/05, Smalltalk # 2004/09, Java # 2005/02, C# # 2005/03, Jython # 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 #=============================================================================== from System.Windows import * from System.Windows.Media import * from System.Windows.Shapes import * from hexagon import HexStone ## -------------------- class Omino(object): _mat1 = [ ( 1, -2), ( 2, 0), ( 1, 2), (-1, 2), (-2, 0), (-1, -2), ] _mat2 = [ ( 0, -4), ( 2, -4), ( 3, -2), ( 4, 0), ( 3, 2), ( 2, 4), ( 0, 4), (-2, 4), (-3, 2), (-4, 0), (-3, -2), (-2, -4), ] _strokeColor = Brushes.Black def __init__(self, x, y, phase=0, color=None, mino1=, offset=1, ): self.phase = phase self.color = color self.mino1 = mino1 self.offset = offset self.matrix1 = self._matrix(x, y, self._mat1) self.shape = self._shape (x, y, self.phase) def _matrix(self, x, y, matrix): M = 2 Ox = HexStone._dx; W = HexStone._width Oy = HexStone._dy; H = HexStone._height X = Ox + W*x Y = Oy + H*y self.pivot = self.pointCollection([Point(X+dx*M, Y+dy*M) for dx, dy in HexStone(X, Y, False).vertices]) s = for ix, iy in matrix: X = Ox + W*(x+ix) Y = Oy + H*(y+iy) points = self.pointCollection([Point(X+dx*M, Y+dy*M) for dx, dy in HexStone(X, Y, False).vertices]) s.append(points) return s def _shape(self, x, y, phase): self.phase = self._rotate1(phase) s = for n in self.mino1: s.append(Polygon( HorizontalAlignment=HorizontalAlignment.Center, VerticalAlignment=VerticalAlignment.Center, Stroke=self._strokeColor, Fill=self.color, Points=self.matrix1[self._rotate1(n)], )) return s def rotateClockwise(self): self.phase = self._rotate1(1) for e, n in zip(self.shape[self.offset:], self.mino1): e.Points = self.matrix1[self._rotate1(n)] def pointCollection(self, vertices): s = PointCollection() for e in vertices: s.Add(e) return s def _rotate1(self, n): return (n + self.phase) % 6 ## -------------------- class SigOmino(Omino): def _shape(self, x, y, phase): pivot = Polygon( HorizontalAlignment=HorizontalAlignment.Center, VerticalAlignment=VerticalAlignment.Center, Stroke=self._strokeColor, Fill=self.color, Points=self.pivot, ) s = super(SigOmino, self)._shape(x, y, phase) return [pivot] + s ## -------------------- class PiOmino(SigOmino): def __init__(self, x, y, phase=0, color=None, mino1=, offset=1, mino2=None, ): self.mino2 = mino2 self.matrix2 = self._matrix(x, y, self._mat2) super(PiOmino, self).__init__(x, y, phase, color, mino1, offset) def _shape(self, x, y, phase): s = super(PiOmino, self)._shape(x, y, phase) for n in self.mino2: s.append(Polygon( HorizontalAlignment=HorizontalAlignment.Center, VerticalAlignment=VerticalAlignment.Center, Stroke=self._strokeColor, Fill=self.color, Points=self.matrix2[self._rotate2(n)], )) return s def rotateClockwise(self): super(PiOmino, self).rotateClockwise() for e, n in zip(self.shape[len(self.mino1)+1:], self.mino2): e.Points = self.matrix2[self._rotate2(n)] def _rotate2(self, n): return (n + self.phase*2) % 12 ## -------------------- class TetriminoC(Omino): def __init__(self, x, y, phase=0): super(self.__class__, self).__init__(x, y, phase, mino1=(0, 1, 2, 3), color=Brushes.Brown, offset=0, ) ## -------------------- class TetriminoO(SigOmino): def __init__(self, x, y, phase=0): super(self.__class__, self).__init__(x, y, phase, mino1=(0, 1, 2), color=Brushes.Yellow, ) class TetriminoP(SigOmino): def __init__(self, x, y, phase=0): super(self.__class__, self).__init__(x, y, phase, mino1=(0, 1, 3), color=Brushes.Magenta, ) class TetriminoB(SigOmino): def __init__(self, x, y, phase=0): super(self.__class__, self).__init__(x, y, phase, mino1=(0, 2, 3), color=Brushes.Purple, ) class TetriminoY(SigOmino): def __init__(self, x, y, phase=0): super(self.__class__, self).__init__(x, y, phase, mino1=(0, 2, 4), color=Brushes.Gray, ) ## -------------------- class TetriminoZ(PiOmino): def __init__(self, x, y, phase=0): super(self.__class__, self).__init__(x, y, phase, mino1=(0, 2), mino2=(0,), color=Brushes.Red, ) class TetriminoL(PiOmino): def __init__(self, x, y, phase=0): super(self.__class__, self).__init__(x, y, phase, mino1=(0, 3), mino2=(0,), color=Brushes.Orange, ) class TetriminoI(PiOmino): def __init__(self, x, y, phase=0): super(self.__class__, self).__init__(x, y, phase, mino1=(0, 3), mino2=(1,), color=Brushes.Cyan, ) class TetriminoJ(PiOmino): def __init__(self, x, y, phase=0): super(self.__class__, self).__init__(x, y, phase, mino1=(0, 3), mino2=(2,), color=Brushes.Blue, ) class TetriminoS(PiOmino): def __init__(self, x, y, phase=0): super(self.__class__, self).__init__(x, y, phase, mino1=(0, 4), mino2=(2,), color=Brushes.Lime, ) ## --------------------
テストケースを記述する(1)
(Jython で作成した)既存のモジュール hexagon.py を再利用しながら、新たなモジュールの動作を検証するために、テストケースを作成します。
class ExWindow(Window): def init(self): target = "tabControl", "button", self._Controls(target) self.items = {} for e, mino in TestCase(): self.items[e] = mino item = TabItem(Header=e) self.tabControl.Items.Add(item) panel = Canvas() item.Content = panel self.addMino(panel, mino) self.tabControl.SelectionChanged += self.selectionChanged self.button.Click += self.click
ジェネレーター TestCase によって、10種類のテトリミノが得られます。
def selectionChanged(self, sender, e):
self.mino = self.items[sender.SelectedItem.Header]
self.button.Content = self.state()
任意のタブを選択すると、各テトリミノの状態がボタンに表示されます。
def click(self, sender, e): self.mino.rotateClockwise() sender.Content = self.state()
ボタンをクリックすると、テトリミノが(時計回りに)回転 rotateClockwise して、その状態が再表示されます。
class TestCase: types = "COpbYZLIJS" def __iter__(self): m = self.items() for e in self.types: yield e, m[e] def items(self): return dict((e, eval("Tetrimino%s(4, 4)"%e.upper())) for e in self.types)
10種類のテトリミノを生成するだけで、その扱いはクライアントに委ねます。
《Note》 第1章で紹介した、