いよいよボードクラスです。マス目の空いている場所に部品が置けるかどうかを判定したり、配置データをこのクラスで管理します。
・クラス宣言
クラスの名前は "Board" です。
Public Class Board
・プロパティ:Width, Height
ボードの幅と縦。初期化時に設定します。
ReadOnly Property Width As Integer 'X軸方向 ReadOnly Property Height As Integer 'Y軸方向
・プロパティ:Cells( , )
※ 外からは2次元のように見えますが実体は1次元です
ボードのマス目(値は Boolean)です。エクセルVBAのCellsとは縦横が逆です。サイズは動的に確保します。
Private _Cells As Boolean() 'セル実体:1次元配列 Property Cells(x As Integer, y As Integer) As Boolean Get Return _Cells(x + y * Width) End Get Set(value As Boolean) _Cells(x + y * Width) = value End Set End Property
・プロパティ:解判定関係
解の判定に使用するプロパティです。PlacedPieceCountが部品の種類(=12)に等しくなったときが正解です。PlacedFirstPieceは最初に置いた部品でプログレスバーの表示計算に使います。
Property PlacedPieceCount As Integer = 0 Property PlacedFirstPiece As Piece = Nothing
・初期化
引数にボードの横と縦のサイズを指定します。
Sub New(width As Integer, height As Integer) _Width = width _Height = height ReDim _Cells(width * height - 1) PlacedPieceCount = 0 PlacedFirstPiece = Nothing End Sub
・関数 onBoard
指定した座標がボード上にあるかどうかを判定します(ボード上にあれば True)。
Public Function onBoard(x As Integer, y As Integer) As Boolean If x >= 0 AndAlso x <= Width - 1 AndAlso y >= 0 AndAlso y <= Height - 1 Then Return True Else Return False End If End Function
・関数:nextBlankCell
指定した座標から空(False)セルを検索して、空セルがあればその座標を返します。検索方向は下で、下端まで到達すると右上へ移ります。空セルがなければ Nothing を返します。
Public Function nextBlankCell(c As Coord) As Coord Dim x = c.X Dim y = c.Y Do Until Cells(x, y) = False Select Case True Case y < Height - 1 y += 1 Case x < Width - 1 x += 1 y = 0 Case Else Return Nothing End Select Loop Return New Coord(x, y) 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 If onBoard(x, y) = False OrElse Cells(x, y) = 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) = 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) = False Next End With PlacedPieceCount -= 1 End Sub
以上が「ボードクラス」です。クラス全体のソースは以下のとおりです。
Public Class Board '********************************************** '* Board (ボードクラス:盤面) '********************************************** ReadOnly Property Width As Integer 'X軸方向 ReadOnly Property Height As Integer 'Y軸方向 Private _Cells As Boolean() 'セル実体:1次元配列 Property Cells(x As Integer, y As Integer) As Boolean Get Return _Cells(x + y * Width) End Get Set(value As Boolean) _Cells(x + y * Width) = value End Set End Property Property PlacedPieceCount As Integer = 0 Property PlacedFirstPiece As Piece = Nothing '** 初期化 Sub New(width As Integer, height As Integer) _Width = width _Height = height ReDim _Cells(width * height - 1) PlacedPieceCount = 0 PlacedFirstPiece = Nothing End Sub '** onBoard Public Function onBoard(x As Integer, y As Integer) As Boolean If x >= 0 AndAlso x <= Width - 1 AndAlso y >= 0 AndAlso y <= Height - 1 Then Return True Else Return False End If End Function '** nextBlankCell(Y軸→X軸の順に検索) Public Function nextBlankCell(c As Coord) As Coord Dim x = c.X Dim y = c.Y Do Until Cells(x, y) = False Select Case True Case y < Height - 1 y += 1 Case x < Width - 1 x += 1 y = 0 Case Else Return Nothing End Select Loop Return New Coord(x, y) 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 If onBoard(x, y) = False OrElse Cells(x, y) = 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) = 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) = False Next End With PlacedPieceCount -= 1 End Sub End Class
以上でプログラムで使用する4つのクラス(Coord, Piece, Shelf, Board)が揃いました。次回は準備作業の最後として「DEFクラス」を作成します。このクラスはプログラムの表紙(鑑)です。プログラム諸元や共有で使用する定数や関数などをまとめて記述しておくクラスです。