广度优先搜索:找不到路径,二维数组中到边界的最短路径

2024-01-07

我尝试编写一个“绕点”游戏。基本的游戏理念是,你必须在蓝点逃脱之前包围它。每放置一个障碍物(橙色点),蓝色点(“玩家”)就会向边界移动一步。如果你在他到达边界之前没有圈出蓝点,那么你就输了,游戏将重新开始。

因此我必须做一个对 UIButton 的 2D 数组进行呼吸优先搜索找到从playerButton到边界的最短路径。

问题:

它通常找不到通往边界的路径(在控制台中打印“未找到路径!”并重新启动),即使蓝点可能有通往边界的路径/该点没有被橙色点包围。它也不会走最短路径,有时该点只是循环。下、上、下……这使得获胜变得非常容易。

我的项目:

最好的事情是如果你可以下载我的项目 https://www.dropbox.com/s/mtl410wzrg3elwg/dot%202%202.zip?dl=0(总共300行代码)here https://www.dropbox.com/s/mtl410wzrg3elwg/dot%202%202.zip?dl=0然后您可以使用这些模式测试问题:(在给定的序列中单击标记的按钮/点)

  1. 找不到可能的路径,但有很多条:(1,2) -> (0,3) -> (1,4)

  2. 找不到可能的路径,但有一条: (2,2) -> (1,3) -> (2,4) -> (2,5) -> (3,5) -> (4,4) -> (3,3)

  3. 向上/向下/向上/...循环:(3,4) -> (2,3) -> (2,2) -> (1,1) -> (1,0) -> (3,4) ) -> (3,5) -> (4,6) -> (4,7) -> (5,8)

重要提示:查看这些问题的方法有无数种,这 3 种模式只是为了更快地找到问题,并且您不必多次播放直到出现问题。另外,你必须让第 94 行(possibleNeighbours.shuffle())未注释,因为这会使模式随机化。

如果您不想下载我的整个项目,您可以查看我的广度优先搜索方法,该方法返回蓝点必须移动到的下一个 x 和 y 坐标:

    func findDirection()->String{
    var blockedArr:  [[Bool]] = [[false, false, false, false, false, false, false, false, false],
                                 [false, false, false, false, false, false, false, false, false],
                                 [false, false, false, false, false, false, false, false, false],
                                 [false, false, false, false, false, false, false, false, false],
                                 [false, false, false, false, false, false, false, false, false],
                                 [false, false, false, false, false, false, false, false, false],
                                 [false, false, false, false, false, false, false, false, false],
                                 [false, false, false, false, false, false, false, false, false],
                                 [false, false, false, false, false, false, false, false, false]] // Can do it like this as its always 9X9
    
    for btnline in btnArr{ //Block all dots which are already occupied
        for btn in btnline{
            if(btn.backgroundColor != defaultColor){
                blockedArr[getX(btn: btn)][getY(btn: btn)] = true
            }
        }
    }
    
    let otheryQueue = otherQueue<Pair>()
    let pair = Pair()
    var possibleNeighbours = findPossibleNeighbours(btn: btnArr[playerX][playerY], blockedArr: blockedArr) //returns array of all possible neighbours of given dot
    print(String(possibleNeighbours.description) + " possibeNeighs beginning" )
   //possibleNeighbours.shuffle() //IMPORTANT: Uncomment this to make it more random
    
    for neighbour in possibleNeighbours{
        if(isOnBorder(point: neighbour)){
            print("Blue dot is on border")
            return neighbour
        }
        pair.setPair(firstValue: neighbour, secondValue: neighbour)
        otheryQueue.enqueue(key: pair)
        blockedArr[getXFromString(string: neighbour)][getYFromString(string: neighbour)] = true
    }
    
    // Start the search
    while(!otheryQueue.isEmpty){
        let pointPair = otheryQueue.dequeue()
        let button = btnArr[getXFromString(string: (pointPair?.getFirst())!)][getYFromString(string: (pointPair?.getFirst())!)]
        possibleNeighbours = findPossibleNeighbours(btn: button, blockedArr: blockedArr)
        for neighbour in possibleNeighbours{
            if isOnBorder(point: neighbour){
                return (pointPair?.getSecond())!
            }
            pair.setPair(firstValue: neighbour, secondValue: (pointPair?.getSecond())!)
            otheryQueue.enqueue(key: pair)
            blockedArr[getXFromString(string: neighbour)][getYFromString(string: neighbour)] = true
        }
    }
    print("No path found!")
    return "-1 -1" //return (-1, -1) position if NO PATH FOUND
}

这是游戏视图的屏幕截图,有助于理解 (1,2)、(0,3)、蓝点等的含义:

如果有问题请提问。

谢谢你的帮助!!

斯威夫特爱好


