예제 #1
0
        /// <summary>
        /// Used to create a begin and end for a maze
        /// </summary>
        /// <param name="arr">The array of the maze</param>
        private void makeMazeBeginEnd(Cell[,] arr)
        {
            Point temp = new Point();
            temp.Y = this.random.Next(this.height);
            arr[temp.Y, temp.X].LeftWall = false;
            this.begin = arr[temp.Y, temp.X];

            temp.Y = this.random.Next(this.height);
            temp.X = this.width - 1;
            arr[temp.Y, temp.X].RightWall = false;
            this.end = arr[temp.Y, temp.X];
        }
예제 #2
0
        /// <summary>
        /// Solves the maze with the right-hand role recursively -
        /// DON'T USE! IT IS FOR DEMONSTRATING PURPOSES ONLY!
        /// </summary>
        /// <param name="start">The maze begin</param>
        /// <param name="dir">the initial direction</param>
        private void rightHandRuleSolve(Cell start, Directions dir)
        {
            /*بص على يمينك
             فاضي؟ خش من غير كلام كثير
             في حيطة؟ بص قدامك
             في حيطة برضه؟ طب شوف شمالك كده
             حيطة؟ ارجع بقى*/

            // look at your right (with respect to your direction)
            // No wall? go in it.
            // Wall? look at your front (with respect to your direction)
            // Wall too? look at your left (with respect to your direction)
            // Wall too? go back (in the reverse of your direction)

            // note that the right of the right is down, the left of down is right, ect

            // has arrived, return
            if (start.Position == this.end.Position)
            {
                return;
            }

            // mark it as visited for graphics
            this.maze[start.Position.Y, start.Position.X].Visited = true;
            // to view the current solving location
            this.currentSolvePos = start.Position;
            // to slow operation
            Thread.SpinWait(this.Sleep * sleepPeriod);

            bool flag;

            switch (dir)
            {
            case Directions.Right:
                    flag = start.Position.Y + 1 < height;
                if (!flag || this.maze[start.Position.Y + 1, start.Position.X].UpWall)
                {
                    flag = start.Position.X + 1 < width;
                    if (!flag || maze[start.Position.Y, start.Position.X + 1].LeftWall)
                    {
                        flag = start.Position.Y - 1 >= 0;
                        if (!flag || maze[start.Position.Y - 1, start.Position.X].DownWall)
                        {
                            rightHandRuleSolve(this.maze[start.Position.Y, start.Position.X], Directions.Left);
                        }
                        else
                        {
                            rightHandRuleSolve(maze[start.Position.Y - 1, start.Position.X], Directions.Up);
                        }
                    }
                    else
                    {
                        rightHandRuleSolve(this.maze[start.Position.Y, start.Position.X + 1], Directions.Right);
                    }
                }
                else
                {
                    rightHandRuleSolve(this.maze[start.Position.Y + 1, start.Position.X], Directions.Down);
                }
                break;

            case Directions.Left:
                flag = start.Position.Y - 1 >= 0;
                if (!flag || maze[start.Position.Y - 1, start.Position.X].DownWall)
                {
                    flag = start.Position.X - 1 >= 0;
                    if (!flag || maze[start.Position.Y, start.Position.X - 1].RightWall)
                    {
                        flag = start.Position.Y + 1 < this.height;
                        if (!flag || maze[start.Position.Y + 1, start.Position.X].UpWall)
                        {
                            rightHandRuleSolve(maze[start.Position.Y, start.Position.X], Directions.Right);
                        }
                        else
                        {
                            rightHandRuleSolve(maze[start.Position.Y + 1, start.Position.X], Directions.Down);
                        }
                    }
                    else
                    {
                        rightHandRuleSolve(maze[start.Position.Y, start.Position.X - 1], Directions.Left);
                    }
                }
                else
                {
                    rightHandRuleSolve(maze[start.Position.Y - 1, start.Position.X], Directions.Up);
                }
                break;

            case Directions.Up:
                flag = start.Position.X + 1 < this.width;
                if (!flag || maze[start.Position.Y, start.Position.X + 1].LeftWall)
                {
                    flag = start.Position.Y - 1 >= 0;
                    if (!flag || maze[start.Position.Y - 1, start.Position.X].DownWall)
                    {
                        flag = start.Position.X - 1 >= 0;
                        if (!flag || maze[start.Position.Y, start.Position.X - 1].RightWall)
                        {
                            rightHandRuleSolve(maze[start.Position.Y, start.Position.X], Directions.Down);
                        }
                        else
                        {
                            rightHandRuleSolve(maze[start.Position.Y, start.Position.X - 1], Directions.Left);
                        }
                    }
                    else
                    {
                        rightHandRuleSolve(maze[start.Position.Y - 1, start.Position.X], Directions.Up);
                    }
                }
                else
                {
                    rightHandRuleSolve(maze[start.Position.Y, start.Position.X + 1], Directions.Right);
                }
                break;
            default:
                flag = start.Position.X - 1 >= 0;
                if (!flag || maze[start.Position.Y, start.Position.X - 1].RightWall)
                {
                    flag = start.Position.Y + 1 < this.height;
                    if (!flag || maze[start.Position.Y + 1, start.Position.X].UpWall)
                    {
                        flag = start.Position.X + 1 < this.width;
                        if (!flag || maze[start.Position.Y, start.Position.X + 1].LeftWall)
                        {
                            rightHandRuleSolve(maze[start.Position.Y, start.Position.X], Directions.Up);
                        }
                        else
                        {
                            rightHandRuleSolve(maze[start.Position.Y, start.Position.X + 1], Directions.Right);
                        }
                    }
                    else
                    {
                        rightHandRuleSolve(maze[start.Position.Y + 1, start.Position.X], Directions.Down);
                    }
                }
                else
                {
                    rightHandRuleSolve(maze[start.Position.Y, start.Position.X - 1], Directions.Left);
                }
                break;
            }
        }
