PictureBox Grid Manager for Path Generation and Patch Placement in VB.NET

This code defines a class named PictureBoxGridManager responsible for generating a grid of PictureBoxes and creating a path through it. It initializes with a gridPanel and a toolTip object. The CreatePictureBoxGridCentered method generates a grid of PictureBoxes centered on the screen, calculates rows and columns, and populates the grid with PictureBoxes representing scenery. Additionally, it generates a snake-like path across the grid and places random patches over the scenery. The ClearExistingTiles method removes existing tiles from the grid. The GenerateSnakePath method generates the path, and the PlacePatchesOverScenery method places random patches. Finally, the FillPatch method fills a patch with a specific type.

The code to cover a certain percentage of the path is flawed and fails to function properly. When setting values from 0.1 to 0.9, or even 1, the percentage coverage doesn’t align mathematically. This discrepancy undermines the code’s accuracy and reliability.

This code snippet defines three procedures within the same class. The first, CreatePictureBoxGridCentered, is responsible for creating a grid of PictureBoxes centered on the screen. It first clears any existing tiles, calculates the dimensions of the screen and the grid, initializes the tiles array, creates PictureBoxes for each grid cell, and sets their properties such as size, location, image, and tooltip. Then, it generates a path through the grid using the GenerateSnakePath method and places patches over the remaining scenery using the PlacePatchesOverScenery method.

The second procedure, GenerateSnakePath, generates a path through the grid by starting from the leftmost column and randomly moving right, down, or up until reaching the rightmost column or the specified percentage of tiles for the path. It sets the appropriate image and tooltip for the path tiles.

The third procedure, PlacePatchesOverScenery, randomly places patches (water or mountain) over the remaining scenery tiles in the grid. It selects random starting points for the patches, limits the number of tiles for each patch type to 10% of the total tiles, and ensures that each patch consists of 3 to 5 tiles. It uses the FillPatch method to fill each patch with the chosen patch type and sets the appropriate image and tooltip for the patch tiles.

 Private Sub CreatePictureBoxGridCentered()
    ' Check and clear any old tiles if already initialized
    If tiles IsNot Nothing Then
        For Each tile As Tile In tiles
            If tile IsNot Nothing AndAlso tile.PictureBox IsNot Nothing Then
                Me.Controls.Remove(tile.PictureBox)
                tile.PictureBox.Dispose()
            End If
        Next
    End If

    ' Screen dimensions
    Dim screenWidth As Integer = Screen.PrimaryScreen.Bounds.Width
    Dim screenHeight As Integer = Screen.PrimaryScreen.Bounds.Height
    Dim pictureBoxSize As New Size(60, 60)
    Dim margin As Integer = 70
    Dim usableScreenWidth As Integer = screenWidth - 2 * margin
    Dim usableScreenHeight As Integer = screenHeight - 2 * margin
    Dim numRows As Integer = usableScreenHeight  pictureBoxSize.Height
    Dim numCols As Integer = usableScreenWidth  pictureBoxSize.Width
    Dim startX As Integer = (screenWidth - numCols * pictureBoxSize.Width)  2
    Dim startY As Integer = (screenHeight - numRows * pictureBoxSize.Height)  2

    ' Initialize the tiles array to match grid dimensions
    ReDim tiles(numRows * numCols - 1)

    ' Initialize all tiles as default scenery (using the image)
    Dim index As Integer = 0
    For row As Integer = 0 To numRows - 1
        For col As Integer = 0 To numCols - 1
            Dim pictureBox As New PictureBox() With {
            .Size = pictureBoxSize,
            .Location = New Point(startX + col * pictureBoxSize.Width, startY + row * pictureBoxSize.Height),
            .BorderStyle = BorderStyle.FixedSingle,
            .Image = My.Resources.scenery_img, ' Set the scenery image
            .SizeMode = PictureBoxSizeMode.StretchImage
        }
            tiles(index) = New Tile(pictureBox, TileType.Scenery)
            Me.Controls.Add(pictureBox)

            ' Set tooltip for initial "Scenery" type
            ToolTip1.SetToolTip(pictureBox, "Scenery")
            index += 1
        Next
    Next

    ' Generate and apply the path
    GenerateSnakePath(numRows, numCols, 0.25)

    ' Apply patches over the remaining scenery
    PlacePatchesOverScenery(numRows, numCols)
End Sub



