C#迷宫生成我自己实现的Prim';s算法错误

C#迷宫生成我自己实现的Prim';s算法错误,c#,windows,xna,prims-algorithm,C#,Windows,Xna,Prims Algorithm,首先,让我为尺寸道歉,我会尽量让这个小一些 在尝试按照维基百科上的说法构建prim的算法后,我发现它无法按照我构建迷宫的方式工作。 所以我试着做同样的想法来适应我的迷宫,但我看到一个奇怪的虫子 当我的游戏开始时,它只是没有正确地构建我的迷宫,我不知道为什么 这是偶尔发生的事情 其他时候它工作得很好, 因此,我有一个公共字典迷宫当它启动迷宫时,它保持迷宫。迷宫是所有的树篱,然后我继续像这样构建路径 private static void buildPath() {

首先,让我为尺寸道歉,我会尽量让这个小一些

在尝试按照维基百科上的说法构建prim的算法后,我发现它无法按照我构建迷宫的方式工作。 所以我试着做同样的想法来适应我的迷宫,但我看到一个奇怪的虫子

当我的游戏开始时,它只是没有正确地构建我的迷宫,我不知道为什么 这是偶尔发生的事情

其他时候它工作得很好, 因此,我有一个
公共字典迷宫
当它启动迷宫时,它保持迷宫。迷宫是所有的树篱,然后我继续像这样构建路径

private static void buildPath()
       {
           List<KeyValuePair<Misc.Cord, Misc.Cord>> ends = new List<KeyValuePair<Misc.Cord, Misc.Cord>>();
           ends.Add(new KeyValuePair<Misc.Cord, Misc.Cord>(new Misc.Cord() { X = 0, Y = 0 }, new Misc.Cord() { X = 0, Y = 0 }));
           Misc.Cord currentPos = null;

           while (ends.Count > 0)
           {
               int posKey = rand.Next(0, ends.Count);
               Misc.Cord lastPos = ends[posKey].Key;
               currentPos = ends[posKey].Value;
               maze[currentPos.X][currentPos.Y] = MazeCellState.Path;
               int currentCount = 0;

               MovingState moveTo1 = (MovingState)rand.Next(0, 4);
               MovingState moveTo2 = (MovingState)rand.Next(0, 4);
               while (moveTo1.Equals(moveTo2))
               {
                   moveTo1 = (MovingState)rand.Next(0, 4);
                   moveTo2 = (MovingState)rand.Next(0, 4);
               }

               // check left
               if (currentPos.X - 2 > 0 && maze[currentPos.X - 2][currentPos.Y] != MazeCellState.Path && currentCount < 2 && (moveTo1 == MovingState.Left || moveTo2 == MovingState.Left))
               {
                   if(!lastPos.Equals(new Misc.Cord() { X = currentPos.X - 2, Y = currentPos.Y }))
                   {
                       ends.Add(new KeyValuePair<Misc.Cord, Misc.Cord>(currentPos, new Misc.Cord() { X = currentPos.X - 2, Y = currentPos.Y }));
                       maze[currentPos.X - 1][currentPos.Y] = MazeCellState.Path;
                       currentCount++;
                   }
               }

               // check right
               if (currentPos.X + 2 < maze.Count && maze[currentPos.X + 2][currentPos.Y] != MazeCellState.Path && currentCount < 2 && (moveTo1 == MovingState.Right || moveTo2 == MovingState.Right))
               {
                   if (!lastPos.Equals(new Misc.Cord() { X = currentPos.X + 2, Y = currentPos.Y }))
                   {
                       ends.Add(new KeyValuePair<Misc.Cord, Misc.Cord>(currentPos, new Misc.Cord() { X = currentPos.X + 2, Y = currentPos.Y }));
                       maze[currentPos.X + 1][currentPos.Y] = MazeCellState.Path;
                       currentCount++;
                   }
               }

               // check Up
               if (currentPos.Y - 2 > 0 && maze[currentPos.X][currentPos.Y - 2] != MazeCellState.Path && currentCount < 2 && (moveTo1 == MovingState.Up || moveTo2 == MovingState.Up))
               {
                   if(!lastPos.Equals(new Misc.Cord() { X = currentPos.X, Y = currentPos.Y - 2}))
                   {
                       ends.Add(new KeyValuePair<Misc.Cord, Misc.Cord>(currentPos, new Misc.Cord() { X = currentPos.X, Y = currentPos.Y - 2 }));
                       maze[currentPos.X][currentPos.Y - 1] = MazeCellState.Path;
                       currentCount++;
                   }
               }

               // check Down
               if (currentPos.Y + 2 < maze[0].Count && maze[currentPos.X][currentPos.Y + 2] != MazeCellState.Path && currentCount < 2 && (moveTo1 == MovingState.Down || moveTo2 == MovingState.Down))
               {
                   if(!lastPos.Equals(new Misc.Cord() { X = currentPos.X, Y = currentPos.Y + 2}))
                   {
                       ends.Add(new KeyValuePair<Misc.Cord, Misc.Cord>(currentPos, new Misc.Cord() { X = currentPos.X, Y = currentPos.Y + 2 }));
                       maze[currentPos.X][currentPos.Y + 1] = MazeCellState.Path;
                       currentCount++;
                   }
               }
                ends.RemoveAt(posKey);
                ends = reorderList(ends);
           }

           maze[0][1] = MazeCellState.Path;
       }

