游戏的洪水填充Go in Visual Basic

时间:2018-01-03 13:25:05

标签: vb.net flood-fill

我是Visual Basic的业余爱好者。我正在尝试重建Go的游戏,我创建了棋盘,并且能够在网格的交叉点上放置石头。

我现在想要开始捕捉周围的石头。我在网上看过,发现洪水填充是最好的方法。但是,我已经在网上看了几天,我找不到任何可以使用的东西,或者操纵创建它。我不懂任何其他编程语言,所以我不能使用Java等代码。我发现Visual Basic的信息对我来说没有多大意义,因为我还是初学者。

我试图自己开始,从#34开始小的情况;如果有一块石头被捕获"。我有两个代表董事会,一个被宣布为" grid",另一个被称为" placement_stone"。

"网格"是用户点击放置石头的实际板。 laid_stone是这个板的副本,但是我使用了" 0"," 1"和" 2"分别代表空白,黑白。我正在使用Windows Forms重新创建此游戏。这是我为捕获石头而编写的代码段:

        Private Sub Panel1_Click(sender As Object, e As EventArgs) Handles Panel1.Click
    Dim board As Panel = DirectCast(sender, Panel)

    ' Figure out where the user clicked: min = 0, max = (gridsize - 1)
    Dim pt As Point = board.PointToClient(Cursor.Position)
    Dim colWidth As Integer = (1 / (GridSize + 1)) * board.Size.Width
    Dim rowHeight As Integer = (1 / (GridSize + 1)) * board.Size.Height
    Dim gridPosition As New Point(Math.Min(Math.Max((pt.X / colWidth) - 1, 0), GridSize - 1), Math.Min(Math.Max((pt.Y / rowHeight) - 1, 0), GridSize - 1))
    Dim newcoordsx As Integer
    Dim newcoordsy As Integer

    ' Now do something with gridPosition:
    If Not Grid(gridPosition.X)(gridPosition.Y).HasValue Then 'If gird(x,y) is empty
        illegalmovelbl.Hide() ' Hides the "Illegal Move" Label
        If cp = True Then ' If current player is Black

这是我陷入困境的部分,并意识到每种情况的编码都需要很长时间。我设法编写了一种情况的代码:

            newcoordsx = gridPosition.X + 1
            If placed_stone(newcoordsx, gridPosition.Y) = 2 Then
                newcoordsy = gridPosition.Y + 1
                If placed_stone(newcoordsx, newcoordsy) = 1 Then
                    newcoordsy = gridPosition.Y - 1
                    If placed_stone(newcoordsx, newcoordsy) = 1 Then
                        newcoordsx = gridPosition.X + 2
                        If placed_stone(newcoordsx, gridPosition.Y) = 1 Then
                            newcoordsx = gridPosition.X + 1
                            Grid(gridPosition.X)(gridPosition.Y) = True 'Place a black stone at Grid(x,y)
                            Grid(newcoordsx)(gridPosition.Y) = Nothing
                            placed_stone(newcoordsx, gridPosition.Y) = 0
                            pass = False
                            cp = False
                            passbtn.BackColor = Color.White 'The passbutton changes colour to white
                            passbtn.ForeColor = Color.Black 'The passbutton font changes colour to black
                        End If
                    End If
                End If
            End If

            'Grid(gridPosition.X)(gridPosition.Y) = True ' Place a black stone at Grid(x,y)
            'placed_stone(gridPosition.X, gridPosition.Y) = 1
            'pass = False
            'cp = False
            'passbtn.BackColor = Color.White ' The passbutton changes colour to white
            'passbtn.ForeColor = Color.Black ' The passbutton font changes colour to black

        ElseIf cp = False Then ' If current player is White
            Grid(gridPosition.X)(gridPosition.Y) = False ' Place a white stone at Grid(x,y)
            placed_stone(gridPosition.X, gridPosition.Y) = 2
            pass = False
            cp = True
            passbtn.BackColor = Color.Black ' The passbutton changes colour to black
            passbtn.ForeColor = Color.White ' The passbutton font changes colour to white
        End If

    ElseIf Grid(gridPosition.X)(gridPosition.Y).HasValue Then ' If gird(x,y) isn't empty
        illegalmovelbl.Show() ' Shows the "Illegal Move" Label
        MsgBox("Place your stone in a vacant point") ' Displays error message
    End If

    board.Invalidate() ' Force the board to redraw itself
End Sub

我曾尝试使用维基百科的洪水填充算法,我理解它是如何工作的逻辑,但我不知道如何在Visual Basic中编程。

 Flood-fill (node, target-color, replacement-color):
 1. If target-color is equal to replacement-color, return.
 2. If the color of node is not equal to target-color, return.
 3. Set the color of node to replacement-color.
 4. Perform Flood-fill (one step to the south of node, target-color, replacement-color).
    Perform Flood-fill (one step to the north of node, target-color, replacement-color).
    Perform Flood-fill (one step to the west of node, target-color, replacement-color).
    Perform Flood-fill (one step to the east of node, target-color, replacement-color).
 5. Return.