Private Sub GenerateSnakePath(numRows As Integer, numCols As Integer, pathPercentage As Double)
    Dim rand As New Random()
    Dim totalTiles As Integer = numRows * numCols
    Dim requiredPathTiles As Integer = CInt(Math.Ceiling(totalTiles * pathPercentage))

    ' Initialize the path from the leftmost column at a random row
    Dim currentRow As Integer = rand.Next(1, numRows - 1)
    Dim currentCol As Integer = 0
    Dim pathTiles As New List(Of Tuple(Of Integer, Integer))()

    pathTiles.Add(Tuple.Create(currentRow, currentCol))
    tiles(currentRow * numCols + currentCol).PictureBox.Image = My.Resources.path_img ' Set path image
    tiles(currentRow * numCols + currentCol).Type = TileType.Path
    ToolTip1.SetToolTip(tiles(currentRow * numCols + currentCol).PictureBox, "Path") ' Set tooltip for path

    ' Movement directions: right, down, up, left
    Dim directions As New List(Of Tuple(Of Integer, Integer)) From {
    Tuple.Create(0, 1),  ' right
    Tuple.Create(1, 0),  ' down
    Tuple.Create(-1, 0), ' up
    Tuple.Create(0, -1)  ' left
}

    ' Generate the path until reaching the rightmost column or required tiles count
    While pathTiles.Count < requiredPathTiles AndAlso currentCol < numCols - 1
        ' Find potential movements (example)
        Dim possibleMoves As New List(Of Tuple(Of Integer, Integer))

        ' Check right movement
        Dim newCol As Integer = currentCol + 1
        If newCol < numCols AndAlso Not pathTiles.Contains(Tuple.Create(currentRow, newCol)) Then
            possibleMoves.Add(Tuple.Create(currentRow, newCol))
        End If

        ' Check vertical movements (up and down)
        For Each direction In {directions(1), directions(2)}
            Dim newRow As Integer = currentRow + direction.Item1
            If newRow >= 0 AndAlso newRow < numRows AndAlso Not pathTiles.Contains(Tuple.Create(newRow, currentCol)) Then
                possibleMoves.Add(Tuple.Create(newRow, currentCol))
            End If
        Next

        ' If no moves are possible, exit
        If possibleMoves.Count = 0 Then Exit While

        ' Choose the next move randomly
        Dim nextMove = possibleMoves(rand.Next(possibleMoves.Count))
        currentRow = nextMove.Item1
        currentCol = nextMove.Item2

        pathTiles.Add(nextMove)
        tiles(currentRow * numCols + currentCol).PictureBox.Image = My.Resources.path_img
        tiles(currentRow * numCols + currentCol).Type = TileType.Path
        ToolTip1.SetToolTip(tiles(currentRow * numCols + currentCol).PictureBox, "Path")
    End While
End Sub


Private Sub PlacePatchesOverScenery(numRows As Integer, numCols As Integer)
    Dim rand As New Random()
    Dim patchTypes As TileType() = {TileType.Water, TileType.Mountain}
    Dim tilesToProcess As New List(Of Tuple(Of Integer, Integer))()

    ' Prepare list of potential start points for patches, only for remaining scenery tiles
    For i As Integer = 0 To tiles.Length - 1
        If tiles(i).Type = TileType.Scenery Then
            tilesToProcess.Add(New Tuple(Of Integer, Integer)(i  numCols, i Mod numCols))
        End If
    Next

    ' Shuffle the list to randomize start points
    tilesToProcess = tilesToProcess.OrderBy(Function(x) rand.Next()).ToList()

    ' Limit patches to 10% of total tiles for each type
    Dim totalTiles As Integer = tiles.Length
    Dim maxPatchTiles As Integer = CInt(totalTiles * 0.1) ' 10% of total tiles
    Dim waterTilesCount As Integer = 0
    Dim mountainTilesCount As Integer = 0

    ' Place patches ensuring they are of size 3 to 5 tiles
    For Each startTile In tilesToProcess
        Dim row As Integer = startTile.Item1
        Dim col As Integer = startTile.Item2
        Dim index As Integer = row * numCols + col

        If tiles(index).Type = TileType.Scenery Then
            Dim patchType As TileType = patchTypes(rand.Next(patchTypes.Length))
            Dim patchSize As Integer = rand.Next(3, 6) ' Random patch size between 3 and 5 tiles

            ' Check the patch type and control the number of tiles
            Dim currentPatchCount As Integer = If(patchType = TileType.Water, waterTilesCount, mountainTilesCount)
            If currentPatchCount + patchSize > maxPatchTiles Then
                patchSize = maxPatchTiles - currentPatchCount ' Adjust size to not exceed limit
            End If

            If patchSize > 0 Then ' Proceed only if there's room for more tiles of this type
                FillPatch(row, col, numRows, numCols, patchType, patchSize)
                If patchType = TileType.Water Then
                    waterTilesCount += patchSize
                Else
                    mountainTilesCount += patchSize
                End If
            End If
        End If
    Next
End Sub

' Helper method for patch filling
Private Sub FillPatch(row As Integer, col As Integer, numRows As Integer, numCols As Integer, patchType As TileType, patchSize As Integer)
    Dim queue As New Queue(Of Tuple(Of Integer, Integer))
    queue.Enqueue(New Tuple(Of Integer, Integer)(row, col))
    Dim processed As Integer = 0

    While queue.Count > 0 AndAlso processed < patchSize
        Dim current As Tuple(Of Integer, Integer) = queue.Dequeue()
        Dim r As Integer = current.Item1
        Dim c As Integer = current.Item2
        Dim idx As Integer = r * numCols + c

        If r >= 0 AndAlso r < numRows AndAlso c >= 0 AndAlso c < numCols AndAlso tiles(idx).Type = TileType.Scenery Then
            tiles(idx).PictureBox.Image = If(patchType = TileType.Water, My.Resources.water_img, My.Resources.mountain_img)
            tiles(idx).Type = patchType
            processed += 1

            ' Set tooltip for the new patch type
            ToolTip1.SetToolTip(tiles(idx).PictureBox, If(patchType = TileType.Water, "Water", "Mountain"))

            ' Enqueue neighboring tiles to form a patch
            Dim neighbors As Tuple(Of Integer, Integer)() = {
            Tuple.Create(r - 1, c), Tuple.Create(r + 1, c),
            Tuple.Create(r, c - 1), Tuple.Create(r, c + 1)
        }

            For Each neighbor In neighbors
                Dim nRow As Integer = neighbor.Item1
                Dim nCol As Integer = neighbor.Item2
                Dim neighborIdx As Integer = nRow * numCols + nCol
                If nRow >= 0 AndAlso nRow < numRows AndAlso nCol >= 0 AndAlso nCol < numCols AndAlso
                tiles(neighborIdx).Type = TileType.Scenery Then
                    queue.Enqueue(neighbor)
                End If
            Next
        End If
    End While
End Sub


New contributor

Bernard Aybout is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật