MENU

【VB】ペントミノ2Dパズルを解く(4)棚クラスを作る

今回は棚クラスです。クラスの概要はこの連載の「(1)はじめに」を参考にしてください。

・クラス宣言

クラスの名前は "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

・初期化

引数のうち name と color はそのままプロパティに、expressionは部品集(Pieces)をつくるための文字列です。

Sub New(name As String, color As Color, expression As String)
   _Name = name
   _Color = color
   _Pieces = New List(Of Piece)
   _PlacedPiece = Nothing
   _PlacedCoord = Nothing
   Dim piece As New Piece(expression)

   For i = 0 To 7
      Dim p = piece.Clone()
      If i > 3 Then
         p.HorizontalReverse()
      End If
      p.AntiClockWiseRotate(i Mod 4)
      p.ShiftToOrigin()
      If Pieces.Any(Function(s) s = p) = False Then
         Pieces.Add(p)
      End If
      'シノニム除外("F","N","L","Y","P"のどれかで設定)
      If name = "F" And i = 1 Then
         Exit For
      End If
   Next

End Sub

'=====(例)=====
Dim piece As New Piece("RDRdL")      '部品"F"を作成します

コード中の "シノニム" とはボード全体を180度回転させたり裏返したりするとぴったり重なる解となるものをいいます。パズルのルールではシノニムは同一解となります。シノニムを除外するにはどうしたらいいでしょうか?


図では8通りの解のうち6通りが シノニム となってしまいますが、部品集に原因となる6個を除外した2個(図の①と②)のみを登録すればシノニムはできなくなります。コードの「シノニム除外」のところで部品"F"について①と②以外が部品集に登録されるのを防いでいます。あとはどのように部品を配置してもシノニムができる心配はありません。
なおこの処理ができるのは8種類の向きがある部品("F", "N", "L", "Y", "P")に限ります。


以上が「棚クラス」です。クラス全体のソースは以下のとおりです。

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)
      _Name = name
      _Color = color
      _Pieces = New List(Of Piece)
      _PlacedPiece = Nothing
      _PlacedCoord = Nothing
      Dim piece As New Piece(expression)

      For i = 0 To 7
         Dim p = piece.Clone()
         If i > 3 Then
            p.HorizontalReverse()
         End If
         p.AntiClockWiseRotate(i Mod 4)
         p.ShiftToOrigin()
         If Pieces.Any(Function(s) s = p) = False Then
            Pieces.Add(p)
         End If
         'シノニム除外("F","N","L","Y","P"のどれかで設定)
         If name = "F" And i = 1 Then
            Exit For
         End If
      Next

   End Sub

End Class

次は「箱クラス」です。