今回は棚クラスです。棚は全部で12作り、1つの棚に1種類の部品を登録します。登録する部品は回転や裏返しをしたものをあらかじめ用意しておきます。例えば部品"T"の棚には向きの違う12個の部品"T"を登録します。
部品"F"の場合は部品の形状が非対称なので登録されるのは24個になります。
こうして登録した各部品棚の部品数はこのようになります。
棚 | F | I | L | N | P | T | U | V | W | X | Y | Z |
---|---|---|---|---|---|---|---|---|---|---|---|---|
部品数 | 24 | 1 | 16 | 16 | 24 | 12 | 12 | 12 | 12 | 3 | 16 | 12 |
ただし部品"P"については24個のうち6個を登録します。ペントミノ2Dソルバーのときと同じように180度回転と反転で重なるものはあらかじめ除外します(図の濃い色の部品のみを登録します)。
・クラス宣言
クラスの名前は "Shelf" です
Public Class Shelf
・プロパティ:名前 Name
棚の名前です。中に入れる部品の名前をそのまま使います。解の表示で使用します
ReadOnly Property Name As String
・プロパティ:表示色 Color
解の表示で背景色として使用します
ReadOnly Property Color As Color
・プロパティ:部品集 Pieces
部品コレクション。前述のとおり回転や裏返しをしたものをあらかじめ入れておきます
ReadOnly Property Pieces As List(Of Piece)
・プロパティ:部品を箱に置いたとき
部品集から部品を選択して箱に置いたときの部品と置いた座標。選択していないときはともにNothing
Property PlacedPiece As Piece Property PlacedCoord As Coord
・初期化
4つの引数のうち name と color はそのままプロパティにしたあと、expression の文字列をもとに部品集(Pieces)をつくっていきます。またBoxはそのサイズを参照するためのものです。
※Boxクラスは「ペントミノ3Dパズルを解く(5)箱クラスを作る」を参照
Sub New(name As String, color As Color, expression As String, box As Box) _Name = name _Color = color _Pieces = New List(Of Piece) _PlacedPiece = Nothing _PlacedCoord = Nothing Dim piece As New Piece(expression) For a = 0 To 3 For b = 0 To 3 For c = 0 To 3 '元の部品を各軸の回りに回転させる Dim p = piece.Clone() p.RotateXY(a) p.RotateXZ(b) p.RotateYZ(c) p.ShiftToOrigin() '部品の向きが箱に収まらなければ除外 If p.LenX > box.LenX OrElse p.LenY > box.LenY OrElse p.LenZ > box.LenZ Then Continue For End If '回転シノニムを除外(DEF.SynonymJudgePieceName="P") If name = DEF.SynonymJudgePieceName Then If IsRotateSynonym(p) Then Continue For End If End If 'リストに無ければ追加 If Pieces.Any(Function(s) s = p) = False Then Pieces.Add(p) End If Next Next Next End Sub
・回転シノニム判定
前述の部品"P"で180度回転させるとぴったり重なるもの(シノニム)を除外するときに使用します。引数の部品を様々な方向に180度回転させて部品集に登録済みかどうかを判定します。
Private Function IsRotateSynonym(pc As Piece) As Boolean For Each plane In {"X", "Y", "Z", "XY", "YZ", "ZX", "XYZ"} Dim p = pc.Clone If plane.Contains("X") Then p.RotateYZ(2) End If If plane.Contains("Y") Then p.RotateXZ(2) End If If plane.Contains("Z") Then p.RotateXY(2) End If p.ShiftToOrigin() If Pieces.Any(Function(s) s = p) = True Then Return True End If Next '回転シノニムではない Return False End Function
以上が「棚クラス」です。クラス全体のソースは以下のとおりです。
Public Class Shelf '********************************************** '* Shelf (部品棚クラス) '********************************************** ReadOnly Property Name As String '名前 ReadOnly Property Color As Color '表示色 ReadOnly Property Pieces As List(Of Piece) '部品コレクション Property PlacedPiece As Piece 'ボードに配置した部品(Pieces内の1個),配置してないときはNothing Property PlacedCoord As Coord 'PlacedPieceを配置した場所,配置してないときはNothing Sub New(name As String, color As Color, expression As String, board As Board) _Name = name _Color = color _Pieces = New List(Of Piece) _PlacedPiece = Nothing _PlacedCoord = Nothing Dim piece As New Piece(expression) For a = 0 To 3 For b = 0 To 3 For c = 0 To 3 '元の部品を各軸の回りに回転させる Dim p = piece.Clone() p.RotateXY(a) p.RotateXZ(b) p.RotateYZ(c) p.ShiftToOrigin() '部品の向きが箱に収まらなければ除外 If p.LenX > board.LenX OrElse p.LenY > board.LenY OrElse p.LenZ > board.LenZ Then Continue For End If '回転シノニムを除外 If name = DEF.SynonymJudgePieceName Then If IsRotateSynonym(p) Then Continue For End If End If 'リストに無ければ追加 If Pieces.Any(Function(s) s = p) = False Then Pieces.Add(p) End If Next Next Next End Sub '回転シノニム判定(True=180度回転で重複する) Private Function IsRotateSynonym(pc As Piece) As Boolean For Each plane In {"X", "Y", "Z", "XY", "YZ", "ZX", "XYZ"} Dim p = pc.Clone If plane.Contains("X") Then p.RotateYZ(2) End If If plane.Contains("Y") Then p.RotateXZ(2) End If If plane.Contains("Z") Then p.RotateXY(2) End If p.ShiftToOrigin() If Pieces.Any(Function(s) s = p) = True Then Return True End If Next '回転シノニムではない Return False End Function End Class
次は「箱クラス」です。