当你的领域是一个网格时,这真的是一个很难实现算法的方法。Prim的网格算法更容易表达。我将告诉您一个简单的方法,而不是研究您在代码中犯了什么错误

创建网格,并使用从零开始的连续数字对所有单元格进行编号。每个细胞有两个可以打破的边界墙;向上和向左,或向下和向右,或其他组合,只要您选择其中一个(左/右)和一个(向上/向下),这并不重要

现在选择任意一个单元,并选择其一面墙。如果该墙另一侧的单元格有不同的编号(一高一低),则打破该墙,然后在整个迷宫中,将所有出现的较高编号重新编号为较低编号。如果选择了一个单元格和另一侧已具有相同编号的墙,则不要尝试另一面墙,而是按顺序移动到下一个单元格,在每行上下重复(可能几乎一路循环),直到找到一个具有可以打破的墙的单元格

如果有N个单元格,则必须重复此破壁练习N-1次,直到最后一次所有单元格都编号为零(因为每次破壁时,都会从字段中删除较高的数字),这样就有了一个完整的迷宫

如果你想要一个迷宫,它的路径通常是从左到右而不是从上到下,那么你可以随意选择在那个方向打破哪堵墙。这也适用于3D迷宫,在那里你可能不需要很多梯子;只是不要选择打破这么多的天花板/地板


在我描述了这个算法之后,我的14岁儿子在3D中用Turbo Pascal实现了它,所以我知道这个算法和这个描述实际上是可行的。这实际上是Prim算法的一个版本,除非所有的弧都具有相同的代价(或者所有的左右弧都具有相同的代价,所有的上下弧都具有相同的代价,等等)。它的巧妙之处在于,编号的方式可以确定哪些单元格已经可以从其他单元格访问到。

好的,对不起,你的第三段让我不知所措。这可能是我的阅读障碍,但你对编号有什么看法?一个高一个低,但你们并没有说任何关于从0开始设置数字的事情,你们怎么会在一个x数组中有一个墙,其中包含一个y数组,其中包含0,但你们并没有说任何关于改变数字的事情,你们的数字系统中有什么墙是0?另外,根据你的解释,整个最上面一行都是一条路径,这使得迷宫有点容易观看视频。哦,另一个注意事项是,我刚刚加入了一个黑客来扫描迷宫,如果存在少于5条路径,那么重新做迷宫构建,因为这是一年前的事,现在我不敢相信你学会了这一点,但是很高兴知道pascal正在以某种形式被使用,我做到了我甚至认为你再也找不到Turbo的编译器了。我想这是一个代码帮助网站,你所提供的是很多网站所提供的,甚至是一段代码的引用都能很好地说明你的意思,但是在TP中构建与我在第二段中所说的多线程C#应用程序是非常不同的“用从零开始的连续数字对所有单元格进行编号”。这些是您在第3段中使用的数字。因此,如果您决定打破墙(底墙)对,很明显,最右边的列不能打破右边的墙,最下面的一行不能打破最下面的墙,但除此之外,每个单元格都可以打破任意一面墙或两面墙。一次只能打破一面墙,并且只有当这面墙的每一边都有不同的数字时。然后随机选择另一面墙来打破。选择时,如果y如果你选择了一堵你无法打破的墙,只有这样你才能通过搜索来找到一堵你可以打破的墙。如果你不这样搜索,它需要很长时间才能完成。而且维基百科的视频显示了一个糟糕的迷宫。如果你总是从一开始就建造,你会得到一个辐射的迷宫,它不是真正随机分布的。对于最小路径问题很好ems,但对迷宫不好。我在注意到我所有迷宫的辐射模式之前也犯了这个错误。
            GraphicsDevice.Viewport.Width * 5 / 64,
            GraphicsDevice.Viewport.Height * 5 / 64