停止有条件地传播递归函数

huangapple go评论55阅读模式
英文:

Stop propagation of recursive function conditionally

问题

代码:

const [stopVisiting, setStopVisiting] = useState(false);
const startVisiting = (visElement) => {
  if (visElement.i === endElement.i && visElement.j === endElement.j) {
    setStopVisiting(true);
  }
  if (visElement.wall === true) return;
  if (stopVisiting === true) {
    console.log("停止函数");
    return;
  } else {
    if (visElement["visited"] === false) {
      var newGrid = [...grid];
      newGrid[visElement.i][visElement.j]["visited"] = true;
      setGrid(newGrid);
      visElement["visited"] = true;
      setTimeout(() => {
        if (visElement["i"] > 0) {
          startVisiting(grid[visElement.i - 1][visElement.j]);
        }
        if (visElement["i"] < 39) {
          startVisiting(grid[visElement.i + 1][visElement.j]);
        }
        if (visElement["j"] > 0) {
          startVisiting(grid[visElement.i][visElement.j - 1]);
        }
        if (visElement["j"] < 59) {
          startVisiting(grid[visElement.i][visElement.j + 1]);
        }
        return;
      }, 500);
    }
  }
};

它实际上会记录语句 "停止函数",但它不起作用。

wall 元素是被阻挡的空间,我们无法通过它。

英文:

I am creating a pathfinding application, where I have created a grid of size 30*60, there is a starting element from where we have to start the path searching and a ending element where we have to stop the function once we reach the ending, in between I have marked all grids as visited. Also have created a variable named stopVisiting, so that once we reach the destination we will set stopVisiting to true to stop the function. But it is not working,

Code:

const [stopVisiting, setStopVisiting] = useState(false);
  const startVisiting = (visElement) =&gt; {
    if (visElement.i === endElement.i &amp;&amp; visElement.j === endElement.j) {
      setStopVisiting(true);
    }
    if (visElement.wall === true) return;
    if (stopVisiting === true) {
      console.log(&quot;Stop the function here&quot;);
      return;
    } else {
      if (visElement[&quot;visited&quot;] === false) {
        var newGrid = [...grid];
        newGrid[visElement.i][visElement.j][&quot;visited&quot;] = true;
        setGrid(newGrid);
        visElement[&quot;visited&quot;] = true;
        setTimeout(() =&gt; {
          if (visElement[&quot;i&quot;] &gt; 0) {
            startVisiting(grid[visElement.i - 1][visElement.j]);
          }
          if (visElement[&quot;i&quot;] &lt; 39) {
            startVisiting(grid[visElement.i + 1][visElement.j]);
          }
          if (visElement[&quot;j&quot;] &gt; 0) {
            startVisiting(grid[visElement.i][visElement.j - 1]);
          }
          if (visElement[&quot;j&quot;] &lt; 59) {
            startVisiting(grid[visElement.i][visElement.j + 1]);
          }
          return;
        }, 500);
      }
    }
  };

It is actually logging the statement Stop the function here, but it not working.

wall element is the blocked space, through which we cannot pass.

答案1

得分: 1

即使您调用了 setStopVisiting(true),您的 stopVisiting 没有被赋予新值,所以 stopVisiting === true 永远不会成立。

相反,不要使用 stopVisiting 状态... 这是不必要的。您可以通过确保将其标记为已访问,然后检查 endElement.visited 来知道是否已经到达了终点,这实际上就是您打算使用 stopVisiting 实现的功能的等效方式。

其他一些注意事项

  • 没有必要同时执行以下两个操作,因为它们实现了相同的功能:

    newGrid[visElement.i][visElement.j]["visited"] = true;
    visElement["visited"] = true;
    

    这两个赋值操作都会将值赋给同一个对象(请注意,newGridgrid 的浅拷贝,所以它的对象不是副本,但这没关系)。

  • [&quot;visited&quot;].visited 符号实现了相同的功能。我建议使用后者。

  • 您有多个条件可以停止访问元素:

    • 达到目标元素
    • 撞到墙
    • 遇到已经访问过的元素。

    这三种情况可以在同一个 if 语句中检查。

以下是更新后的代码:

  const startVisiting = (visElement) => {
    if (visElement.wall || visElement.visited || endElement.visited) return;

    visElement.visited = true; // 这将最终设置 `endElement.visited`
    setGrid([...grid]);
    setTimeout(() => {
      const { i, j } = visElement;  // 解构以使下面的代码更可读
      if (i > 0) startVisiting(grid[i - 1][j]);
      if (i < 39) startVisiting(grid[i + 1][j]);
      if (j > 0) startVisiting(grid[i][j - 1]);
      if (j < 59) startVisiting(grid[i][j + 1]);
    }, 500);
  };
英文:

Even though you call setStopVisiting(true), your stopVisiting is not getting assigned a new value so stopVisiting === true is never going to be true.

Instead, don't use a stopVisiting state... it is not needed. You can know whether you have reached the end by making sure you mark it as visited and then by checking endElement.visited, which really is the equivalent of what you intended with stopVisiting.

Some other remarks

  • It is not needed to do both of the following, since they achieve the same:

    newGrid[visElement.i][visElement.j][&quot;visited&quot;] = true;
    visElement[&quot;visited&quot;] = true;
    

    These two assignments assign to the visited property of the same object (Note that newGrid is a shallow copy of grid, so its objects are not copies, but that's OK).

  • The notations [&quot;visited&quot;] and .visited achieve the same. I'd stick with the latter.

  • You have several conditions that stop the process from visiting an element:

    • Having reached the target element
    • Hitting a wall
    • Encountering an element that was already visited.

    These three cases can be checked in one and the same if statement

Here is the updated code:

  const startVisiting = (visElement) =&gt; {
    if (visElement.wall || visElement.visited || endElement.visited) return;

    visElement.visited = true; // This will eventually set `endElement.visited`
    setGrid([...grid]);
    setTimeout(() =&gt; {
      const {i, j} = visElement;  // Destructure to make code below more readable
      if (i &gt;  0) startVisiting(grid[i - 1][j]);
      if (i &lt; 39) startVisiting(grid[i + 1][j]);
      if (j &gt;  0) startVisiting(grid[i][j - 1]);
      if (j &lt; 59) startVisiting(grid[i][j + 1]);
    }, 500);
  };

huangapple
  • 本文由 发表于 2023年6月22日 17:40:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76530530.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定