Visual Basic 中围棋游戏的洪水填充

2023-12-11

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

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

我尝试自己开始,从“如果一块石头被捕获”的情况开始。我对棋盘有两种表示,一种被声明为“grid”,另一种被声明为“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 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.

当然,在围棋中,您不是在该区域着色,而是在捕获时必须移除石头,并且您不会从刚刚放置捕获的石头开始洪水填充,而是从您想要捕获的最近的石头开始。

您能解释一下如何在 Visual Basic 中简单地使用洪水填充以及如何将其应用到围棋游戏中吗?

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


我不熟悉围棋游戏的规则/游戏玩法,所以我不确定您到底想要完成什么,但如果您认为洪水填充类型的算法是您所需要的,那么我至少可以就如何做到这一点提供一些建议。您的代码需要的首要任务是将其分解为更细粒度的方法。单击该面板时您尝试执行哪些步骤?当然,这不仅仅是一件事。有许多不同的事情正在发生——每一件事情都可以通过单独的专用方法来执行。例如,如果您有这样的方法:

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Visual Basic 中围棋游戏的洪水填充 的相关文章

  • 如何使用 VB.NET 打开受密码保护的共享网络文件夹?

    我需要在网络上打开受密码保护的共享文件夹才能访问 Access 97 数据库 如何打开文件夹并输入密码 在这里找到http www mredkj com vbnet vbnetmapdrive html http www mredkj co
  • 在 Visual Basic 中将窗体放置在屏幕右下角

    当表单加载时 如何将表单定位在屏幕的右下角 我正在使用 Visual Basic 2010 Express Thanks 编辑 我这样做了 看起来效果很好 Dim x As Integer Dim y As Integer x Screen
  • 洪水填充优化:尝试使用队列

    我正在尝试创建一种填充方法 该方法采用用户指定的初始坐标 检查字符 然后根据需要更改它 这样做之后 它会检查相邻的方块并重复该过程 经过一番研究 我遇到了洪水填充算法并尝试了该算法 它可以工作 但无法满足我对 250 x 250 个字符的数
  • 设置表单的背景颜色

    Private Sub HScrollBar1 Scroll ByVal sender As Object ByVal e As ScrollEventArgs Handles HScrollBar1 Scroll Me BackColor
  • 插入具有只读主键列的表

    我正在使用一个使用 sql server 数据库的应用程序 我试图在表中插入一行 如下所示 该表有一个主键 prodNum 这是自动生成的密钥 当我尝试向表中插入一行时 如下所示 在行中intResult oSglProdTableAdap
  • 从字体到跨度(大小和颜色)和背面的正则表达式(VB.NET)

    我正在寻找一个正则表达式 可以将我的字体标签 仅具有大小和颜色属性 转换为具有相关内联CSS的span标签 如果有帮助的话 这将在 VB NET 中完成 我还需要一个正则表达式来实现相反的效果 下面详细说明的是我正在寻找的转换示例 font
  • SQL存储过程执行时间差异

    我在 win form 应用程序中遇到奇怪的问题 我正在调用一个存储过程 并且执行大约需要 6 秒 此存储过程接受多个参数 包括一个输出参数 从应用程序级别我使用 Dim dt1 DateTime Now cmd ExecuteNonQue
  • 使用 Group By LINQ 语句时 VB.NET 返回 IEnumerable(Of IEnumerable(Of T))

    我正在尝试转换安西姆 凯拉德INotifyDataErrorInfo执行 http burnaftercoding com post asynchronous validation with wpf 4 5 进入VB NET 一切顺利 直到
  • 需要将用户名和密码添加到 VB.NET Web 服务客户端中的 SOAP 标头

    我需要查询一个进行基本身份验证的 Web 服务 将用户名和密码放在请求标头中 我的客户端是用 VB NET Visual Basic Express Edition 2010 编写的 我已将 Web 服务添加到服务引用中 它为我自动生成了合
  • VB无法访问不同项目中的类,相同的解决方案

    我正在使用 VB for Visual Studio 工作 并且项目中有一个类需要将变量声明为另一个项目中的类 对于可视化 解决方案 A 包含 Project1 和 Project2 在 Project1 的类中 我需要声明一个变量作为 P
  • 使用 DirectCast、CType、TryCast 转换数据类型

    自从我在 2005 年从 VB6 迁移到 VB NET 以来 我一直在使用 CType 将一种数据类型转换为另一种数据类型 我这样做是因为它打字速度更快 以前存在于 VB6 中 而且我不知道为什么我必须使用 DirectCast 如果它们之
  • 创建 Visual Studio 风格的选项/设置对话框

    我目前正在改进 winforms 应用程序的选项对话框 目前我正在使用选项卡控件 我想为类似于 Visual Studio 的设置创建一个表单 对话框 这是怎么做到的 我可以在左侧看到类似树视图的控件 但是他们使用什么控件来显示每个选项页面
  • VB.NET - 有没有办法在委托中使用可选参数? (或者计划允许这样做?)

    据我了解 在 VS2008 附带的 VB 版本中 委托中不可能有可选参数 但是 我想知道将来是否有任何解决方法或计划将此功能合并到 VB NET 中 我想做的事 Public Delegate Function Deserializer O
  • 您可以将委托函数作为可选参数传递吗?

    我知道在 Visual Basic 中 委托函数不能contain可选参数 但是方法可以将委托作为可选参数吗 我想做的是这样的 Delegate Sub MyDelegate ByVal input As String Sub MyDele
  • ArrayList 搜索 .net

    以下是存储在我的数组列表中的数据的格式 A Amsterdam B Brussels C Canada 如此等等 我想通过仅传递前几个字符直到 来搜索我的数组列表 因此 如果我有类似 AA Test 的东西 那么我只想通过 AA 来检查它是
  • 如何在 vb.Net 中设置默认表单?

    如何将第四个表单设置为在 Visual Studio 2008 中按 f5 时将运行的默认表单 因为表单 1 始终是第一个启动的 在解决方案资源管理器中右键单击您的项目 选择属性 选择应用程序选项卡 从 启动表单 下的下拉列表中选择您的表单
  • 在VB.net中动态添加用户控件

    我在 Vb net Windows 应用程序 中制作了自定义 UserControl 如何将其动态添加到表单中 UserControl 本质上只是另一个类 它继承自 Control 因此您可以使用控件执行各种操作 但除此之外它只是一个类 因
  • 使用 CoCreateInstance 从 C++ 调用 COMVisible VB.Net dll

    自从我上一个问题以来 在某种程度上取得了进展 我已经编译了以下项目 它是基于https stackoverflow com a 10949784 846550 https stackoverflow com a 10949784 84655
  • 回发 Asp.Net 上的动态用户控件

    我创建了一个项目 user control 它有一个文本框 按钮等 它将有意收集用户想要的项目总数 我在 page load 上动态创建了几个 user control 实例 如果您单击项目数量的添加按钮 它将添加到会话变量中 但是 当用户
  • 从 RichTextBox 复制文本及其格式

    如何将 RichTextBox 中的文本及其格式复制到写字板或网络浏览器 就像复制纯文本一样 您可以使用Clipboard SetText method http msdn microsoft com en us library 6eahs