예제 #3
0
        /// <summary>
        /// Solves the maze with the right-hand role iteratively
        /// </summary>
        /// <param name="start">The maze begin</param>
        /// <param name="dir">the initial direction</param>
        private void iterativeRightHandRuleSolve(Cell start, Directions dir)
        {
            // look at your right (with respect to your direction)
            // No wall? go in it.
            // Wall? look at your front (with respect to your direction)
            // Wall too? look at your left (with respect to your direction)
            // Wall too? go back (in the reverse of your direction)

            // note that the right of the right is down, the left of down is right, ect

            bool flag;
            // repeat while you didn't reach the end
            while (start.Position != this.end.Position)
            {
                // for graphics
                this.maze[start.Position.Y, start.Position.X].Visited = true;
                // for graphics
                this.currentSolvePos = start.Position;

                // to slow operation
                Thread.SpinWait(this.Sleep * sleepPeriod);

                switch (dir)
                {
                    case Directions.Right:
                        // has up wall?
                        flag = start.Position.Y + 1 < height;
                        if (!flag || this.maze[start.Position.Y + 1, start.Position.X].UpWall)
                        {
                            // has left wall?
                            flag = start.Position.X + 1 < width;
                            if (!flag || maze[start.Position.Y, start.Position.X + 1].LeftWall)
                            {
                                // has down wall ?
                                flag = start.Position.Y - 1 >= 0;
                                if (!flag || maze[start.Position.Y - 1, start.Position.X].DownWall)
                                {
                                    start = this.maze[start.Position.Y, start.Position.X];
                                    dir = Directions.Left;
                                }
                                else
                                {
                                    start = maze[start.Position.Y - 1, start.Position.X];
                                    dir = Directions.Up;
                                }
                            }
                            else
                            {
                                start = this.maze[start.Position.Y, start.Position.X + 1];
                                dir = Directions.Right;
                            }
                        }
                        else
                        {
                            start = this.maze[start.Position.Y + 1, start.Position.X];
                            dir = Directions.Down;
                        }
                        break;
                    case Directions.Left:
                        flag = start.Position.Y - 1 >= 0;
                        if (!flag || maze[start.Position.Y - 1, start.Position.X].DownWall)
                        {
                            flag = start.Position.X - 1 >= 0;
                            if (!flag || maze[start.Position.Y, start.Position.X - 1].RightWall)
                            {
                                flag = start.Position.Y + 1 < this.height;
                                if (!flag || maze[start.Position.Y + 1, start.Position.X].UpWall)
                                {
                                    start = maze[start.Position.Y, start.Position.X];
                                    dir = Directions.Right;
                                }
                                else
                                {
                                    start = maze[start.Position.Y + 1, start.Position.X];
                                    dir = Directions.Down;
                                }
                            }
                            else
                            {
                                start = maze[start.Position.Y, start.Position.X - 1];
                                dir = Directions.Left;
                            }
                        }
                        else
                        {
                            start = maze[start.Position.Y - 1, start.Position.X];
                            dir = Directions.Up;
                        }
                        break;
                    case Directions.Up:
                        flag = start.Position.X + 1 < this.width;
                        if (!flag || maze[start.Position.Y, start.Position.X + 1].LeftWall)
                        {
                            flag = start.Position.Y - 1 >= 0;
                            if (!flag || maze[start.Position.Y - 1, start.Position.X].DownWall)
                            {
                                flag = start.Position.X - 1 >= 0;
                                if (!flag || maze[start.Position.Y, start.Position.X - 1].RightWall)
                                {
                                    start = maze[start.Position.Y, start.Position.X];
                                    dir = Directions.Down;
                                }
                                else
                                {
                                    start = maze[start.Position.Y, start.Position.X - 1];
                                    dir = Directions.Left;
                                }
                            }
                            else
                            {
                                start = maze[start.Position.Y - 1, start.Position.X];
                                dir = Directions.Up;
                            }
                        }
                        else
                        {
                            start = maze[start.Position.Y, start.Position.X + 1];
                            dir = Directions.Right;
                        }
                        break;
                    default:
                        flag = start.Position.X - 1 >= 0;
                        if (!flag || maze[start.Position.Y, start.Position.X - 1].RightWall)
                        {
                            flag = start.Position.Y + 1 < this.height;
                            if (!flag || maze[start.Position.Y + 1, start.Position.X].UpWall)
                            {
                                flag = start.Position.X + 1 < this.width;
                                if (!flag || maze[start.Position.Y, start.Position.X + 1].LeftWall)
                                {
                                    start = maze[start.Position.Y, start.Position.X];
                                    dir = Directions.Up;
                                }
                                else
                                {
                                    start = maze[start.Position.Y, start.Position.X + 1];
                                    dir = Directions.Right;
                                }
                            }
                            else
                            {
                                start = maze[start.Position.Y + 1, start.Position.X];
                                dir = Directions.Down;
                            }
                        }
                        else
                        {
                            start = maze[start.Position.Y, start.Position.X - 1];
                            dir = Directions.Left;
                        }
                        break;
                }
            }

            this.maze[start.Position.Y, start.Position.X].Visited = true;
            this.currentSolvePos = start.Position;
        }
