Exemplo n.º 1
0
        /// <summary>
        /// String showing the solved maze result
        /// </summary>
        /// <returns>
        /// Returns string representation of the solved maze.
        /// </returns>
        ///
        public string ResultString()
        {
            char[] mazeDrawing = new char[height * width];
            // fill in start and end
            mazeDrawing[startX + (startY * width)] = 'S';
            mazeDrawing[endX + (endY * width)]     = 'E';
            // loop through each parent, add an X until we find start
            Queue <currentPoint> path = new Queue <currentPoint>();

            // start with end point
            path.Enqueue(new currentPoint(endX, endY));

            while (path.Count > 0)
            {
                currentPoint p = path.Dequeue();
                //  while not reaching the start
                if (p.X != startX || p.Y != startY)
                {
                    // queue this points parent
                    path.Enqueue(mazeParents[p.X + (p.Y * width)]);
                    if (p.X != endX || p.Y != endY)
                    {
                        // draw an X if this is not the end location
                        mazeDrawing[p.X + (p.Y * width)] = 'X';
                    }
                }
            }

            // fill in the rest
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    // if the point has not already been filled in
                    if (mazeDrawing[x + (y * width)] == '\0')
                    {
                        // wall or pathway
                        if (mazeData[x + (y * width)])
                        {
                            mazeDrawing[x + (y * width)] = '#';
                        }
                        else
                        {
                            mazeDrawing[x + (y * width)] = ' ';
                        }
                    }
                }
            }

            // print it out
            string solvedPrint = "";

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    solvedPrint += mazeDrawing[x + (y * width)] + " ";
                }
                solvedPrint += "\n";
            }
            return(solvedPrint);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Solve the maze using breadth first search
        /// </summary>
        /// <returns>
        /// Returns whether the maze was solved successfully. True or false.
        /// </returns>
        ///
        public bool Solve()
        {
            // tested copying the fields to local variables here, it gave no signficat benefit to the speed of the algorithm when averaging 1000 large maze solves.
            stopwatch.Restart();

            // start with the starting point
            Queue <currentPoint> todo = new Queue <currentPoint>();

            todo.Enqueue(new currentPoint(startX, startY));

            // using 'width' as a stride to separate data into rows when accessing.
            // use 1 rather than 0, just to save time inialising all the entries as -1, since 0 is the int default.
            mazeDistance[startX + (startY * width)] = 1;

            // solved flag
            bool endFound = false;

            // loop until all traversable points have been searched, or end has been found.
            while (todo.Count > 0 && !endFound)
            {
                // grab the current point
                currentPoint p = todo.Dequeue();
                // local variables rather than pulling the object refrence each time.
                int pX = p.X;
                int pY = p.Y;

                // check for end location
                if (pX == endX && pY == endY)
                {
                    endFound = true;
                }
                else
                {
                    // get the current disance from start
                    int current = mazeDistance[pX + (pY * width)];

                    // check the adjacent points
                    // use an inline method as this is not strictly a "class" funtion,
                    // but rather a section of repeated code only used by this method.
                    CheckPoint checkPoint = (x, y) => {
                        // make sure point is within the bounds of the maze
                        if (x >= 0 && x < width && y >= 0 && y < height)
                        {
                            if (mazeDistance[x + (y * width)] == 0) // not yet processed
                            {
                                if (!mazeData[x + (y * width)])     // only process viable pathways
                                {
                                    // add distance, parent and queue for further processing
                                    mazeDistance[x + (y * width)] = current + 1;
                                    mazeParents[x + (y * width)]  = p;
                                    todo.Enqueue(new currentPoint(x, y));
                                }
                            }
                        }
                    };

                    // Right
                    int newX = pX + 1;
                    int newY = pY;
                    checkPoint(newX, newY);

                    // Left
                    newX = pX - 1;
                    newY = pY;
                    checkPoint(newX, newY);

                    // Up
                    newX = pX;
                    newY = pY + 1;
                    checkPoint(newX, newY);

                    // Down
                    newX = pX;
                    newY = pY - 1;
                    checkPoint(newX, newY);
                }
            }
            stopwatch.Stop();

            solveMillis = stopwatch.ElapsedMilliseconds;
            solveTicks  = stopwatch.ElapsedTicks;

            return(endFound);
        }