箱クラスは箱内の空いているセルに部品が置けるかどうかを判定したり、現在おいている部品と座標位置を登録して完成判断に使用します。
・クラス宣言
クラスの名前は "Box" です。
Public Class Box
・プロパティ:LenX, LenY, LenZ
箱の大きさ。初期化時に退避します。
ReadOnly Property LenX As Integer 'X軸方向 ReadOnly Property LenY As Integer 'Y軸方向 ReadOnly Property LenZ As Integer 'Z軸方向
・プロパティ:Cells( , , )
箱内のセル(値は Boolean)です。見た目(Cells)は3次元ですが処理速度の関係で実体(_Cells)は1次元にしています。サイズは初期化で確保します。
Private _Cells As Boolean() 'セル実体:1次元配列 Property Cells(x As Integer, y As Integer, z As Integer) As Boolean Get Return _Cells(x + (y + z * LenY) * LenX) End Get Set(value As Boolean) _Cells(x + (y + z * LenY) * LenX) = value End Set End Property
・プロパティ:解判定関係
解の判定に使用するプロパティです。PlacedPieceCountが部品の種類(=12)に等しくなったときが正解です。PlacedFirstPieceは最初に置いた部品でプログレスバーの表示計算に使います。
Property PlacedPieceCount As Integer = 0 Property PlacedFirstPiece As Piece = Nothing
・初期化
引数にボードの横と縦のサイズを指定します。
Sub New(width As Integer, depth As Integer, height As Integer) _LenX = width _LenY = depth _LenZ = height ReDim _Cells(width * depth * height - 1) PlacedPieceCount = 0 PlacedFirstPiece = Nothing End Sub
・関数 FitInBox
指定した座標が箱の中にあるかどうかを判定します(箱の中にあれば True)。
Public Function FitInBox(x As Integer, y As Integer, z As Integer) As Boolean If x >= 0 AndAlso x <= LenX - 1 AndAlso y >= 0 AndAlso y <= LenY - 1 AndAlso z >= 0 AndAlso z <= LenZ - 1 Then Return True Else Return False End If End Function
・関数:NextBlankCell
指定した座標から空(False)セルを検索して、空セルがあればその座標を返します。検索方向はZ→Y→X座標の順です。空セルがなければ Nothing を返します。
Public Function NextBlankCell(c As Coord) As Coord Dim x = c.X Dim y = c.Y Dim z = c.Z Do Until Cells(x, y, z) = False Select Case True Case z < LenZ - 1 z += 1 Case y < LenY - 1 y += 1 z = 0 Case x < LenX - 1 x += 1 y = 0 z = 0 Case Else Return Nothing End Select Loop Return New Coord(x, y, z) End Function
・関数:CanPlace
箱内の指定した位置に部品が置けるかどうかを返します(部品を置くことができれば True)。部品の5個の座標に対応するセルがすべて空であれば True、1つでもセルが埋まっていれば False を返します。
Public Function CanPlace(piece As Piece, c As Coord) As Boolean For Each p In piece.Coords Dim x = c.X + p.X Dim y = c.Y + p.Y Dim z = c.Z + p.Z If FitInBox(x, y, z) = False OrElse Cells(x, y, z) = True Then Return False End If Next Return True End Function
・メソッド:PlacePiece
箱内の指定した位置に部品を置きます
Public Sub PlacePiece(shelf As Shelf) With shelf.PlacedCoord For Each p In shelf.PlacedPiece.Coords Cells(.X + p.X, .Y + p.Y, .Z + p.Z) = True Next End With PlacedPieceCount += 1 '解判定のためのカウンターを増加 If PlacedPieceCount = 1 Then PlacedFirstPiece = shelf.PlacedPiece 'プログレスバー表示用 End If End Sub
・メソッド:RemovePiece
ボードの指定した位置の部品を取り除きます
Public Sub RemovePiece(shelf As Shelf) With shelf.PlacedCoord For Each p In shelf.PlacedPiece.Coords Cells(.X + p.X, .Y + p.Y, .Z + p.Z) = False Next End With PlacedPieceCount -= 1 '解判定のためのカウンターを減少 End Sub
以上が「ボードクラス」です。クラス全体のソースは以下のとおりです。
Public Class Box '********************************************** '* Box (箱クラス) '********************************************** ReadOnly Property LenX As Integer 'X軸方向 ReadOnly Property LenY As Integer 'Y軸方向 ReadOnly Property LenZ As Integer 'Z軸方向 Private _Cells As Boolean() 'セル実体:1次元配列 Property Cells(x As Integer, y As Integer, z As Integer) As Boolean Get Return _Cells(x + (y + z * LenY) * LenX) End Get Set(value As Boolean) _Cells(x + (y + z * LenY) * LenX) = value End Set End Property Property PlacedPieceCount As Integer = 0 Property PlacedFirstPiece As Piece = Nothing '** 初期化 Sub New(width As Integer, depth As Integer, height As Integer) _LenX = width _LenY = depth _LenZ = height ReDim _Cells(width * depth * height - 1) PlacedPieceCount = 0 PlacedFirstPiece = Nothing End Sub '** FitInBox Public Function FitInBox(x As Integer, y As Integer, z As Integer) As Boolean If x >= 0 AndAlso x <= LenX - 1 AndAlso y >= 0 AndAlso y <= LenY - 1 AndAlso z >= 0 AndAlso z <= LenZ - 1 Then Return True Else Return False End If End Function '** NextBlankCell Public Function NextBlankCell(c As Coord) As Coord Dim x = c.X Dim y = c.Y Dim z = c.Z Do Until Cells(x, y, z) = False Select Case True Case z < LenZ - 1 z += 1 Case y < LenY - 1 y += 1 z = 0 Case x < LenX - 1 x += 1 y = 0 z = 0 Case Else Return Nothing End Select Loop Return New Coord(x, y, z) End Function '** CanPlace Public Function CanPlace(piece As Piece, c As Coord) As Boolean For Each p In piece.Coords Dim x = c.X + p.X Dim y = c.Y + p.Y Dim z = c.Z + p.Z If FitInBox(x, y, z) = False OrElse Cells(x, y, z) = True Then Return False End If Next Return True End Function '** PlacePiece Public Sub PlacePiece(shelf As Shelf) With shelf.PlacedCoord For Each p In shelf.PlacedPiece.Coords Cells(.X + p.X, .Y + p.Y, .Z + p.Z) = True Next End With PlacedPieceCount += 1 If PlacedPieceCount = 1 Then PlacedFirstPiece = shelf.PlacedPiece End If End Sub '** RemovePiece Public Sub RemovePiece(shelf As Shelf) With shelf.PlacedCoord For Each p In shelf.PlacedPiece.Coords Cells(.X + p.X, .Y + p.Y, .Z + p.Z) = False Next End With PlacedPieceCount -= 1 End Sub End Class
以上でプログラムで使用する4つのクラス(Coord, Piece, Shelf, Box)が揃いました。次回はプログラムの鑑「DEFクラス」です。プログラム諸元や共有で使用する定数や関数などをまとめて記述しておくクラスです。