Godot4.2实战用自定义Array2D类5分钟搞定扫雷游戏核心逻辑扫雷游戏作为经典益智游戏的代表其核心逻辑看似简单却蕴含着精妙的二维数组操作技巧。本文将带你用Godot4.2中的自定义Array2D类快速实现扫雷的核心机制感受这个强大工具如何让复杂逻辑变得优雅简洁。1. 游戏初始化与雷区生成扫雷游戏的第一步是创建游戏地图并随机布置地雷。使用Array2D的静态方法fill_rect_random可以轻松实现这一需求# 创建10x10的游戏地图0表示安全1表示地雷 var mine_map Array2D.fill_rect_random(10, 10, 0, 1)但这样生成的雷区地雷分布可能过于密集。我们可以通过调整随机数范围和二次处理来控制地雷数量# 更精确控制地雷数量约15%概率 func generate_mine_map(rows, cols): var map Array2D.fill_rect(rows, cols, 0) for x in range(rows): for y in range(cols): if randf() 0.15: # 15%概率生成地雷 map.set_cell(x, y, 1) return map提示实际项目中建议将地雷概率设为可配置参数方便调整游戏难度2. 计算周围地雷数量扫雷游戏的核心玩法是通过数字提示判断周围地雷分布。利用Array2D的四向查询方法可以优雅实现这一功能func count_adjacent_mines(map: Array2D, x: int, y: int) - int: var directions [ map.get_up(x, y), map.get_down(x, y), map.get_left(x, y), map.get_right(x, y), map.get_up(x, y-1), map.get_up(x, y1), map.get_down(x, y-1), map.get_down(x, y1) ] return directions.reduce(func(acc, val): return acc (val if val 1 else 0), 0)更高效的实现方式是预先定义所有8个相邻位置的偏移量var NEIGHBOR_OFFSETS [ Vector2(-1,-1), Vector2(-1,0), Vector2(-1,1), Vector2(0,-1), Vector2(0,1), Vector2(1,-1), Vector2(1,0), Vector2(1,1) ] func count_mines_optimized(map: Array2D, pos: Vector2) - int: var count 0 for offset in NEIGHBOR_OFFSETS: if map.get_cellv(pos offset) 1: count 1 return count3. 游戏状态管理与点击逻辑扫雷游戏需要管理三种格子状态未打开、已打开和标记状态。我们可以用两个Array2D分别存储地雷分布和玩家操作状态var mine_map: Array2D # 1地雷, 0安全 var state_map: Array2D # 0未打开, 1已打开, 2标记 func handle_click(pos: Vector2, is_marking: bool): if is_marking: # 标记/取消标记逻辑 var current state_map.get_cellv(pos) state_map.set_cellv(pos, 2 if current ! 2 else 0) else: # 打开格子逻辑 if mine_map.get_cellv(pos) 1: game_over() else: reveal_cells(pos) func reveal_cells(pos: Vector2): # 递归实现空白区域展开 if state_map.get_cellv(pos) ! 0: return var mine_count count_mines_optimized(mine_map, pos) state_map.set_cellv(pos, 1) if mine_count 0: for offset in NEIGHBOR_OFFSETS: var new_pos pos offset if state_map.is_valid_position(new_pos): reveal_cells(new_pos)注意实际实现时需要添加边界检查Array2D的get_cell方法已经处理了越界情况4. 游戏界面与Array2D的联动将Array2D数据可视化到游戏场景中我们可以创建一个TileMap节点并动态更新onready var tile_map: TileMap $TileMap func update_display(): for x in range(state_map.data.size()): for y in range(state_map.data[0].size()): var pos Vector2(x, y) var state state_map.get_cellv(pos) var mine mine_map.get_cellv(pos) if state 0: # 未打开 tile_map.set_cell(0, pos, 0, Vector2(0, 0)) elif state 2: # 标记 tile_map.set_cell(0, pos, 0, Vector2(3, 0)) else: # 已打开 if mine 1: # 地雷 tile_map.set_cell(0, pos, 0, Vector2(2, 0)) else: var count count_mines_optimized(mine_map, pos) tile_map.set_cell(0, pos, 0, Vector2(1, count))配合适当的TileSet资源这个简单的逻辑就能实现完整的扫雷游戏视觉效果。Array2D的数据操作与TileMap的显示更新完美解耦使代码更易维护。5. 性能优化与高级功能当游戏地图较大时可以考虑以下优化策略增量更新只重绘发生变化的格子var dirty_cells [] func mark_dirty(pos: Vector2): if not dirty_cells.has(pos): dirty_cells.append(pos) func process_dirty_cells(): for pos in dirty_cells: update_cell(pos) dirty_cells.clear()预计算数字游戏初始化时计算所有格子的数字提示var hint_map: Array2D func precompute_hints(): hint_map Array2D.fill_rect(mine_map.data.size(), mine_map.data[0].size(), 0) for x in range(mine_map.data.size()): for y in range(mine_map.data[0].size()): if mine_map.get_cell(x, y) 0: hint_map.set_cell(x, y, count_mines_optimized(mine_map, Vector2(x, y)))首次点击保护确保玩家第一次点击不会是地雷func safe_first_click(click_pos: Vector2): while mine_map.get_cellv(click_pos) 1: # 重新生成雷区但保持点击位置安全 mine_map generate_mine_map(10, 10) reveal_cells(click_pos)通过这些优化即使是大型扫雷地图也能流畅运行。Array2D的方法链式调用让这些高级功能的实现变得异常简洁。