Javascript 从迷宫中找到最短路径(广度优先搜索)

Javascript 从迷宫中找到最短路径(广度优先搜索),javascript,algorithm,Javascript,Algorithm,晚上好。我有一个迷宫,以矩阵的形式表示。有一个起点和一个终点。我编写了一个函数,将可以访问的所有单元格添加到数组中。该函数还删除所有没有子体的单元格(死锁)。但该功能不会删除导致死胡同的单元格。请帮忙完成这个功能 //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

晚上好。我有一个迷宫,以矩阵的形式表示。有一个起点和一个终点。我编写了一个函数,将可以访问的所有单元格添加到数组中。该函数还删除所有没有子体的单元格(死锁)。但该功能不会删除导致死胡同的单元格。请帮忙完成这个功能

//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, 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];
功能findWay(位置,结束){
变量队列=[];
//包含已访问的单元格的数组
var=[];
//包含无法为此位置输入的单元格的数组
var invalidCells=[];
//用单元标记当前单元格,以便不再访问它。
矩阵[位置[0]][位置[1]]=1;
//将当前位置添加到队列中
排队推(位置);
//直到队列为空
while(queue.length>0){
//获取队列的第一个元素
var pos=queue.shift();
//我们清除阵列,因为对于每个新位置,我们都有自己的阵列
invalidCells.length=0;
//一系列运动方向
变量方向=[
[pos[0]+1,pos[1]],
[pos[0],pos[1]+1],
[pos[0]-1,pos[1]],
[位置[0],位置[1]-1]
];                      
对于(变量i=0;i=矩阵[0]。长度| |方向[i][1]<0 | | |方向[i][1]>=矩阵[0]。长度| |矩阵[i][0]][方向[i][1]!=0){
无效单元格。推(方向[i]);
继续;
}
//如果这个方向是一个终端单元
//返回已访问单元格的数组
如果(方向[i][0]==end[0]&方向[i][1]==end[1])返回访问;
//如果不满足任何条件,则用一个标记此方向,并将其添加到队列末尾
矩阵[方向[i][0]][方向[i][1]]=1;
排队推送(方向[i]);
}
//将当前位置添加到已访问单元格的数组中
访问推送(pos);
//如果循环的迭代没有返回任何结果,那么这个单元格就是一条死胡同
if(invalidCells.length==4){
//从阵列中移除死锁
pop();
}
}
}
findWay(开始、结束);

似乎没有必要跟踪访问的
无效单元格

  • 已访问
    包含所有已访问的单元格(在所有方向)。尽管您试图在到达死胡同后从中移除细胞,但没有简单的方法可以回溯并从中移除其他细胞,这些细胞会导致此死胡同,并且不涉及其他可能仍然成功的路径

  • invalidCells
    仅用于检测死角,但由于前面的一点,我将不再使用它

我假设您的目标是获得一个
已访问的
数组,该数组表示到最终单元的最短路径,并从中删除所有可能的变量迂回。使用BFS实现这一点的方法是,不仅使用队列存储位置,还使用通向这些位置的最短路径。然后,当您点击结束单元格时,可以返回该单一路径,忽略队列中可能仍然存在的所有其他路径

请注意,您的示例中存在一个问题:结束单元标记为1,您的代码将不会检测到这样一个单元作为结束单元,而是在它周围走动,并且永远找不到它。请确保末端单元格始终标记为0,或者在执行任何其他检查之前执行末端单元格测试

下面是对代码所做的更改--请参见注释的位置

var矩阵=[
[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];
功能findWay(位置,结束){
变量队列=[];
矩阵[位置[0]][位置[1]]=1;
queue.push([position]);//存储路径,而不仅仅是位置
while(queue.length>0){
var path=queue.shift();//从队列中获取路径
var pos=path[path.length-1];/…然后是它的最后一个位置
变量方向=[
[pos[0]+1,pos[1]],
[pos[0],pos[1]+1],
[pos[0]-1,pos[1]],
[位置[0],位置[1]-1]
];
对于(变量i=0;i=矩阵[0]。长度
||方向[i][1]<0 | |方向[i][1]>=矩阵[0]。长度
||矩阵[direction[i][0]][direction[i][1]!=0{
继续;
}
矩阵[方向[i][0]][方向[i][1]]=1;
//扩展并推送队列上的路径
queue.push(path.concat([direction[i]]);
}
}
}
变量路径=findWay(开始、结束);

log(JSON.stringify(path))我建议您对您的代码进行注释和记录,以帮助您了解到目前为止您所做的工作。如果目的是仅在
中访问到终点的路径,那么使用DFS将更有用。有了BFS,就不会有回溯,所以你将无法删除最终导致死胡同的单元格。注意:在您的示例中,结束单元格标记为1,因此您永远找不到它。