为什么我的迷宫生成器不检测是否在 p5.js 中访问了单元格?

Why is my maze generator not detecting if a cell has been visited in p5.js?

我正在尝试制作一个迷宫生成器,到目前为止几乎一切正常。我已经能够将我的位置设置为随机 pos,然后我重复 standard() 函数。在函数中,我将 pos 添加到 posList,然后我选择一个随机方向。接下来,我检查单元格是否已被 运行 通过所有 posList 向量反向访问过。我还没有执行回溯的代码。如果 visited = false 然后我移动到广场并执行尚未制作的 path() 功能。但是,出于某种原因,移动器只是不检测是否已访问单元格。我正在使用 p5.js。我做错了什么?

var posList = [];
var pos;
var tempo;
var boole = false;
var direc;
var mka = 0;
function setup() {
  createCanvas(400, 400);
  //Set up position
  pos = createVector(floor(random(3)), floor(random(3)));
  frameRate(1)
}

//Choose a direction
function direct(dire) {
  if(dire === 0) {
    return(createVector(0, -1));
  } else if(dire === 1) {
    return(createVector(1, 0));
  } else if(dire === 2) {
    return(createVector(0, 1));
  } else {
    return(createVector(-1, 0));
  }
}

/foLo stands fo forLoop
function foLo() {
  //If we have checked less than three directions and know there is a possibility for moving
  if(mka < 4) {
    //tempoRARY, this is what we use to see if the cell has been visited
    tempo = createVector(pos.x + direct(direc).x, pos.y + direct(direc).y);
    //Go through posList backwards
    for(var i = posList.length - 1; i >= 0; i --) {
      //If the cell has been visited or the cell is off of the screen
      if(tempo ===  posList[i]) {
        //Change the direction
        direc ++;
        //Roll over direction value
        if(direc === 4) {
          direc = 0;
        }
        //Re-execute on next frame
        foLo();
        //The cell has been visited
        boole = false;
        //Debugging
        console.log(direc)
        mka++;
      } else if(tempo.x < 0 || tempo.x > 2 || tempo.y < 0 || tempo.y > 2) {
        direc ++;
        if(direc === 4) {
          direc = 0;
        }
        foLo();
        boole = false;
        console.log(direc)
        mka++;
      }
    }
    //If it wasn't visited (Happens every time for some reason)
    if(boole === true) {
      //position is now the temporary value
      pos = tempo;
      console.log("works")
      mka = 0;
    }
  }
}

function standard() {
  //Add pos to posList
  posList.push(pos);
  //Random direction
  direc = floor(random(4));
  //Convert to vector
  direct(direc);
  foLo();
  //Tracks pos
  fill(255, 255, 0);
  rect(pos.x*100+50, pos.y*100+50, 50, 50)
}

function draw() {
  background(255);
  fill(0);
  noStroke();
  //draw grid
  for(var i = 0; i < 4; i ++) {
    rect(i*100,0,50,350);
    rect(0, i*100, 350, 50);
  }
  standard();
  boole = true;
  console.log(pos)
  console.log(posList);
}

您的问题出在比较两个向量的那一行if(tempo === posList[i]) {:这永远不会成立。

您可以使用以下代码验证(例如 setup()):

const v1 = new p5.Vector(1, 0);
const v2 = new p5.Vector(1, 0);
const v3 = new p5.Vector(1, 1);

console.log(v1 === v2) // false
console.log(v1 === v3) // false

这是因为尽管具有相同的值 v1v2 引用了两个不同的对象。

您可以使用 p5.Vector.equals 函数。该文档有以下示例:

let v1 = createVector(10.0, 20.0, 30.0);
let v2 = createVector(10.0, 20.0, 30.0);
let v3 = createVector(0.0, 0.0, 0.0);
print(v1.equals(v2)); // true
print(v1.equals(v3)); // false

这可能不会给你一个有效的算法,因为我怀疑你有其他逻辑错误(但我可能是错的,或者你稍后会调试它们)但至少这部分代码会做你期望的。


另一个解决方案是使用 Set 而不是您的职位列表。此解决方案的缺点是您必须调整代码以处理“网格外”位置情况。但是,当您想跟踪访问过的项目时,Set 通常是一个很好的解决方案,因为访问时间是恒定的。这意味着要定义一个位置是否已经被访问过,它总是需要相同的时间(你会做类似 visitedSet.has(positionToCheck) 的事情,而在你的解决方案中,你遍历一个列表,你访问过的单元格越多检查单元格是否在列表中需要更长的时间。

Set 解决方案将要求您先转换向量,然后再将它们添加到正弦集合中,我在不能简单地比较向量之前解释过。所以你可以用这样的东西检查他们的字符串表示:

const visitedCells = new Set();
const vectorToString = (v) => `${v.x},{$v.y}` // function to get the vector representation

// ...
visitedCells.add(vectorToString(oneCell)); // Mark the cell as visited

visited = visitedCells.has(vectorToString(anotherCell))

还有一个一般性的建议你应该注意你的变量和函数的名字。例如

// foLo stands fo forLoop
function foLo() {

是一个很大的味道:你的函数名称应该是描述性的,当你看到你的函数调用 foLo(); 必须在函数声明旁边找到注释时,会使代码的可读性降低。您可以将其命名为 generateMaze(),这样您无需查看功能代码就知道它在做什么。

也一样
//tempoRARY, this is what we use to see if the cell has been visited
tempo = createVector(pos.x + direct(direc).x, pos.y + direct(direc).y);

例如,您可以简单地将 tempo 重命名为 cellToVisit

boole:命名一个布尔值boole并不能传达很多信息。

刚写代码的时候可能看起来是一些小细节,但是当你的代码有几百行或者休息几天再看的时候,你会感谢过去的你那。