【问题标题】:Pathfinding javascript algorithm not working as it's supposed to寻路 javascript 算法无法正常工作
【发布时间】:2016-07-21 21:56:52
【问题描述】:

我正在编写寻路算法,但是我被困在一件事上。算法获取起始单元格并将其添加到队列中,将其标记为已访问并在屏幕上的单元格中打印数字(数字显示当前单元格与起始单元格的距离)。然后对于队列的第一个元素,它检查其邻居。如果邻居不是墙或尚未访问,则将其添加到队列中。然后从队列中删除第一个元素并重复整个函数,直到队列长度等于0。

我不能让一件事起作用,当用单元格填充队列并给单元格它们的距离编号时,结果应该是这样的:

S12
1#2
22E

其中#是一堵墙,S是起点,E是目标点。然而,当算法运行时,它会产生以下结果:

S12
2#3
33E

似乎某些单元格的距离数增加了不止一次,这不应该发生。在代码中,我添加了额外的布尔标志,无论单元格距离数是否已经增加,以及仅在到目前为止尚未增加距离数时才增加距离数的附加条件。帮助指出我犯错的地方将不胜感激。寻路功能:

function findPath(startCell, goalCell) {
  var queue = [];

  queue.push({
    cell: startCell,
    hasBeenIncremented: true,
    hasBeenSearched: false,
    searchDistance: undefined
  });
  queue[0].searchDistance = 0;

  fillPath();

  function fillPath() {
    queue[0].cell.hasBeenSearched = true;
    pointColor(queue[0].cell.x, queue[0].cell.y, 'darkred');
    setInnerHTML(queue[0].cell.x, queue[0].cell.y, queue[0].searchDistance);

    for (var i = -1; i <= 1; i++) {
      if (queue[0].cell.x + i < 0 || queue[0].cell.x + i > boardHeight - 1) {
        continue;
      }
      for (var j = -1; j <= 1; j++) {
        if (queue[0].cell.y + j < 0 || queue[0].cell.y + j > boardWidth - 1) {
          continue;
        }
        if (i == 0 && j == 0) {
          continue;
        }
        if (getCell(queue[0].cell.x + i, queue[0].cell.y + j).hasWall == true || getCell(queue[0].cell.x + i, queue[0].cell.y + j).hasBeenSearched == true) {
          continue;
        }
        if (queue[0].cell.x == goalCell.x && queue[0].cell.y == goalCell.y) {
          pointColor(goalCell.x, goalCell.y, 'darkred');
          setInnerHTML(goalCell.x, goalCell.y, '*');
          return 'path completed';
        }

        queue.push({
          cell: getCell(queue[0].cell.x + i, queue[0].cell.y + j),
          hasBeenSearched: false,
          searchDistance: undefined,
          hasBeenIncremented: false
        });
        if(queue[queue.length - 1].hasBeenIncremented != true) {
          queue[queue.length - 1].searchDistance = queue[0].searchDistance + 1;
          queue[queue.length - 1].hasBeenIncremented = true;
        }

      }
    }
    queue.shift();
    if (queue.length > 0) {
      setTimeout(fillPath, 1000);
    }
  }

}

JS 小提琴链接:https://jsfiddle.net/s8texvxa/2/(这不是一个完整的算法 - 只是它的第一部分)。

【问题讨论】:

    标签: javascript algorithm path-finding


    【解决方案1】:

    您在排队之前执行了检查,但它可能通过其他路径在队列中但尚未检查,因此仍被视为未访问。

    请注意,如果可以通过多条路径到达一个单元格,则必须确保使用最短距离。

    看起来您正在使用广度优先算法,因此在排队时将单元格标记为已访问就足够了,这样就不会再次添加它。

    【讨论】:

    • 我不确定我是否完全理解 - 已经有距离的单元格不能再次添加到队列中,因为它们将“haveBeenSearched”标志设置为 true,并且在“for”中省略了它们循环片段if (getCell(queue[0].cell.x + i, queue[0].cell.y + j).hasWall == true || getCell(queue[0].cell.x + i, queue[0].cell.y + j).hasBeenSearched == true) { continue; }
    • 您在排队前进行了检查,但它可能通过其他路径在队列中但尚未检查,因此仍被视为未访问。请注意,如果可以通过多条路径到达一个单元格,则必须确保使用最短距离。
    • 看起来您正在使用广度优先算法,因此在排队时将单元格标记为已访问可能就足够了。
    • 对,这就是问题所在!一些单元被多次添加到队列中。您能否编辑您的答案,以便我接受。
    • 修改了我的答案。
    猜你喜欢
    • 2014-11-06
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多