Algorithm 创建游戏场的算法

Algorithm 创建游戏场的算法,algorithm,logic,Algorithm,Logic,我目前正在寻找一种方法来检查是否每个字段都可以访问,如果可以,是否有一种方法可以在不使用字段两次的情况下访问每个字段。 我现在的想法是从各个方向开始,把用过的土地当作新的墙。如果机器人手被卡住,他会重新启动并转向另一个方向。但我不确定这是否有效。 演出怎么样?这行得通吗 世界/墙壁和机器人的位置是随机的。 机器人驾驶员不得使用他以前使用过的场地 下面是一个示例图像。 根据您的输入,您可以使用一个搜索引擎,以机器人的起始位置作为树的根来搜索整个世界。通常使用BFS,您会记住在这种特定情况下您已经看

我目前正在寻找一种方法来检查是否每个字段都可以访问,如果可以,是否有一种方法可以在不使用字段两次的情况下访问每个字段。 我现在的想法是从各个方向开始,把用过的土地当作新的墙。如果机器人手被卡住,他会重新启动并转向另一个方向。但我不确定这是否有效。 演出怎么样?这行得通吗

世界/墙壁和机器人的位置是随机的。 机器人驾驶员不得使用他以前使用过的场地

下面是一个示例图像。

根据您的输入,您可以使用一个搜索引擎,以机器人的起始位置作为树的根来搜索整个世界。通常使用BFS,您会记住在这种特定情况下您已经看到的“节点”或分幅。当算法终止时,您可以检查访问的节点列表是否等于要访问的节点列表


我认为,如果您知道每个磁贴的相邻节点(例如,通过引用),就可以这样做.

这个问题可以建模为一个图中的连通性问题,我们可以在迷宫中运行一次深度优先搜索,并找到从起始位置可以到达的每个位置,如果任何位置不是墙/块,并且在运行DFS后未访问过,则您无法从任何位置之后的起始位置到达该位置迷宫中的路径

基本上,您需要将游戏中的每个位置表示为图形中的一个节点,其中每个节点都有其北、东、南和西墙的标志。当您希望通过边访问相邻位置时,您只能在相邻位置的墙未朝您尝试来自的方向时进行访问。因此,您所需要做的就是修改DFS算法,以便只有在没有墙的情况下才能访问/调用相邻节点上的DFS

void explore(Node position)
{
    position.visited = true

    while(position.hasUnvisitedDirection())
    {
        //random unvisited direction
        int direction   =   position.getDirection();

        if(direction == WEST && !west(node).visited && !position.westWall)
            explore(west(node));

        if(direction == EAST && !east(node).visited && !position.eastWall)
            explore(east(node));

        if(direction == SOUTH && !south(node).visited && !position.southWall)
            explore(south(node));

        if(direction == NORTH && !north(node).visited && !position.northWall)
            explore(north(node));

    }
}
这里我们对DFS做了一个修改,我们在每个访问的位置随机选择一个未访问的位置。
east(Node)
north(Node)
等调用将分别返回传递节点的位置east、north-注意网格中的边情况(如果将图形建模为二维数组,这非常直观)

接下来,我们要检查图是否只有一个强连接组件,如果DFS中只有一个跳转,则情况就是这样,即我们将在深度优先搜索林中有一棵树,并且每个位置都可以从您想要的起始位置到达。否则,运行DFS后未访问的节点将无法访问,如果算法返回false,则可以在运行DFS后检查这些位置。因此,应通过以下措施实现这一目标:

boolean isConnected(Graph g, Node startPosition)
{
    int jumps   =   0;
    for (Node node : g.nodes())
    {
        if(!node.visited)
        {
            jumps++;
            if(jumps > 1) return false;
            else explore(position);
        }
    }

    return true;
}

可用于解决上述迷宫。

所有单元的可达性都很简单,每个单元只有一个布尔矩阵“可达”,从机器人的起始位置开始传播连通性信息,确保所有单元都已标记。这与世界大小成线性关系,因此没有问题

对于非冗余路径,基本上你需要一个启发式,因为正如在其他答案中已经提到的,哈密顿路径问题是NP。然后编写一个BFS或DFS遍历搜索空间,寻找获胜路径

我使用了下面的启发式方法,在“棋盘马”上可以很好地进行缩放,在“骑士”中,你必须覆盖棋盘上的所有位置。如果你从拓扑学的角度来看,这和你的问题是一样的

因此,启发式:

  • 在每个单元格中,计算出您可以从中解脱出来的方法的数量。将此信息存储在矩阵中。所以中间的一个单元格有4个,墙旁边的一个单元格只有3个等等
  • 在DFS中的每个决策点,选择下一个单元格作为退出次数最少的单元格(这是启发式的核心)
  • 如果两个相邻的单元位于1个传出出口处,回溯,则此分支上的问题已消失
  • 当您输入单元格时,相邻单元格的减量将退出
冲洗并重复

这只是在指导探索,如果你运气不好,探索的总体复杂性仍然很高

直觉上,现在去出口较少的地区是好的,因为以后再回到那里会更加困难。带有1个退出规则的2个单元格只是一个优化,但它可以修剪大型子树,这很好。如果检测到0个出口的未访问单元格,也可以根据放置测试的位置进行回溯


我使用这种启发式方法,即使在比经典的8x8更大的棋盘上,也能轻松地吐出许多解决方案

我已经实现了类似的东西来解决一个被称为“骑士之旅”的难题。我认为,这个问题应该基本上涉及相同的逻辑,只需稍作修改

我不会谈论遍历,我会尝试让它更容易理解-从任何给定的点,回答“下一步最好的动作是什么?”的问题,你想进一步思考并问:“什么是最具限制性的因素?”在这种情况下,最具限制性的因素,基于你的下一步可用动作,是指每个移动可以使用的移动数。你的每一个下一步行动都有自己的下一步行动。下一个可用移动次数最少的下一个可用移动是您的最大限制因素

例如,假设我有移动x,y和z。x和z都有2个下一步可用移动,y有3个下一步可用移动-你想移动到x或z(你决定哪个不重要,所以你可以像我在代码中做的那样随机化)

为什么这有意义?换一种方式考虑一下——下一步可用的移动(在我们的示例中是x、y和z)都是您在某个时候必须到达的点!对于x、y和z的下一步可用移动,也可以考虑将返回到x、y或z的方式。从那以后