随机推荐

  • 从 XPath 表达式填充 XML 模板文件?

    从 XPath 表达式的映射填充 或生成 XML 模板文件的最佳方法是什么 要求是我们需要从模板开始 因为这可能包含 XPath 表达式中未捕获的信息 例如 起始模板可能是
  • 在c中不使用线程和sleep()方法定期调用函数

    我想调用一个函数 假设每 10 或 20 秒调用一次 当我搜索时 我想出了一些线索sleep 方法无处不在 我还检查了 C 中的时间和时钟类 但找不到任何对我的问题有帮助的内容 定期调用函数的最简单方法是什么 Use libevent在我看
  • 来自 Windows 窗体应用程序的 HTTP Post C#

    我需要用 C 编写一个表单应用程序 通过 HTTP POST 将参数发送到 url 并返回响应 我真的不知道从哪里开始 这可能吗 预先感谢 加尔 首先请参阅 1 HttpWebRequest类 2 HttpWebResponse类 3 We
  • 如何使谷歌表格公式只计算一次?

    我的 Google 表格中有 3 行 即股票 价格和总计 所以 我只是对股票和价格使用 多个 公式 然后将值放入总行中 但我不希望每当我更改库存值时总行都会更新或更改值 有人能帮我吗 假设您希望单元格 A1 只计算一次其值 您可以将以下内容
  • 在 ASP.NET MVC 中跟踪 LINQ TO SQL 生成的查询

    关于 LINQ to SQL 生成的查询输出的快速问题 我正在使用 ASP NET MVC 项目 Visual Studio 2008 并且正在尝试 MSDN 文档中的建议 MyDataContext dc new MyDataContex
  • MOQ- 使用 Func 参数设置和验证通用方法

    我有一个第三方接口 我想模拟它的方法 为了明确我的目的 请考虑以下 IFoo 接口 它具有像 M2 这样的通用方法 M2 参数之一的类型为 Func public interface IFoo bool M1
  • 从 HandlerInterceptor 抛出 HTTP 状态代码异常

    我正在尝试创建一个 HandlerInterceptor 其预处理的代码结构如下 public boolean preHandle HttpServletRequest req HttpServletResponse res Object
  • 如何删除基于另一个 DataFrame 的列上的 DataFrame 中的行?

    我正在尝试使用SQLContext subtract 在 Spark 1 6 1 中 根据另一个数据帧中的列从数据帧中删除行 让我们举个例子 from pyspark sql import Row df1 sqlContext create
  • FAB 的片段布局与 CoordinatorLayout 冲突

    我在用着材料抽屉 with a MainDrawerActivity我替换里面的每个片段容器 FrameLayout基于所选项目 但我想添加一个与以下项交互的 FAB 仅针对此片段 CoordinatorLayout所以它可以处理很酷的动画
  • 将小数转换为分数

    我正在尝试将十进制数转换为其分数 小数点后最多有 4 位数字 示例 12 34 1234 100 12 3456 123456 10000 我的代码 include
  • 弃用 FBML

    您可能已经知道 或阅读本文末尾的引用 Facebook 正在弃用 FBML 转而使用 iframe 来开发应用程序 我目前正在启动一个新的浏览器插件 需要在我的 Facebook 页面上有一个登陆选项卡 其中包含个性化安装按钮以及人们希望在
  • 为什么我不能使用两个 i32 参数调用 gen_range?

    我有这段代码 但它无法编译 use rand Rng use std io fn main println Guess the number let secret number rand thread rng gen range 0 101
  • 在 Ajax 中处理非常大的长数字的最佳方法?

    Javascript 将所有数字表示为双精度浮点数 这意味着在处理 64 位 Java Long 数据类型最高端的数字 17 位数字之后的任何数字 时 它会失去精度 例如 数字 714341252076979033 变为 714341252
  • For 循环迭代字符串切片不起作用

    我编写了这段代码 它将小写英语短语翻译成猪拉丁语 package main import fmt strings bufio github com stretchr stew slice regexp os func main lst st
  • Qt:当主窗口被模式 QDialog 阻塞时,如何将焦点集中到从主窗口创建的无模式 QDialog

    在我的 Qt 应用程序中 我面临以下场景 当引发特定事件时 我会显示无模式QDialog要求用户确认 对话框显示使用show 函数从一个QMainWindow 任何时候引发事件并且没有其他模式QDialog显示后 用户可以单击确认按钮 不幸
  • 后台信标监控的响应能力(Android Beacon Library / Kontakt SDK / Estimote SDK)

    背景 我正在开发一个 Android 应用程序 用于监视后台的特定信标 并在检测到进入时执行自定义编码 我目前正在使用 Android Beacon Library 进行探索 并且能够在屏幕打开时 几秒钟内 的大部分时间响应地检测到信标 但
  • 简单数组处理循环的 AVX 512 与 AVX2 性能对比

    Closed 这个问题需要调试细节 目前不接受答案 我目前正在研究一些优化并比较 DSP 应用程序的矢量化可能性 这对于 AVX512 来说似乎是理想的选择 因为这些只是简单的不相关数组处理循环 但在新的 i9 上 与 AVX2 相比 使用
  • 使用 Symfony2 翻译 JS 文件

    我目前正在开发一个应用程序 需要使用我的 JavaScript 的翻译 BazingaJsTranslationBundle 包似乎不错 但在我尝试之后 我认为它不符合我的需求 它为我的所有应用程序包生成所有翻译 负载可能很重 您知道其他捆
  • 如何使用 xmllint/xpath 解析不同元素上的多个属性的值?

    对于给定的 xml 文件 称为配置文件 xml我想提取value每个conf元素 并将其存储在变量中以供以后使用
  • Visual Basic 中围棋游戏的洪水填充

    我是 Visual Basic 的业余爱好者 我正在尝试重新创建游戏Go 我已经创建了棋盘 并且能够将石头放置在网格的交叉点上 我现在想开始捕捉被包围的石头 我在网上查了一下 发现洪水填充是解决这个问题的最佳方法 然而 我在网上查了好几天