Реализация рекурсивного Backtracker в JavaScript? - PullRequest
2 голосов
/ 27 февраля 2020

У меня есть двумерный массив, заполненный объектами. Я хочу преобразовать этот массив в лабиринт, где некоторые объекты являются стенами (у них есть свойство isWall, которое должно быть помечено как истинное), а некоторые объекты являются проходами (isWall будет ложным).

Я пытаюсь использовать для этого Рекурсивный откат (я использую стек вместо рекурсии), но мой Лабиринт появляется вот так Picture of incorrect Maze

Черные квадраты представляют стены, тогда как белые квадраты представляют проходы. Числа внутри белых квадратов не имеют значения (только веса, которые я использую для Джикстра).

Вот моя реализация Recursive Backtracking в 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;
}

Я был бы очень признателен за некоторые рекомендации о том, где мой код работает неправильно. Спасибо!

1 Ответ

1 голос
/ 27 февраля 2020

Я думаю, что ошибка, вероятно, из-за вашей строки

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]

Теперь есть еще одна логика c ошибка здесь при условии 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 проверяет, доступна ли ячейка, а затем немедленно выполняет действие, если ячейка была доступна.

Я попытался выполнить код, и он просто стал полосой вертикальных линий. Поэтому попробуйте сохранить доступные координаты в списке и выбрать случайную координату из этого нового списка. Это, казалось, исправило ошибку:)

...