【问题标题】:A* in Javascript (with p5.js) not workingJavascript 中的 A*(使用 p5.js)不起作用
【发布时间】:2017-03-11 06:37:02
【问题描述】:

我正在为位于二维正方形数组中的玩家编写寻路算法。我想找到从 a 到 b 的最短路径并有效地做到这一点。我之前在 java (Processing) 中工作,我的函数工作得很好。

boolean findPath(PVector down, PVector up, Square[][] board) {
  PVector start = up;
  PVector goal = down;

  ArrayList<Square> closedSet = new ArrayList<Square>();
  ArrayList<Square> openSet = new ArrayList<Square>();

  HashMap<Square, Square> cameFrom = new HashMap<Square, Square>((int)Math.pow(squares, 2));
  HashMap<Square, Float> gScore = new HashMap<Square, Float>((int)Math.pow(squares, 2));
  HashMap<Square, Float> fScore = new HashMap<Square, Float>((int)Math.pow(squares, 2));

  for (int i = 0; i<dungeon.floors.get(currentFloor).numSquares; i++) {
    for (int j = 0; j<dungeon.floors.get(currentFloor).numSquares; j++) {
      gScore.put(board[i][j], 1000.0);
    }
  }

  gScore.put(board[(int)start.x][(int)start.y], 0.0);
  fScore.put(board[(int)start.x][(int)start.y], heuristic(start, goal));

  openSet.add(board[(int)start.x][(int)start.y]);

  while (!openSet.isEmpty()) {
    Square current = board[(int)start.x][(int)start.y];
    float lowest = 1000;
    for (Square s : openSet) {
      if (fScore.get(s)<lowest) {
        lowest = fScore.get(s);
        current = s;
      }
    }
    if (current.locX == goal.x && current.locY == goal.y) {
      while (cameFrom.containsKey(current)) {
        current = cameFrom.get(current);
      }
      board[(int)start.x][(int)start.y].squareType = -3;
      return true;
    }
    openSet.remove(current);
    closedSet.add(current);
    //neighbors() returns an ArrayList of valid neighbors
    for (Square s : current.neighbors(board)) {
      if (closedSet.contains(s)) {
      } else {

        float tempG = gScore.get(current) + 1;
        if (!openSet.contains(s)) {
          openSet.add(s);
        } 
        if (tempG < gScore.get(s)) {

          cameFrom.put(s, current);
          gScore.put(s, tempG);
          fScore.put(s, gScore.get(s) + heuristic(new PVector(s.locX, s.locY), goal));
        }
      }
    }
  }

  return false;
}

float heuristic(PVector start, PVector goal) {
  return dist(start.x, start.y, goal.x, goal.y);
}

但我正在将游戏转移到 Javascript,但我不知道我的代码哪里出错了。它被卡在一个正方形上并将其永久添加到 closedSet 中(数十万次)。这是我的 Javascript 代码 -

this.findPath = function(f, _start, _goal) {
      var start = _start;
      var goal = _goal;

      var closedSet = [];
      var openSet = [];

      var squareScores = [];
      var startSquare = (start.x * numSquares) + start.y;

      for (var i = 0; i < numSquares; i++) {
         for (var j = 0; j < numSquares; j++) {
            squareScores.push(new MapSquare(dungeon.floors[f].board[i][j], 10000, 10000));
         }
      }

      squareScores[startSquare].gScore = 0;
      squareScores[startSquare].fScore = this.heuristic(start, goal);
      openSet.push(squareScores[startSquare]);

      while (openSet.length > 0) {
         var current = squareScores[startSquare];
         var lowest = 9999;
         for (var s = 0; s < squareScores.length; s++) {
            if (squareScores[s].fScore < lowest) {
               lowest = squareScores[s].fScore;
               current = squareScores[s];
            }
         }
         if (current.square.x == goal.x && current.square.y == goal.y) {
             return true;
         }

         openSet.splice(openSet.indexOf(current.square));  
         closedSet.push(current.square);

         var currentNeighbors = current.square.neighbors(dungeon.floors[f].board);
         for (var i = 0; i < currentNeighbors.length; i++) {
            var skip = false;
            for (let c of closedSet) {
               if (c.x == currentNeighbors[i].x && c.y == currentNeighbors[i].y) {
                  skip = true;
               }
            }
            if (skip) {
               continue;
            }
            else {
               var tempG = current.gScore + 1;

               var dontAdd = false;
               for (let o of openSet) {
                  if (o.x == currentNeighbors[i].x && o.y == currentNeighbors[i].y) {
                     dontAdd = true;
                  }
               }
               if (!dontAdd) {
                  openSet.push(currentNeighbors[i]);
               }
               var index = (currentNeighbors[i].x * numSquares) + currentNeighbors[i].y;
               if (tempG < squareScores[index].gScore) {
                  //cameFrom.push(gScore[i]);
                  console.log("update");

                  squareScores[index].gScore = tempG;
                  squareScores[index].fScore = squareScores[index].gScore + this.heuristic(squareScores[index].square.x, squareScores[index].square.y, goal.x, goal.y);
               }
            }
         }
      }
      return false;
   };

   //dist from player to goal
   this.heuristic = function(_x1, _y1, _x2, _y2) {
      return dist(_x1, _y1, _x2, _y2);
   };

我的 Javascript 代码看起来有点不同,因为我已经尝试修复了几天,但我无法弄清楚。我究竟做错了什么?如果代码需要澄清,请询问。

【问题讨论】:

    标签: javascript processing a-star p5.js


    【解决方案1】:

    您将不得不debug 您的代码。该链接是关于在 Processing 中调试的,但同样的想法也适用于 JavaScript 和 P5.js。

    具体来说,您需要准确地弄清楚代码的执行何时与您预期的不同。

    您可以通过添加console.log()语句来计算变量的值,以什么顺序调用哪些函数,是否输入if语句,循环迭代的次数等。

    如果这不起作用,您还可以使用调试器单步执行您的代码。每个浏览器都带有一个 JavaScript 调试器,它允许您单步执行代码并检查每个变量的值。同样,我们的目标是准确确定代码何时执行与您预期不同的操作。

    当你把它缩小到几行时,如果你仍然不知道如何解决它,那么你可以创建一个MCVE 来隔离问题,而不需要围绕它的所有额外代码。到那时,帮助你会容易得多。祝你好运。

    【讨论】:

    • 您好,感谢您的回复。相信我,我已经连续调试了好几个小时(使用 google chrome 开发控制台)。我一直在控制台。记录列表的大小,逐行浏览代码,观察变量,我似乎唯一能发现的是启发式方法没有返回正确的值或其他东西。在我最初的问题中,启发式被除以 2,但最初它只是一个距离函数,我不明白这怎么可能是错误的,除非存在非常显着的舍入错误。无论如何感谢您的建议!
    • 当您说启发式方法没有返回正确的值时,您到底是什么意思?你能整理一个minimal reproducible example,它只显示使用硬编码值的启发式函数,它到底有什么不正确的地方?
    • 在我的代码底部,函数 this.heuristic 只是返回两点之间的距离。但有时它不会返回正确的距离。
    • @CadenPopps 你能比说它有时不返回正确的距离更具体吗?它返回的是什么?这些情况下的参数是什么?创建一个minimal reproducible example,它只显示距离函数根据硬编码值返回错误的东西,我们可以从那里开始。
    猜你喜欢
    • 2018-09-13
    • 1970-01-01
    • 2020-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多