晚上好。我有一个以矩阵形式表示的迷宫。有一个起点和一个终点。我写了一个函数,它将所有可以访问的单元格添加到数组中。该函数还会删除所有没有后代的单元格(死锁)。但该功能不会删除导致死胡同的单元格。请帮助完成这项功能。
//maze
matrix = [
[0, 1, 0, 1, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 1, 0],
[0, 0, 0, 0, 0],
[0, 1, 0, 1, 0]
];
var start = [4, 0];
var end = [3, 4];
function findWay(position, end) {
var queue = [];
//an array that contains the cells that have already visited
var visited = [];
//An array that contains cells that can not be entered for this position
var invalidCells = [];
//mark the current cell with a unit so as not to visit it anymore.
matrix[position[0]][position[1]] = 1;
//add the current position to the queue
queue.push(position);
//until the queue is empty
while (queue.length > 0) {
//get the first element of the queue
var pos = queue.shift();
//we clear the array, because for each new position we will have our own array
invalidCells.length = 0;
//an array of motion directions
var direction = [
[pos[0] + 1, pos[1]],
[pos[0], pos[1] + 1],
[pos[0] - 1, pos[1]],
[pos[0], pos[1] - 1]
];
for (var i = 0; i < direction.length; i++) {
//do a check for each direction
//if at least one cell does at least one of the conditions, the cell is
placed in an array of invalid cells
//then run a new iteration of the loop
if (direction[i][0] < 0 || direction[i][0] >= matrix[0].length || direction[i][1] < 0 || direction[i][1] >= matrix[0].length || matrix[direction[i][0]][direction[i][1]] != 0) {
invalidCells.push(direction[i]);
continue;
}
//If this direction turned out to be an end cell
//return the array of visited cells
if (direction[i][0] == end[0] && direction[i][1] == end[1]) return visited;
//if none of the conditions are met, mark this direction with one and add it to the end of the queue
matrix[direction[i][0]][direction[i][1]] = 1;
queue.push(direction[i]);
}
//add the current position to the array of visited cells
visited.push(pos);
//If no iteration of the loop returns anything, then this cell is a dead end
if (invalidCells.length == 4) {
//remove the deadlock from the array
visited.pop();
}
}
}
findWay(start, end);
答案 0 :(得分:1)
似乎没有必要跟踪visited
和invalidCells
:
visited
包含所有访问过的单元格(在所有方向上)。虽然你到达死胡同后试图从中移除细胞,但是没有简单的方法可以回溯并从中移除其他细胞,导致这个死胡同,并且它们不会参与其他可能仍然存在的路径成功。
invalidCells
仅用于检测死角,但由于前一点,我会放弃使用它。
我假设您的目标是到达一个visited
数组,该数组代表结束单元格的最短路径,并从中删除所有可能的变体绕道。使用BFS实现这一目标的方法是使用您的队列不仅可以存储位置,还可以使用导致这些位置的最短路径。然后,当您点击结束单元格时,您可以返回该单个路径,忽略可能仍在队列中的所有其他路径。
请注意,您的示例存在问题:结束单元格标记为1,并且您的代码不会检测到此类单元格作为结束单元格,但会绕过它,并且永远不会找到它。要么确保结束单元始终标记为0,要么在进行任何其他检查之前执行结束单元测试。
以下是对您的代码所做的更改 - 请参阅注释的位置。
var matrix = [
[0, 1, 0, 1, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 1, 0],
[0, 0, 0, 0, 0],
[0, 1, 0, 1, 0]
];
var start = [4, 0];
var end = [3, 4];
function findWay(position, end) {
var queue = [];
matrix[position[0]][position[1]] = 1;
queue.push([position]); // store a path, not just a position
while (queue.length > 0) {
var path = queue.shift(); // get the path out of the queue
var pos = path[path.length-1]; // ... and then the last position from it
var direction = [
[pos[0] + 1, pos[1]],
[pos[0], pos[1] + 1],
[pos[0] - 1, pos[1]],
[pos[0], pos[1] - 1]
];
for (var i = 0; i < direction.length; i++) {
// Perform this check first:
if (direction[i][0] == end[0] && direction[i][1] == end[1]) {
// return the path that led to the find
return path.concat([end]);
}
if (direction[i][0] < 0 || direction[i][0] >= matrix[0].length
|| direction[i][1] < 0 || direction[i][1] >= matrix[0].length
|| matrix[direction[i][0]][direction[i][1]] != 0) {
continue;
}
matrix[direction[i][0]][direction[i][1]] = 1;
// extend and push the path on the queue
queue.push(path.concat([direction[i]]));
}
}
}
var path = findWay(start, end);
console.log(JSON.stringify(path));