当然,在Go中,不是在该区域着色,而是在捕获时必须移除石头,并且您不会从刚刚捕获的石头开始填充,从最近的距离开始你希望捕获的石头。

您能否以简单的方式解释如何在Visual Basic中使用泛洪填充以及如何在Go游戏中实现它?

如果有人想查看整个代码,请告诉我。我很感激任何建议!

1 个答案:

答案 0 :(得分:4)

我不熟悉游戏Go的规则/游戏玩法,所以我不确定你想要完成什么,但如果你相信泛滥填充类型的算法是你需要的,那么我至少可以提供一些如何做到这一点的建议。您的代码所需的主要内容是细分为更精细的方法。单击面板时,您尝试执行的步骤是什么?当然,这不仅仅是一件事。有许多不同的事情发生 - 每个事情都可以通过一个单独的专用方法来执行。例如,如果您有这样的方法:

Private Function GetGridPosition(board As Panel, cursorPosition As Point) As Point
    Dim pt As Point = board.PointToClient(Cursor.Position)
    Dim colWidth As Integer = (1 / (GridSize + 1)) * board.Size.Width
    Dim rowHeight As Integer = (1 / (GridSize + 1)) * board.Size.Height
    Return New Point(Math.Min(Math.Max((pt.X / colWidth) - 1, 0), GridSize - 1), Math.Min(Math.Max((pt.Y / rowHeight) - 1, 0), GridSize - 1))        
End Function

然后,在Panel1_Click事件处理程序中,您可以大大简化代码的开头,如下所示:

Private Sub Panel1_Click(sender As Object, e As EventArgs) Handles Panel1.Click
    Dim board As Panel = DirectCast(sender, Panel)
    Dim gridPosition As Point = GetGridPosition(board, Cursor.Position)
' ...

当然,这会使代码更有条理,更容易阅读,但这并不能让你更接近洪水填充算法,对吗?嗯,是的,这大部分是正确的,但组织和可读性本身就是值得的目标,所以让我们继续......我们需要做的下一步是让玩家移动,然后,如果移动成功,我们需要切换到另一个玩家。所以,让我们首先创建切换玩家的方法:

Private Sub SwitchPlayer()
    pass = False
    cp = Not cp
    passbtn.BackColor = GetPlayerForeColor(cp)
    passbtn.ForeColor = GetPlayerBackColor(cp)
End Sub

Private Function GetPlayerForeColor(player as Boolean) As Color
    If player Then
        Return Color.White
    Else
        Return Color.Black
    End If 
End Function

Private Function GetPlayerBackColor(player as Boolean) As Color
    If player Then
        Return Color.Black
    Else
        Return Color.White
    End If 
End Function

你会注意到我偷偷走了(Chrome自动拼写告诉我这不是一个字,但是我的美国成长经历会有所不同)其他一些方法在那里我是在它。我确定他们的目的很明显。但就在那里停下来。这很明显吗?您会注意到评论已经消失,但代码的含义仍然很明显。这就是自我记录代码的含义。当他们需要时,评论很棒,但是当他们根本没有必要时,评论会更好。

所以,假装现在我们有这样的方法:

Private Function MakeMove(gridPosition As Grid, player As Boolean) As Boolean
    ' return true if the move was successful
End Function

然后整个Panel1_Click事件处理程序看起来像这样:

Private Sub Panel1_Click(sender As Object, e As EventArgs) Handles Panel1.Click
    Dim board As Panel = DirectCast(sender, Panel)
    Dim gridPosition As Point = GetGridPosition(board, Cursor.Position)
    If MakeMove(gridPosition, cp) Then
        SwitchPlayer()
    Else
        ShowIllegalMoveMessage()
    End If
End Sub

Private Sub ShowIllegalMoveMessage()
    illegalmovelbl.Show() 'Shows the "Illegal Move" Label
    MsgBox("Place your stone in a vacant point") 'Displays error message
End Sub

好的,现在我们已经开始了解它。那么,在采取行动时需要采取哪些步骤?嗯,我不知道,因为我不了解游戏。我把这个练习留给你,但是,如果你的倾向是正确的,并且你需要某种泛洪填充算法,那么这可能意味着你需要某种PlaceStone动作可以一遍又一遍地重复,所以这应该是它自己的方法:

Private Sub PlaceStone(gridPosition As Point, player As Boolean)
    ' Do something
End Sub

显然Do something是所有这一切的关键部分,而且它是我无法帮助你的那一部分。但是,如果它将成为洪水填充算法,我可以给你一个非常大的暗示。在其中所做的所有其他事情中,它将再次调用PlaceStone,将其传递给不同的网格位置(周围位置之一)。例如,像这样:

Private Sub PlaceStone(gridPosition As Point, player As Boolean)
    Dim north As Position = GetNorthPosition(gridPosition)
    If Floodable(north, player) Then
        PlaceStone(north, player)
    End If
    ' ...
End Sub

当一个方法调用自身时,我们称之为递归。但是,在您开始将代码拆分为专用的小方法之前,每个方法都有自己的封装任务,那么您就无法真正添加递归。所以,首先进行组织,然后添加递归。