广度优先搜索:线程 1:Swift 运行时失败:强制解包一个 nil 值

Breadth First Search: Thread 1: Swift runtime failure: force unwrapped a nil value

我尝试编写一个“圆点”游戏。因此,我必须对 UIButtons 的二维数组进行 Breath First Search 以找到从 playerButton 到边框的最短路径。

不幸的是,我有时会在几天内收到 线程 1:Swift 运行时故障:强制解包一个零值 错误我就是找不到问题所在。

这是程序的一个功能,return要移动下一个x和y坐标。那就是我做 BFS 的地方。

func findDirection()->String{
    var blocked: [String] = [] 
    let queue = otherQueue<Pair>()
    let pair = Pair()
    var possibleNeighbours = findPossibleNeighbours(btn: btnArr[playerX][playerY], blockedArr: blocked)
    
    for neighbour in possibleNeighbours{
        if(isOnBorder(point: neighbour)){
            return neighbour
        }
        pair.setPair(firstValue: neighbour, secondValue: neighbour)
        queue.enqueue(key: pair)
        blocked.append(neighbour)
    }
    
    //Start the search
    while(!queue.isEmpty){
        let pointPair = queue.dequeue()

        // !!!!!! THIS IS THE ERROR LINE: 
        let button = btnArr[getXFromString(string: (pointPair?.getFirst())!)][getYFromString(string: (pointPair?.getFirst())!)] 
        
        possibleNeighbours = findPossibleNeighbours(btn: button, blockedArr: blocked)
        for neighbour in possibleNeighbours{
            if isOnBorder(point: neighbour){
                return (pointPair?.getSecond())!
            }
            pair.setPair(firstValue: neighbour, secondValue: (pointPair?.getSecond())!)
            queue.enqueue(key: pair)
            blocked.append(neighbour)
        }
    }
    return "-1 -1"
}

问题:

它说 pointPair?.getFirst()! 被强制展开一个 nil 值。 pointPair 是我从队列中取出的 Pair。所以我的猜测是我的队列是空的并试图出列。查了好几遍,竟然写了一个新的QueueClass。那不是问题, !queue.isEmpty 工作正常,这是 while-condition。下一个猜测是 getFirst(),return 是我的 Pair 的第一个值,return 是一个 nil 值。这对我来说也没有意义,因为第一个值是 possibleNeighbours-Array 的迭代 neighbour,它不能为 nil(如果它是可能的邻居并且显然存在,它只会添加到数组中)。

当点只有两种可能的移动方式时,问题总是会发生。以这个为例

蓝点从 (4, 4) 开始。然后我点击 (2, 3),点移动到 (3, 3)。然后我点击 (2, 4),点移动到 (3, 4)。然后按钮必须有可能的方式:移动到 (2, 5) 或 (3, 5)。如果您现在单击两者之一,它会崩溃。在控制台中,我可以读到在单击 (2, 5) 后队列仅包含 ["3 5"] 这是正确的,因为 (3, 5) 是继续前进的唯一方法。不知何故,它不会移动到那里,并用力崩溃并解开一个 nil 值...

如果你想下载我的整个项目并测试它,你可以这样做 here(希望 link 有效)。

您知道失败的原因吗? :(

感谢您的帮助!

您的问题在于 otherQueue 中的 dequeue 函数如何工作。您在返回数据之前调整指针,这导致在从具有一个条目的队列中移除头部后返回 nil

尝试类似...

func dequeue() -> T? {
    if self.head?.data == nil { return nil  }
    let result = head?.data
    if let nextItem = self.head?.next {
        head = nextItem
    } else {
        head = nil
    }
    return result
}

此外,您不应该在 while(!otheryQueue.isEmpty || otheryQueue.dequeue() != nil) 中调用 dequeue