You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

河流生成算法中瓦片相邻区域比较代码的优化方案问询

优化河流生成算法的相邻瓦片检查逻辑

嘿,我完全懂你现在的烦恼——重复写一堆几乎一模一样的if语句不仅代码臃肿到难以维护,后续要扩展更远的相邻瓦片检查时,代码量会爆炸式增长,还会拖慢运行效率。咱们来重构这段逻辑,让它更简洁、高效,还能轻松扩展。

核心问题分析

你的原代码里,8次重复的if本质上只是遍历当前瓦片的8个相邻方向,每次做的操作都是:计算相邻坐标→获取降雨值→判断条件→设置瓦片。这种重复劳动完全可以用「方向数组+循环」来替代。

第一步:用方向数组消除代码冗余

首先,我们把8个相邻方向的偏移量(列偏移dx,行偏移dy)整理成一个数组,这样只需要一次循环就能遍历所有相邻位置:

// 定义8个相邻方向的偏移量(覆盖上下左右+四个对角线)
let neighborOffsets: [(Int, Int)] = [
    (-1, 1), (-1, 0), (-1, -1),
    (0, -1), (1, -1), (1, 0),
    (1, 1), (0, 1)
]

第二步:重构核心逻辑

接下来把原有的重复逻辑改成循环遍历,同时还能顺便实现你提到的「找出最低值」的需求:

// 先获取当前瓦片的降雨值,避免重复调用方法
let currentRain = Rain.value(atPosition: vector_float2(Float(columns), Float(rows)))

if currentRain == 1.0 {
    var shouldSetRiverTile = false
    var minNeighborRain = Float.greatestFiniteMagnitude
    var minRainPosition: (col: Int, row: Int)? // 记录降雨最低的相邻瓦片位置

    // 遍历所有相邻方向
    for (dx, dy) in neighborOffsets {
        let neighborCol = columns + dx
        let neighborRow = rows + dy
        
        // 👉 这里一定要加边界检查!避免访问超出地图范围的无效瓦片
        guard neighborCol >= 0, neighborCol < mapWidth, 
              neighborRow >= 0, neighborRow < mapHeight else {
            continue
        }

        let neighborRain = Rain.value(atPosition: vector_float2(Float(neighborCol), Float(neighborRow)))
        
        // 检查是否满足降雨条件
        if neighborRain == 0.9 {
            shouldSetRiverTile = true
        }
        
        // 追踪降雨值最低的相邻瓦片
        if neighborRain < minNeighborRain {
            minNeighborRain = neighborRain
            minRainPosition = (neighborCol, neighborRow)
        }
    }

    // 只要有一个相邻瓦片满足条件,就设置当前瓦片为河流
    if shouldSetRiverTile {
        fullMap.setTileGroup(tileDef4, forColumn: columns, row: rows)
    }

    // 👉 如果后续需要根据最低值瓦片做更多逻辑(比如河流流向),可以用minRainPosition
    // 比如:if let minPos = minRainPosition, minNeighborRain < 0.8 { ... }
}

第三步:性能升级——缓存降雨值

如果Rain.value(atPosition:)是一个比较耗时的操作(比如从纹理读取、实时计算Perlin噪声),提前缓存整个降雨地图到二维数组能大幅提升效率,避免重复的方法调用和坐标转换:

// 提前初始化并缓存整个降雨地图(假设你知道地图的宽mapWidth、高mapHeight)
var rainCache: [[Float]] = Array(repeating: Array(repeating: 0.0, count: mapHeight), count: mapWidth)
for col in 0..<mapWidth {
    for row in 0..<mapHeight {
        rainCache[col][row] = Rain.value(atPosition: vector_float2(Float(col), Float(row)))
    }
}

之后访问降雨值时,直接用数组索引即可,速度快很多:

// 替换原来的Rain.value调用
let neighborRain = rainCache[neighborCol][neighborRow]

扩展建议

如果后续需要检查更远的相邻瓦片(比如2格、3格外),只需要在外层加一个控制距离的循环,生成对应范围的偏移量即可,比如检查距离为n的所有瓦片:

let maxDistance = 2 // 检查2格范围内的所有瓦片
for dx in -maxDistance...maxDistance {
    for dy in -maxDistance...maxDistance {
        guard dx != 0 || dy != 0 else { continue } // 跳过当前瓦片本身
        let neighborCol = columns + dx
        let neighborRow = rows + dy
        // 后续逻辑同上...
    }
}

这样不管你要检查多少范围的瓦片,代码量都不会爆炸,逻辑也清晰很多。

内容的提问来源于stack exchange,提问作者E. Huckabee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:38:27