无法看到如何将洪水填充程序更改为DFS

时间:2016-03-13 01:19:17

标签: javascript minecraft

我一直在使用洪水填充例程来检查某种类型的块,然后查找所有相同类型的连接块,并将它们更改为键入" stone" 我主要感兴趣的是块的坐标,并且不想改变它们,但是当我删除"更改为stone"声明似乎无休止地运行。 在研究之后,似乎深度优先搜索可以工作但不确定如何实现 - 似乎我只需要调整洪水填充,但我尝试的一切都无休止地循环或在第一次迭代时停止。 这是原始计划。



//interact
var node1 = {
 xy : []
};
var blockp;
//starting block type and position
blockp = world.getBlock(npc.getBlockX(), npc.getBlockY() - 1, npc.getBlockZ() + 1);
node1.xy[0] = npc.getBlockX();
node1.xy[1] = npc.getBlockZ() + 1;
node1.xy[2] = npc.getBlockY() - 1;
//
var floodfill = function (nameb, node) {
 if (nameb == "minecraft:stone" || nameb == null) {
  return;
 }
 var blkname;
 var xy0 = node.xy[0];
 var xy1 = node.xy[1];
 var xy2 = node.xy[2];
 //
 //Line I would like to remove
 world.setBlock(node.xy[0], node.xy[2], node.xy[1], world.createItem("minecraft:stone", 0, 1));
 //
 // collect x y z positions for all blocks
 world.getTempData("X_corr").push(node.xy[0]);
 world.getTempData("Y_corr").push(node.xy[2]);
 world.getTempData("Z_corr").push(node.xy[1]);
 //
 node.xy[0] = xy0;
 node.xy[1] = xy1 + 1;
 node.xy[2] = xy2;
 if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
  blkname = null;
 } else {
  blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
 }
 floodfill(blkname, node);
 //
 node.xy[0] = xy0;
 node.xy[1] = xy1 - 1;
 node.xy[2] = xy2;
 if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
  blkname = null;
 } else {
  blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
 }
 floodfill(blkname, node);
 //
 node.xy[0] = xy0 + 1;
 node.xy[1] = xy1;
 node.xy[2] = xy2;
 if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
  blkname = null;
 } else {
  blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
 }
 floodfill(blkname, node);
 //
 node.xy[0] = xy0 - 1;
 node.xy[1] = xy1;
 node.xy[2] = xy2;
 if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
  blkname = null;
 } else {
  blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
 }
 floodfill(blkname, node);
 //
 node.xy[0] = xy0;
 node.xy[1] = xy1;
 node.xy[2] = xy2 + 1;
 npc.say("go up " + blkname);
 if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
  blkname = null;
 } else {
  blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
  npc.say("go up " + blkname);
 }
 floodfill(blkname, node);
 //
 node.xy[0] = xy0;
 node.xy[1] = xy1;
 node.xy[2] = xy2 - 1;
 if (world.getBlock(node.xy[0], node.xy[2], node.xy[1]) == null) {
  blkname = null;
 } else {
  blkname = world.getBlock(node.xy[0], node.xy[2], node.xy[1]).name;
 }
 floodfill(blkname, node);
 //
 return;
}
floodfill(blockp.name, node1);




1 个答案:

答案 0 :(得分:0)

让我首先了解为什么洪水填充永远不会结束:它不知道什么时候必须停止,因为没有一个块发生变化。该程序认为它之前从未遇到过阻塞,并再次看到它,并再次看到......

深度优先搜索是一种更深入的搜索方法,直到它不再存在。当你撞到一个部件的末端时,你会回去,直到你遇到一个你以前从未见过的物品,然后在与之相关的任何东西中潜水。

广度优先搜索恰恰相反。它会检查连接到起始点的内容,检查所有内容,然后检查所有子项及其子项,等等。

因为你想找到所有相互连接的块,所以你选择哪种搜索方法没有区别,因为它们会找到相同O(n)复杂度的所有项目。

我个人对你正在尝试做的事情一无所知,但我试图尽可能保持这种普遍性。

对于这些搜索中的任何一个,block应该有一个名为visited的变量或类似的变量,您可以用它来表示您之前是否遇到此阻止。您可能必须自己创建此变量。 您还需要一种方法来查找block所连接的block并将其作为数组或列表返回。在示例中,我将调用此函数neighbours()

要实施DFS,您需要Stack。堆栈是一个LIFO数据结构,这意味着最后出现的是第一件事。将某些东西放入堆栈称为push。将该项目取回称为pop

这是DFS的伪代码:

DFS(Block start) {
    Stack stack = new stack();
    stack.push(start); // Put the first block in the stack
    while(stack.count > 0) {
         Block current = stack.pop();

         if(current.visited)
              continue; // if we've already seen this block, don't bother 
         current.visited = true;

         /* YOU CAN DO ANYTHING YOU WANT WITH THE BLOCK HERE */

         Block[] neighbours = current.neighbours();
         foreach(neighbour in neighbours)
              stack.push(neighbour);
    }
}

BFS是不同的,稍微适合您要做的事情。它使用Queue来存储以先进先出顺序搜索所需的所有内容。这意味着稍后将搜索搜索树下方的内容,这通常更适合任何搜索。向队列中添加内容称为enqueue,将下一个内容称为dequeue

这是BFS的伪代码:

BFS(Block start)
    Queue queue = new Queue();
    queue.enqueue(start); // Put the first block in the stack
    while(queue.count > 0) {
         Block current = queue.dequeue();

         if(current.visited)
              continue; // if we've already seen this block, don't bother 
         current.visited = true;

         /* YOU CAN DO ANYTHING YOU WANT WITH THE BLOCK HERE */

         Block[] neighbours = current.neighbours();
         foreach(neighbour in neighbours)
              queue.enqueue(neighbour);
    }
}

如您所见,两种搜索方法都非常相似,它们都在O(n)time complexity中运行。

祝你好运!