在Kotlin中实现扫雷洪水填充算法的代码完善求助
扫雷洪水填充算法优化方案
问题背景
我正在复刻扫雷游戏,需要完善洪水填充逻辑的explore函数。游戏规则如下:
- 初始雷区为9x9的空白单元格(用
.表示):
│123456789│ —│—————————│ 1│.........│ 2│.........│ 3│.........│ 4│.........│ 5│.........│ 6│.........│ 7│.........│ 8│.........│ 9│.........│ —│—————————│
- 玩家探索单元格时的三种情况:
- 踩到地雷则游戏失败(此部分已实现)
- 单元格为空但周围有地雷,仅显示该单元格的地雷数量
- 单元格为空且周围无地雷,标记为
/并自动递归探索所有相邻单元格,直到遇到有地雷的单元格为止
已实现checkIfMinesAround函数检测单元格周围地雷数量,现有explore代码存在问题,需要修正。
原代码问题
import java.util.Queue import java.util.LinkedList fun explore(row: Int, column: Int) { val length1 = minefield.size val length2 = minefield[0].size if (displayedMinefield[row][column] == "/") return val queue: Queue<Int> = LinkedList<Int>() queue.add(listOf(row, column)) while (!queue.isEmpty()) { val (i, j) = queue.first queue.removeFirst() if (i < 0 || i >= length1 || j < 0 || j >= length2) { continue } else { if (checkIfMinesAround(i, j)) { displayedMinefield[i][j] = minefield[i][j] } else { displayedMinefield[i][j] = "/" } queue.add(listOf(i + 1, j)) queue.add(listOf(i - 1, j)) queue.add(listOf(i, j + 1)) queue.add(listOf(i, j - 1)) } } }
原代码存在的问题:
- 队列类型声明错误:
Queue<Int>无法存储行列坐标对,应该用Queue<List<Int>> - 无重复处理判断:同一单元格会被多次入队,导致无效循环
- 逻辑不符合规则:有地雷的单元格仍会继续探索相邻单元格,违反规则B
- 坐标检查时机晚:已经入队的无效坐标才会被过滤,浪费资源
修正后的代码
import java.util.Queue import java.util.LinkedList fun explore(row: Int, column: Int) { val totalRows = minefield.size if (totalRows == 0) return val totalCols = minefield[0].size // 检查是否踩雷(假设地雷在minefield中用"*"标记) if (minefield[row][column] == "*") { // 调用已实现的游戏失败逻辑 return } // 已显示的单元格直接返回 if (displayedMinefield[row][column] != ".") { return } val queue: Queue<List<Int>> = LinkedList() queue.add(listOf(row, column)) // 先标记为已处理,避免重复入队 displayedMinefield[row][column] = "/" while (queue.isNotEmpty()) { val (currentRow, currentCol) = queue.poll() val hasSurroundingMines = checkIfMinesAround(currentRow, currentCol) if (hasSurroundingMines) { // 显示周围地雷数量 displayedMinefield[currentRow][currentCol] = minefield[currentRow][currentCol] continue // 有地雷的单元格,不再探索相邻 } // 定义四个相邻方向(如需八方向可添加斜向坐标) val adjacentDirections = listOf( listOf(1, 0), listOf(-1, 0), listOf(0, 1), listOf(0, -1) ) for ((rowOffset, colOffset) in adjacentDirections) { val newRow = currentRow + rowOffset val newCol = currentCol + colOffset // 检查坐标合法且未被处理 if (newRow in 0 until totalRows && newCol in 0 until totalCols && displayedMinefield[newRow][newCol] == ".") { displayedMinefield[newRow][newCol] = "/" queue.add(listOf(newRow, newCol)) } } } }
修改说明
- 修正队列类型:将队列改为存储
List<Int>类型的坐标对,解决类型不匹配问题 - 提前过滤无效操作:函数开头检查踩雷、已显示的单元格,直接返回避免无效执行
- 避免重复入队:入队前先标记单元格为已处理,防止同一单元格被多次加入队列
- 符合游戏规则:周围有地雷的单元格,仅显示数量并终止后续探索,符合规则B
- 优化坐标检查:入队前先验证坐标合法性,减少无效循环
- 代码更简洁:用方向列表统一管理相邻单元格,便于后续扩展(比如八方向探索)
内容的提问来源于stack exchange,提问作者anirudh30three
相关产品推荐
相关产品推荐

