首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Visual中游戏的洪水填充

Visual中游戏的洪水填充
EN

Stack Overflow用户
提问于 2018-01-03 13:25:05
回答 1查看 457关注 0票数 2

我是Visual的业余爱好者。我正在尝试重新创建的游戏,我已经创建了板,并能够将石头放置在网格的交叉口。

我现在要开始捕获被包围的石头。我在网上查了一下,发现洪水是解决这个问题的最好方法。然而,我已经在网上搜索了好几天了,我找不到任何我可以使用或操作的东西来创建它。我不懂任何其他的编程语言,所以我不能使用Java等的代码,而且我发现的用于Visual的一些信息对我来说没有多大意义,因为我仍然是个初学者。

我试着自己动手,从“如果一颗石头被抓住”的情况开始。我有两个董事会代表,一个被声明为“网格”,另一个被声明为"placed_stone“。

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

代码语言:javascript
复制
        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

这就是我被困住的地方,我意识到每一种情况的编码都会花费太长的时间。我成功地为一种情况编写了代码:

代码语言:javascript
复制
            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编程。

代码语言:javascript
复制
 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.

当然,在围棋中,你不需要在这个区域着色,你必须在捕获的时候移除石头,而不是从你刚刚准备捕获的石头开始,而是从你想要捕获的最接近的石头开始。

请您解释一下如何在Visual中轻松地使用洪水填充以及如何在这个围棋游戏中实现它吗?

如果有人想看完整的代码,请告诉我。如有任何建议,我将不胜感激!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-03 14:25:17

我不太熟悉游戏的游戏规则,所以我不确定你到底想要完成什么,但是如果你相信一种充满洪水的算法是你所需要的,那么我至少可以给你一些建议。您的代码需要的首要任务是将其分解为更细粒度的方法。单击面板时,尝试执行哪些步骤?当然,这不仅仅是一回事。有许多不同的事情正在进行--每一件事情都可以通过一个单独的专用方法来执行。例如,如果您有这样的方法:

代码语言:javascript
复制
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事件处理程序中,可以大大简化代码的开头,如下所示:

代码语言:javascript
复制
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)
' ...

当然,这使得代码更有条理,更容易阅读,但这并不能使您更接近洪水填充算法,对吗?嗯,是的,这基本上是真的,但是组织和可读性本身就是有价值的目标,所以无论如何让我们继续.下一步我们需要执行的是让球员的移动,然后,如果移动是成功的,我们需要切换到另一个球员。因此,让我们首先创建切换播放器的方法:

代码语言:javascript
复制
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自动拼写告诉我,这不是一个词,但我的美国教育要求不同)在那里的其他几种方法,而我在那里。我相信他们的目的是显而易见的。但就在那停下来。明显地能看出来?您会注意到注释已经消失,但是代码的含义仍然是显而易见的。这就是我们所说的自我记录代码的意思。评论在必要的时候是很棒的,但是当它们根本不需要的时候就更好了。

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

代码语言:javascript
复制
Private Function MakeMove(gridPosition As Grid, player As Boolean) As Boolean
    ' return true if the move was successful
End Function

然后整个Panel1_Click事件处理程序可能如下所示:

代码语言:javascript
复制
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动作,所以这应该是它自己的方法:

代码语言:javascript
复制
Private Sub PlaceStone(gridPosition As Point, player As Boolean)
    ' Do something
End Sub

显然,Do something是所有这些的关键部分,也是我无法帮助您的一个部分。但是,如果它是一个洪水填充算法,我可以给你一个很大的提示。在它将要做的其他事情中,它将再次调用PlaceStone,将它传递给一个不同的网格位置(周围的位置之一)。例如,类似这样的东西:

代码语言:javascript
复制
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

当一个方法调用自己时,我们称之为递归。但是,除非您开始将代码拆分为专用的小方法,每个方法都有自己的封装任务,否则您就不能真正添加递归。所以,首先组织起来,然后再添加递归。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48078334

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档