我是Visual的业余爱好者。我正在尝试重新创建去的游戏,我已经创建了板,并能够将石头放置在网格的交叉口。
我现在要开始捕获被包围的石头。我在网上查了一下,发现洪水是解决这个问题的最好方法。然而,我已经在网上搜索了好几天了,我找不到任何我可以使用或操作的东西来创建它。我不懂任何其他的编程语言,所以我不能使用Java等的代码,而且我发现的用于Visual的一些信息对我来说没有多大意义,因为我仍然是个初学者。
我试着自己动手,从“如果一颗石头被抓住”的情况开始。我有两个董事会代表,一个被声明为“网格”,另一个被声明为"placed_stone“。
“网格”是用户点击放置石头的实际板。placed_stone是这个板的副本,但我用"0“、"1”和"2“分别表示空、黑和白。我正在使用Windows窗体重新创建这个游戏。这是我为捕获石块而编写的代码段:
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编程。
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中轻松地使用洪水填充以及如何在这个围棋游戏中实现它吗?
如果有人想看完整的代码,请告诉我。如有任何建议,我将不胜感激!
发布于 2018-01-03 14:25:17
我不太熟悉游戏的游戏规则,所以我不确定你到底想要完成什么,但是如果你相信一种充满洪水的算法是你所需要的,那么我至少可以给你一些建议。您的代码需要的首要任务是将其分解为更细粒度的方法。单击面板时,尝试执行哪些步骤?当然,这不仅仅是一回事。有许多不同的事情正在进行--每一件事情都可以通过一个单独的专用方法来执行。例如,如果您有这样的方法:
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当一个方法调用自己时,我们称之为递归。但是,除非您开始将代码拆分为专用的小方法,每个方法都有自己的封装任务,否则您就不能真正添加递归。所以,首先组织起来,然后再添加递归。
https://stackoverflow.com/questions/48078334
复制相似问题