NetLogo六边形细胞聚合森林火灾模型点火功能故障求助
六边形森林火灾模型Ignite函数失效排查与修复方案
核心排查方向
针对ignite函数无效、火灾无法传播的问题,优先从以下关键环节排查:
1. 六边形邻居坐标计算错误
六边形网格的邻居逻辑和矩形网格完全不同,若邻居索引计算错误,会导致火灾无法找到可传播的目标细胞,甚至初始点火的细胞状态更新无法被感知:
- 若使用轴向坐标,6个邻居的偏移应为
(1,0), (1,-1), (0,-1), (-1,0), (-1,1), (0,1)(满足q+r+s=0的约束); - 若使用偏移坐标(如偶行偏移),需区分奇偶行的列偏移:偶行邻居列偏移为
-1,0,1,奇行邻居列偏移为0,1,-1(行偏移均为-1,0,1,排除自身); - 务必检查邻居坐标是否在网格有效范围内,避免访问空细胞。
2. 细胞状态判断与更新逻辑漏洞
ignite函数的核心是状态切换,若状态判断或更新逻辑错误,会直接导致点火失效:
- 确认状态枚举值是否统一:比如定义
STATE_FOREST=0, STATE_BURNING=1, STATE_ASH=2,ignite函数仅能将STATE_FOREST的细胞切换为STATE_BURNING; - 检查状态更新是否作用于全局网格:若仅修改了局部变量而非网格中的实际细胞对象,状态变化不会被保存。
3. 初始点火的范围与有效性问题
随机初始点火若选中无效细胞,会出现“看似没点火”的假象:
- 随机生成的细胞坐标必须在网格的行列范围内(如行索引
0 <= r < rows,列索引0 <= c < cols); - 初始点火前需筛选出状态为“森林”的细胞,避免选中已燃烧或灰烬状态的细胞。
4. 主循环(Go函数)的执行顺序错误
若主循环中实时修改细胞状态,会导致同一帧内的状态干扰,引发传播逻辑混乱:
- 正确流程:先遍历所有燃烧细胞,收集所有可点燃的邻居;再统一将这些邻居点燃;最后将燃烧细胞转为灰烬。禁止在遍历过程中直接修改细胞状态。
修复示例代码
以下是基于轴向坐标的六边形火灾模型核心实现,可直接参考调整你的代码:
细胞结构定义
class HexCell: def __init__(self, q, r): self.q = q # 轴向坐标q self.r = r # 轴向坐标r self.s = -q - r # 轴向坐标s(满足q+r+s=0) self.state = 0 # 0: 未燃烧森林, 1: 燃烧中, 2: 灰烬
邻居获取函数
def get_neighbors(cell, grid): # 六边形6个方向的轴向偏移 directions = [(1,0), (1,-1), (0,-1), (-1,0), (-1,1), (0,1)] neighbors = [] for dq, dr in directions: nq = cell.q + dq nr = cell.r + dr # 检查邻居是否在网格内 if (nq, nr) in grid: neighbors.append(grid[(nq, nr)]) return neighbors
Ignite函数实现
def ignite(cell): # 仅未燃烧的森林可被点燃 if cell.state == 0: cell.state = 1
主循环(Go函数)
def go(grid): to_ignite = [] # 第一步:收集所有待点燃的邻居 for cell in grid.values(): if cell.state == 1: # 遍历燃烧细胞的所有邻居 for neighbor in get_neighbors(cell, grid): if neighbor.state == 0: to_ignite.append(neighbor) # 燃烧细胞转为灰烬 cell.state = 2 # 第二步:统一点燃待燃烧细胞 for cell in to_ignite: ignite(cell)
初始点火逻辑
def init_fire(grid): # 筛选所有未燃烧的森林细胞 forest_cells = [cell for cell in grid.values() if cell.state == 0] if not forest_cells: return # 随机选一个点火 import random target_cell = random.choice(forest_cells) ignite(target_cell)
额外调试技巧
- 加日志输出:在
ignite函数中添加print(f"Ignited cell ({cell.q}, {cell.r}) | 状态从 {cell.state-1} 转为 1"),确认函数是否被调用、状态是否正确修改; - 可视化网格状态:每执行一次
go函数后,打印网格中所有细胞的状态,直观查看火灾传播情况; - 检查主循环调用:确保模拟过程中每一步都执行了
go函数,而非仅执行一次。
内容的提问来源于stack exchange,提问作者yuta sugiyama
相关产品推荐
相关产品推荐