你的里面有这段代码findDirection() func:

    let otheryQueue = otherQueue<Pair>()
    let pair = Pair()
    var possibleNeighbours = findPossibleNeighbours(btn: btnArr[playerX][playerY], blockedArr: blockedArr) //returns array of all possible neighbours of given dot
    print(String(possibleNeighbours.description) + " possibeNeighs beginning" )
   //possibleNeighbours.shuffle() //IMPORTANT: Uncomment this to make it more random
    
    for neighbour in possibleNeighbours{
        if(isOnBorder(point: neighbour)){
            print("Blue dot is on border")
            return neighbour
        }
        pair.setPair(firstValue: neighbour, secondValue: neighbour)
        otheryQueue.enqueue(key: pair)
        blockedArr[getXFromString(string: neighbour)][getYFromString(string: neighbour)] = true
    }

    // Start the search
    while(!otheryQueue.isEmpty){
       ...

为了调试,我在“开始搜索”之前添加了以下内容:

    var p = otheryQueue.first
    while p != nil {
        print("first", p?.data.first, "second", p?.data.second)
        p = p?.next
    }
    
    // Start the search
    while(!otheryQueue.isEmpty){
       ...

如果我首先点击任何灰点,例如0 0,我在控制台中得到的输出是:

Button 0 0 tapped
["4 3", "5 4", "4 5", "3 5", "3 4", "3 3"] possibeNeighs beginning
first Optional("3 3") second Optional("3 3")
first Optional("3 3") second Optional("3 3")
first Optional("3 3") second Optional("3 3")
first Optional("3 3") second Optional("3 3")
first Optional("3 3") second Optional("3 3")
first Optional("3 3") second Optional("3 3")

(如果我先点击3 3输出将全部为“3 4”)。

您的代码仅创建一个pair对象,然后每次通过循环修改其值。

您可能想创建一个new pair每次你想要的时候都反对.enqueue it:

    for neighbour in possibleNeighbours{
        if(isOnBorder(point: neighbour)){
            print("Blue dot is on border")
            return neighbour
        }
        
        // add this line
        let pair = Pair()
        
        pair.setPair(firstValue: neighbour, secondValue: neighbour)
        otheryQueue.enqueue(key: pair)
        blockedArr[getXFromString(string: neighbour)][getYFromString(string: neighbour)] = true
    }

现在我第一次点击时控制台输出0 0 is:

Button 0 0 tapped
["4 3", "5 4", "4 5", "3 5", "3 4", "3 3"] possibeNeighs beginning
first Optional("4 3") second Optional("4 3")
first Optional("5 4") second Optional("5 4")
first Optional("4 5") second Optional("4 5")
first Optional("3 5") second Optional("3 5")
first Optional("3 4") second Optional("3 4")
first Optional("3 3") second Optional("3 3")

您可能想在下一个块(搜索块)中执行相同的操作:

    // Start the search
    while(!otheryQueue.isEmpty){
        let pointPair = otheryQueue.dequeue()
        let button = btnArr[getXFromString(string: (pointPair?.getFirst())!)][getYFromString(string: (pointPair?.getFirst())!)]
        possibleNeighbours = findPossibleNeighbours(btn: button, blockedArr: blockedArr)
        for neighbour in possibleNeighbours{
            if isOnBorder(point: neighbour){
                return (pointPair?.getSecond())!
            }
            
            // add this line
            let pair = Pair()
            
            pair.setPair(firstValue: neighbour, secondValue: (pointPair?.getSecond())!)
            otheryQueue.enqueue(key: pair)
            blockedArr[getXFromString(string: neighbour)][getYFromString(string: neighbour)] = true
        }
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

广度优先搜索:找不到路径,二维数组中到边界的最短路径 的相关文章

随机推荐

  • 配置 Spring Kafka 以使用 DeadLetterPublishingRecoverer

    我正在使用 Spring Boot 2 1 3 并尝试配置 SpringSeekToCurrentErrorHandler with a DeadLetterPublishingRecoverer将错误记录发送到不同的主题 创建新的 DLT
  • 遇到顺序友好/不友好的终端操作 vs 并行/顺序 vs 有序/无序流

    灵感来自这个问题 https stackoverflow com questions 44944973 search for example of inconsistent behavior java 8 stream 我开始研究有序流与无
  • 如何将 Breeze 与通用工作单元和存储库一起使用?

    使用这个 https genericunitofworkandrepositories codeplex com https genericunitofworkandrepositories codeplex com 以及以下一组博客文章
  • UI文本字段密码

    我知道可以使用以下命令使 UITextfield 在密码模式下运行 textfield secureTextEntry YES 这会将用户输入的所有字符更改为 然而 最后输入的字符会闪烁大约半秒 我知道这是标准行为 有什么方法可以阻止这种情
  • 如何从另一个网站“抓取”内容

    有朋友问过我这个问题 我无法回答 他问道 我正在制作这个网站 您可以在其中存档您的网站 它的工作原理是这样的 您输入您的网站 例如 something com 然后我们的网站抓取该网站上的内容 例如图像等 并将其上传到我们的网站 这样 即使
  • 如何反编译正则表达式?

    有没有办法在编译后反编译正则表达式 编译后的正则表达式对象有一个 pattern 属性 它给出原始文本模式 gt gt gt import re gt gt gt regex re compile foo bar gt gt gt rege
  • 在 Codeigniter 2 中扩展多个模型

    如何设置 CI2 以允许扩展多个模型 我只能让它扩展一个名为的模型 放入 application core MY Model 区分大小写 选择我正在做的扩展模型 在模型 require once APPPATH core MY Anothe
  • 如何在 Scala 中获取用户的输入?

    我想接受用户的输入 你能告诉我如何在 Scala 中以字符串形式请求用户输入吗 在 Scala 2 11 中使用 scala io StdIn readLine 而不是已弃用的Console readLine
  • 如何在没有调试符号和优化的情况下创建 cmake 构建配置?

    我认为默认配置类型可以这样描述 Debug w debug symbols w o optimization Release w o debug symbols w optimization RelWithDebInfo w debug s
  • 如何将 d3.js 示例嵌入到 Jekyll 博客文章中?

    我正在尝试这个 Jekyll 主题http richbray me frap http richbray me frap 我想创建一篇博客文章来展示这个 D3 js 示例 http bl ocks org mbostock 4061502
  • Django:如何在管理表单中获取当前用户?

    在姜戈的ModelAdmin 我需要显示根据用户拥有的权限定制的表单 有没有办法将当前用户对象放入表单类中 以便我可以在其中自定义表单 init method 我认为将当前请求保存在本地线程中是可能的 但这将是我的最后手段 因为我认为这是一
  • 为什么内存警告为 4 MB 利用率和 320 MB 可用空间?

    我正在运行附加到 Xcode 5 1 1 的 iOS 7 1 的 iPhone 4 上进行测试 我不明白为什么当仪器显示我的应用程序仅使用几兆字节并且有大量可用内存时 我会收到内存警告甚至崩溃 请参阅附件 有任何想法吗 Update 正如我
  • 从 Excel 工作表获取数据

    如何将 Excel 工作表中的数据加载到 Django 应用程序中 我使用数据库 PosgreSQL 作为数据库 我想以编程方式执行此操作 客户希望每周将两个不同的列表加载到网站上 但他们不想在管理部分中执行此操作 他们只想从 Excel
  • 在此范围内未声明“pthread_setname_np”

    我在我的应用程序中创建了多个线程 我想为每个 pthread 分配一个名称 所以我使用pthread setname np它可以在 Ubuntu 上运行 但不能在 SUSE Linux 上运行 我用 google 搜索了一下 发现 np 的
  • Intellij IDEA 未检测到更改

    昨天 我重构了我的项目 并更改了包的布局 我将一些包移动到另一个包中 创建了新包等 但现在 当我尝试运行 JUnit 测试时 我得到了NoSuchMethodError重构后名称更改的方法 另外 当我更改方法中的其他代码时 IDEA 仍然运
  • 无法找到 com.facebook.katana.provider.platformprovider 和 com.facebook.wakizashi.provider.platformprovider 的提供商信息

    在我的 Android 应用程序中 我使用 FacebookDialog 我正在写下以下代码 在 Galaxy Note 3 Android 4 4 2 中 一切顺利 然而 在Experia SOL21 Android4 1 2 中却没有
  • 恢复 SQL Server 数据库之前等待连接关闭

    我有一个使用两个数据库的网络应用程序 DB1 用户执行 CRUD 创建 读取 更新 删除 操作 数据库 DB2 是位于另一台服务器上的只读数据库 我将其用于报告目的 我的 DB1 每小时都会保存事务日志 而在 DB2 上 我有一项工作需要在
  • 使用 RESTful URL 能给我带来什么?

    我一直在阅读有关 REST 的内容 并试图找出使用它的优势是什么 具体来说 REST 样式的 URL 相比于带有查询字符串的更典型的 GET 请求有什么优势 值得实现 为什么是这个网址 http www parts depot com pa
  • 减少 HTML

    我的网页中有以下 HTML Forum ul li Stack li li OverFlow li ul 正如您在下面看到的 我完美地列出了项目 但是之间存在固定的差距 ul and li 元素 有什么办法可以缩小这个差距吗 即附加屏幕中
  • 广度优先搜索:找不到路径,二维数组中到边界的最短路径

    我尝试编写一个 绕点 游戏 基本的游戏理念是 你必须在蓝点逃脱之前包围它 每放置一个障碍物 橙色点 蓝色点 玩家 就会向边界移动一步 如果你在他到达边界之前没有圈出蓝点 那么你就输了 游戏将重新开始 因此我必须做一个对 UIButton 的