在 JavaScript 中实现递归回溯器?
Implementing a Recursive Backtracker in JavaScript?
我有一个充满对象的二维数组。我想将这个数组转换成一个迷宫,其中一些对象是墙(它们有一个 isWall
属性 应该标记为 true),一些对象是通道(isWall
将是 false)。
我正在尝试为此使用 Recursive Backtracking(我使用的是堆栈而不是递归),但我的迷宫显示如下
黑色方块代表墙壁,而白色方块代表通道。白色方块内的数字无关紧要(只是我用于 Djikstra 的权重)。
这是我在 JavaScript 中实现的递归回溯。
JavaScript
function isValid(r, c, grid) {
if (r < 0 || c < 0) {
return false;
}
if (r < grid.length && c < grid[r].length) {
return true;
}
return false;
}
export default function recursiveBacktracker(grid, startNode, endNode) {
// Fill Grid with walls
for (let r = 0; r < grid.length; r++) {
for (let c = 0; c < grid[r].length; c++) {
grid[r][c].isWall = true;
}
}
let visited = new Set();
let stack = [startNode];
let neighbors = [
[2, 0],
[-2, 0],
[0, 2],
[0, -2]
];
while (stack.length > 0) {
let cur = stack.pop();
let r = cur[0],
c = cur[1];
console.log(r, c);
visited.add(r + "." + c);
grid[r][c].isWall = false;
for (let n of neighbors) {
let rr = r + n[0];
let cc = c + n[1];
if (isValid(rr, cc, grid) && !visited.has(rr + "." + cc)) {
grid[r + n[0] / 2][c + n[0] / 2].isWall = false;
stack.push([rr, cc]);
break;
}
}
}
return grid;
}
如果我能就我的代码哪里出了问题提供指导,我将不胜感激。谢谢!
我认为这个错误很可能是因为你的行
grid[r + n[0] / 2][c + n[0] / 2].isWall = false;
我觉得打错了,你想要的是
grid[r + n[0] / 2][c + n[1] / 2].isWall = false; //simply change n[0] to n[1]
现在 if 条件这里又出现了一个逻辑错误:
for (let n of neighbors) {
let rr = r + n[0];
let cc = c + n[1];
if (isValid(rr, cc, grid) && !visited.has(rr + "." + cc)) {
grid[r + n[0] / 2][c + n[0] / 2].isWall = false;
stack.push([rr, cc]);
break;
}
}
递归回溯算法需要选择一个随机的可用邻居,而您所做的只是选择您找到的第一个可用邻居。
如您所见,if 条件检查单元格是否可用,如果单元格可用则立即执行操作。
我尝试了 运行 代码,它只是变成了一条垂直线。
因此,请尝试将可用坐标存储在列表中,然后从该新列表中随机选择一个坐标。这似乎修复了错误 :)
我有一个充满对象的二维数组。我想将这个数组转换成一个迷宫,其中一些对象是墙(它们有一个 isWall
属性 应该标记为 true),一些对象是通道(isWall
将是 false)。
我正在尝试为此使用 Recursive Backtracking(我使用的是堆栈而不是递归),但我的迷宫显示如下
黑色方块代表墙壁,而白色方块代表通道。白色方块内的数字无关紧要(只是我用于 Djikstra 的权重)。
这是我在 JavaScript 中实现的递归回溯。
JavaScript
function isValid(r, c, grid) {
if (r < 0 || c < 0) {
return false;
}
if (r < grid.length && c < grid[r].length) {
return true;
}
return false;
}
export default function recursiveBacktracker(grid, startNode, endNode) {
// Fill Grid with walls
for (let r = 0; r < grid.length; r++) {
for (let c = 0; c < grid[r].length; c++) {
grid[r][c].isWall = true;
}
}
let visited = new Set();
let stack = [startNode];
let neighbors = [
[2, 0],
[-2, 0],
[0, 2],
[0, -2]
];
while (stack.length > 0) {
let cur = stack.pop();
let r = cur[0],
c = cur[1];
console.log(r, c);
visited.add(r + "." + c);
grid[r][c].isWall = false;
for (let n of neighbors) {
let rr = r + n[0];
let cc = c + n[1];
if (isValid(rr, cc, grid) && !visited.has(rr + "." + cc)) {
grid[r + n[0] / 2][c + n[0] / 2].isWall = false;
stack.push([rr, cc]);
break;
}
}
}
return grid;
}
如果我能就我的代码哪里出了问题提供指导,我将不胜感激。谢谢!
我认为这个错误很可能是因为你的行
grid[r + n[0] / 2][c + n[0] / 2].isWall = false;
我觉得打错了,你想要的是
grid[r + n[0] / 2][c + n[1] / 2].isWall = false; //simply change n[0] to n[1]
现在 if 条件这里又出现了一个逻辑错误:
for (let n of neighbors) {
let rr = r + n[0];
let cc = c + n[1];
if (isValid(rr, cc, grid) && !visited.has(rr + "." + cc)) {
grid[r + n[0] / 2][c + n[0] / 2].isWall = false;
stack.push([rr, cc]);
break;
}
}
递归回溯算法需要选择一个随机的可用邻居,而您所做的只是选择您找到的第一个可用邻居。 如您所见,if 条件检查单元格是否可用,如果单元格可用则立即执行操作。
我尝试了 运行 代码,它只是变成了一条垂直线。 因此,请尝试将可用坐标存储在列表中,然后从该新列表中随机选择一个坐标。这似乎修复了错误 :)