예제 #4
0
 /// <summary>
 /// Knocks wall between two neighbor cellls
 /// </summary>
 /// <param name="maze">The maze array</param>
 /// <param name="current">the current cell</param>
 /// <param name="next">the next neighbor cell</param>
 private void knockWall(Cell[,] maze, ref Cell current, ref Cell next)
 {
     // The next is down
     if (current.Position.X == next.Position.X && current.Position.Y > next.Position.Y)
     {
         maze[current.Position.Y, current.Position.X].UpWall = false;
         maze[next.Position.Y, next.Position.X].DownWall = false;
     }
     // the next is up
     else if (current.Position.X == next.Position.X)
     {
         maze[current.Position.Y, current.Position.X].DownWall = false;
         maze[next.Position.Y, next.Position.X].UpWall = false;
     }
     // the next is right
     else if (current.Position.X > next.Position.X)
     {
         maze[current.Position.Y, current.Position.X].LeftWall = false;
         maze[next.Position.Y, next.Position.X].RightWall = false;
     }
     // the next is left
     else
     {
         maze[current.Position.Y, current.Position.X].RightWall = false;
         maze[next.Position.Y, next.Position.X].LeftWall = false;
     }
 }
예제 #5
0
        /// <summary>
        /// Resets a maze array
        /// </summary>
        /// <param name="arr">The maze array</param>
        /// <param name="width">Number of squares in width</param>
        /// <param name="height">Number of squares in height</param>
        private void initailze(Cell[,] arr, int width, int height)
        {
            this.width = width;
            this.height = height;

            for (int i = 0; i < this.height; i++)
            {
                for (int j = 0; j < this.width; j++)
                {
                    arr[i, j] = new Cell(new Point(j * this.unitX, i * this.unitY), new Point(j, i));
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Solves a maze with iterative backtracking DFS
        /// </summary>
        /// <param name="start">The start of the maze cell</param>
        /// <param name="end">The end of the maze cell</param>
        /// <returns>returrns true if the path is found</returns>
        private unsafe bool iterativeDepthFirstSearchSolve(Cell start, Cell end)
        {
            // unsafe indicates that this method uses pointers
            Stack<Cell> stack = new Stack<Cell>();

            stack.Push(start);

            while (stack.Count > 0)
            {
                Cell temp = stack.Pop();

                // base condition
                if (temp.Position == end.Position)
                {
                    // add end point to foundPath
                    this.foundPath.Add(temp);
                    // dereference all pointers chain until you reach the begin
                    while (temp.Previous != null)
                    {
                        this.foundPath.Add(temp);
                        temp = *temp.Previous;
                    }
                    // add begin point to foundPath
                    this.foundPath.Add(temp);
                    // to view green square on it
                    this.maze[temp.Position.Y, temp.Position.X].Visited = true;
                    return true;
                }

                // for the graphics
                this.currentSolvePos = temp.Position;

                // mark as visited to prevent infinite loops
                this.maze[temp.Position.Y, temp.Position.X].Visited = true;

                // used to slow operation
                Thread.SpinWait(this.Sleep * sleepPeriod);

                // Check every neighbor cell
                // If it exists (not outside the maze bounds)
                // and if there is no wall between start and it
                    // set the next.Previous to the current cell
                    // push next into stack
                // else complete

                // Left
                if (temp.Position.X - 1 >= 0
                    && !this.maze[temp.Position.Y, temp.Position.X - 1].RightWall
                    && !this.maze[temp.Position.Y, temp.Position.X - 1].Visited)
                {
                    // fixed must be used to indicate that current memory-location won't be changed
                    fixed (Cell* cell = &this.maze[temp.Position.Y, temp.Position.X])
                        this.maze[temp.Position.Y, temp.Position.X - 1].Previous = cell;
                    stack.Push(this.maze[temp.Position.Y, temp.Position.X - 1]);
                }

                // Right
                if (temp.Position.X + 1 < this.width
                    && !this.maze[temp.Position.Y, temp.Position.X + 1].LeftWall
                    && !this.maze[temp.Position.Y, temp.Position.X + 1].Visited)
                {
                    fixed (Cell* cell = &this.maze[temp.Position.Y, temp.Position.X])
                        this.maze[temp.Position.Y, temp.Position.X + 1].Previous = cell;
                    stack.Push(this.maze[temp.Position.Y, temp.Position.X + 1]);
                }

                // Up
                if (temp.Position.Y - 1 >= 0
                    && !this.maze[temp.Position.Y - 1, temp.Position.X].DownWall
                    && !this.maze[temp.Position.Y - 1, temp.Position.X].Visited)
                {
                    fixed (Cell* cell = &this.maze[temp.Position.Y, temp.Position.X])
                        this.maze[temp.Position.Y - 1, temp.Position.X].Previous = cell;
                    stack.Push(this.maze[temp.Position.Y - 1, temp.Position.X]);
                }

                // Down
                if (temp.Position.Y + 1 < this.height
                    && !this.maze[temp.Position.Y + 1, temp.Position.X].UpWall
                    && !this.maze[temp.Position.Y + 1, temp.Position.X].Visited)
                {
                    fixed (Cell* cell = &this.maze[temp.Position.Y, temp.Position.X])
                        this.maze[temp.Position.Y + 1, temp.Position.X].Previous = cell;
                    stack.Push(this.maze[temp.Position.Y + 1, temp.Position.X]);
                }
            }
            // no solution found
            return false;
        }
예제 #7
0
        /// <summary>
        /// Gets all neighbor cells to a specific cell, 
        /// where those neighbors exist and not visited already
        /// </summary>
        /// <param name="arr">The maze array</param>
        /// <param name="cell">The current cell to get neighbors</param>
        /// <param name="width">The width of the maze</param>
        /// <param name="height">The height of the maze</param>
        /// <returns></returns>
        private List<Point> getNeighbours(Cell[,] arr, Cell cell, int width, int height)
        {
            Point temp = cell.Position;
            List<Point> availablePlaces = new List<Point>();

            // Left
            temp.X = cell.Position.X - 1;
            if (temp.X >= 0 && this.allWallsIntact(arr, arr[temp.Y, temp.X]))
            {
                availablePlaces.Add(temp);
            }
            // Right
            temp.X = cell.Position.X + 1;
            if (temp.X < width && this.allWallsIntact(arr, arr[temp.Y, temp.X]))
            {
                availablePlaces.Add(temp);
            }

            // Up
            temp.X = cell.Position.X;
            temp.Y = cell.Position.Y - 1;
            if (temp.Y >= 0 && this.allWallsIntact(arr, arr[temp.Y, temp.X]))
            {
                availablePlaces.Add(temp);
            }
            // Down
            temp.Y = cell.Position.Y + 1;
            if (temp.Y < height && this.allWallsIntact(arr, arr[temp.Y, temp.X]))
            {
                availablePlaces.Add(temp);
            }
            return availablePlaces;
        }
예제 #8
0
        /// <summary>
        /// Solves a maze with recursive backtracking DFS - 
        /// DON'T USE! IT IS FOR DEMONSTRATING PURPOSES ONLY!
        /// </summary>
        /// <param name="start">The start of the maze cell</param>
        /// <param name="end">The end of the maze cell</param>
        /// <returns>returrns true if the path is found</returns>
        private unsafe bool depthFirstSearchSolve(Cell *st, ref Cell end)
        {
            // base condition
            if (st->Position == end.Position)
            {
                // make it visited in order to be drawed with green
                this.maze[st->Position.Y, st->Position.X].Visited = true;
                // add end point to the foundPath
                this.foundPath.Add(*st);
                return true;
            }

            // has been visited alread, return
            if (this.maze[st->Position.Y, st->Position.X].Visited)
                return false;

            // for the graphics
            this.currentSolvePos = st->Position;
            // used to slow the process
            Thread.SpinWait(this.Sleep * sleepPeriod);

            // mark as visited
            this.maze[st->Position.Y, st->Position.X].Visited = true;

            // Check every neighbor cell
            // If it exists (not outside the maze bounds)
            // and if there is no wall between start and it
            // recursive call this method with it
            // if it returns true, add the current start to foundPath and return true too
            // else complete

            // Left
            if (st->Position.X - 1 >= 0 && !this.maze[st->Position.Y, st->Position.X - 1].RightWall)
            {
                this.maze[st->Position.Y, st->Position.X].Path = Cell.Paths.Left;
                fixed (Cell *ptr = &this.maze[st->Position.Y, st->Position.X - 1])
                {
                    if (this.depthFirstSearchSolve(ptr, ref end))
                    {
                        this.foundPath.Add(*st);
                        return true;
                    }
                }
            }
            // for the graphics
            this.currentSolvePos = st->Position;
            // used to slow the process
            Thread.SpinWait(this.Sleep * sleepPeriod);
            // Right
            if (st->Position.X + 1 < this.width && !this.maze[st->Position.Y, st->Position.X + 1].LeftWall)
            {
                this.maze[st->Position.Y, st->Position.X].Path = Cell.Paths.Right;
                fixed (Cell* ptr = &this.maze[st->Position.Y, st->Position.X + 1])
                {
                    if (this.depthFirstSearchSolve(ptr, ref end))
                    {
                        this.foundPath.Add(*st);
                        return true;
                    }
                }
            }
            // for the graphics
            this.currentSolvePos = st->Position;
            // used to slow the process
            Thread.SpinWait(this.Sleep * sleepPeriod);

            // Up
            if (st->Position.Y - 1 >= 0 && !this.maze[st->Position.Y - 1, st->Position.X].DownWall)
            {
                this.maze[st->Position.Y, st->Position.X].Path = Cell.Paths.Up;
                fixed (Cell* ptr = &this.maze[st->Position.Y - 1, st->Position.X])
                {
                    if (this.depthFirstSearchSolve(ptr, ref end))
                    {
                        this.foundPath.Add(*st);
                        return true;
                    }
                }
            }

            // for the graphics
            this.currentSolvePos = st->Position;
            // used to slow the process
            Thread.SpinWait(this.Sleep * sleepPeriod);

            // Down
            if (st->Position.Y + 1 < this.height && !this.maze[st->Position.Y + 1, st->Position.X].UpWall)
            {
                this.maze[st->Position.Y, st->Position.X].Path = Cell.Paths.Down;
                fixed (Cell* ptr = &this.maze[st->Position.Y + 1, st->Position.X])
                {
                    if (this.depthFirstSearchSolve(ptr, ref end))
                    {
                        this.foundPath.Add(*st);
                        return true;
                    }
                }
            }
            this.maze[st->Position.Y, st->Position.X].Path = Cell.Paths.None;
            return false;
        }
예제 #9
0
        /// <summary>
        /// Generate a maze with the Depth-First Search approach
        /// </summary>
        /// <param name="arr">the array of cells</param>
        /// <param name="width">A width for the maze</param>
        /// <param name="height">A height for the maze</param>
        private void depthFirstSearchMazeGeneration(Cell[,] arr, int width, int height)
        {
            Stack<Cell> stack = new Stack<Cell>();
            Random random = new Random();

            Cell location = arr[this.random.Next(height), this.random.Next(width)];
            stack.Push(location);

            while (stack.Count > 0)
            {
                List<Point> neighbours = this.getNeighbours(arr, location, width, height);
                if (neighbours.Count > 0)
                {
                    Point temp = neighbours[random.Next(neighbours.Count)];

                    this.currentGenerateLocation = temp;

                    this.knockWall(arr, ref location, ref arr[temp.Y, temp.X]);

                    stack.Push(location);
                    location = arr[temp.Y, temp.X];
                }
                else
                {
                    location = stack.Pop();
                }

                Thread.SpinWait(this.Sleep * sleepPeriod);
            }

            this.makeMazeBeginEnd(this.maze);
        }
예제 #10
0
 /// <summary>
 /// Determines whether a particular cell has all its walls intact
 /// </summary>
 /// <param name="arr">the maze array</param>
 /// <param name="cell">The cell to check</param>
 /// <returns></returns>
 private bool allWallsIntact(Cell[,] arr, Cell cell)
 {
     for (int i = 0; i < 4; i++)
     {
         if (!arr[cell.Position.Y, cell.Position.X][i])
         {
             return false;
         }
     }
     return true;
 }
예제 #11
0
 /// <summary>
 /// Used to reset all cells
 /// </summary>
 /// <param name="arr">The maze array to reset elements</param>
 private void unvisitAll(Cell[,] arr)
 {
     for (int i = 0; i < this.maze.GetLength(0); i++)
     {
         for (int j = 0; j < this.maze.GetLength(1); j++)
         {
             arr[i, j].Visited = false;
             arr[i, j].Path = Cell.Paths.None;
         }
     }
 }