OutOfMemoryException用于大尺寸的迷宫求解器

时间:2015-04-06 17:35:15

标签: c# arrays maze

程序适用于高达20x20的数组但是对于任何更大的数组都会抛出OutOfMemoryException。

以下是代码:

public static Point GetFinalPath(int x, int y) {

        queue.Enqueue(new Point(x,y, null));

        while(queue.Count>0) {
            Point p = queue.Dequeue();

            if (arr[p.x,p.y] == 9) {
                Console.WriteLine("Found Destination");
                return p;
            }

            if(IsOpen(p.x+1,p.y)) {
                arr[p.x,p.y] = 1;
                queue.Enqueue(new Point(p.x+1,p.y, p));
            }

            //similarly for the other directions


        }
        return null;
    }

public int[,] SolutionMaze()
            {
                Point p = GetFinalPath(0, 0);

                while (p.getParent() != null)
                {
                    solvedarray[p.x, p.y] = 9;
                    p = p.getParent();
                }
                return solvedarray;
            }

好的人在这里是代码的其余部分

public static Queue<Point> queue=new Queue<Point>();

  public static bool IsOpen(int x, int y)
        {
            //BOUND CHECKING
            if ((x >= 0 && x < XMAX) && (y >= 0 && y < YMAX) && (arr[x,y] == 0 || arr[x,y] == 9))
            {
                return true;
            }
            return false;
        }
 public class Point
        {
           public int x;
           public int y;
            Point parent;

            public Point(int x, int y, Point parent)
            {
                this.x = x;
                this.y = y;
                this.parent = parent;
            }

            public Point getParent()
            {
                return this.parent;
            }

        }

假设开始为0,0并且在构造函数中将最终目标设置为9.

帮我实现一个大小为500x500的数组

2 个答案:

答案 0 :(得分:0)

好吧,看看你的代码,我发现了一个问题。你执行了错误的检查。您应该检查您的点是否已添加到队列中。你现在做什么?我们,您只是将已处理的单元格标记为未打开。很容易看到您可以两次添加到同一节点的队列。

让我们按照我的例子:

1 | . .
0 | ! .
--+----
yx| 0 1
Queue: point (0,0)

我们从点(0,0)开始。此时,我们将点(0,1)和(1,0)添加到我们的队列中并将标记点(0,0)添加为已处理

1 | . .
0 | X !
--+----
yx| 0 1
Queue: point (0,1), point (1,0)

现在我们将点(0,1)出列,将其标记为已处理并将点(1,1)添加到队列中。

1 | ! .
0 | X X
--+----
yx| 0 1
Queue: point (1,0), point(1,1)

现在我们将点(1,0)出列,将其标记为已处理并将点(1,1)添加到队列中:

1 | X !
0 | X X
--+----
yx| 0 1
Queue: point (1,1), point (1,1)

现在我们在队列中有两次相同的点。这不是你的最后一个问题。您的积分会引用所有父母,因此您之前的积分(加倍)也无法使用垃圾收集器进行处理。

答案 1 :(得分:0)

好的,我找到了OutOfMemory的答案。现在代码甚至适用于500x500矩阵 事实证明我刚刚实现了一个节点列表,它使用y * MAX_X_LENGTH + x公式跟踪队列中添加的节点

public static Queue<Point> queue=new Queue<Point>();

        public SolveMaze(int[,] array,int staX,int staY,int finX,int finY)
        {
            //sets Destination as 9
            arr = array;
            XMAX = array.GetLength(0);
            YMAX = array.GetLength(1);
            finishY = finX; finishX = finY; startY = staX; startX = staY;
            solvedarray = new int[XMAX, YMAX];
        }

        public static List<int> nodelist=new List<int>();

        public void AddPointToQueueIfOpenAndNotAlreadyPresent(Point p,int direction)
        {
            if (nodelist.Contains(XMAX * p.y + p.x))
                return;
            else
            {
                switch(direction){
                case 1:
                    //north
                    if (IsOpen(p.x, p.y - 1))
                    {
                        arr[p.x, p.y] = 1;
                        queue.Enqueue(new Point(p.x, p.y - 1, p));
                        nodelist.Add(XMAX * (p.y - 1) + p.x);
                    }
                    break;
                case 0:
                    //east
                    if (IsOpen(p.x + 1, p.y))
                    {
                        arr[p.x, p.y] = 1;
                        queue.Enqueue(new Point(p.x + 1, p.y, p));
                        nodelist.Add(XMAX * (p.y) + p.x + 1);
                    }
                    break;
                case 3:
                    //south
                    if (IsOpen(p.x, p.y + 1))
                    {
                        arr[p.x, p.y] = 1;
                        queue.Enqueue(new Point(p.x, p.y +1, p));
                        nodelist.Add(XMAX * (p.y + 1) + p.x);
                    }
                    break;
                case 2:
                    //west
                    if (IsOpen(p.x - 1, p.y))
                    {
                        arr[p.x, p.y] = 1;
                        queue.Enqueue(new Point(p.x - 1, p.y, p));
                        nodelist.Add(XMAX * (p.y) + p.x-1);
                    }
                    break;                    }
            }
        }

        public Point GetFinalPath(int x, int y) {
            if (arr[finishX, finishY] == 0)
                arr[finishX, finishY] = 9;
            else
                return null;

                queue.Enqueue(new Point(x, y, null));
                nodelist.Add(XMAX * y + x);

        while(queue.Count>0) {
            Point p = queue.Dequeue();
            nodelist.Remove(p.y * XMAX + p.x);

            if (arr[p.x,p.y] == 9) {
                Console.WriteLine("Exit is reached!");
                return p;
            }

            for (int i = 0; i < 4; i++)
            {
                AddPointToQueueIfOpenAndNotAlreadyPresent(p, i);
            }
        }
        return null;
    }


        public static bool IsOpen(int x, int y)
        {
            //BOUND CHECKING
            if ((x >= 0 && x < XMAX) && (y >= 0 && y < YMAX) && (arr[x,y] == 0 || arr[x,y] == 9))
            {
                return true;
            }
            return false;
        }


            public int[,] SolutionMaze()
            {
                Point p = GetFinalPath(startX, startY);
                if(p!=null)
                while (p.getParent() != null)
                {
                    solvedarray[p.x, p.y] = 9;
                    p = p.getParent();
                }
                return solvedarray;
            }
    }

         public class Point
        {
           public int x;
           public int y;
            Point parent;

            public Point(int x, int y, Point parent)
            {
                this.x = x;
                this.y = y;
                this.parent = parent;
            }

            public Point getParent()
            {
                return this.parent;
            }

        }