예제 #1
0
        /// <summary>
        /// Returns an enumerator that solves the maze by creating a solution path using the Recursive Backtracking Algorithm
        /// </summary>
        /// <param name="service"></param>
        public override IEnumerator SolveMazeRoutine(MazeSolvingService service)
        {
            //create datastructues necessary for algorithm to work
            Stack <MazeCell> stack = new Stack <MazeCell>();

            //set starting point and store exit for loop condition
            MazeCell exitCell = service.ExitCell;
            MazeCell entrance = service.EntranceCell;

            entrance.MarkAsPartOfSolution();
            stack.Push(entrance);

            //loop until the next cell in path is the exit
            MazeCell nextCellInPath = null;

            while (nextCellInPath != exitCell)
            {
                //look at the cell at the top of the stack and get the next cells in the path relative to it
                MazeCell        cell            = stack.Peek();
                List <MazeCell> cellsNextInPath = service.GetNextCellsInPath(cell);

                //check if the path is a dead end or not
                if (cellsNextInPath.Count > 0)
                {
                    //fetch a random cell that is next in the path and mark it as part of the solution
                    nextCellInPath = cellsNextInPath[Random.Range(0, cellsNextInPath.Count)];
                    nextCellInPath.MarkAsPartOfSolution();

                    //mark the walls as part of the solution aswell
                    cell.MarkWallAsPartOfSolution(nextCellInPath);
                    nextCellInPath.MarkWallAsPartOfSolution(cell);

                    //push the next cell to the stack
                    stack.Push(nextCellInPath);
                }
                else
                {
                    //mark the dead end and its broken walls as checked, so not part of the solution anymore
                    cell.MarkAsChecked();
                    cell.MarkBrokenWallsAsChecked();

                    //pop the stack to backtrack
                    stack.Pop();
                }

                yield return(null);
            }

            CompletedRoutine();
        }
        /// <summary>
        /// Returns an enumerator that marks the maze as checked from given walker cell until a junction is met
        /// </summary>
        /// <param name="walker"></param>
        /// <param name="service"></param>
        /// <returns></returns>
        private IEnumerator CheckUntilJunctionRoutine(MazeCell walker, MazeSolvingService service)
        {
            walker.MarkAsChecked();
            yield return(null);

            //loop until a junction is found and is borken out of the loop
            while (true)
            {
                //get the next cell in the current path
                List <MazeCell> cellsNextInPath = service.GetNextCellsInPath(walker);
                if (cellsNextInPath.Count == 1)
                {
                    //save it is a junction
                    MazeCell nextCellInPath = cellsNextInPath[0];
                    bool     isJunction     = nextCellInPath.IsJunction;

                    //mark the walls as checked
                    walker.MarkWallAsChecked(nextCellInPath);
                    nextCellInPath.MarkWallAsChecked(walker);

                    if (isJunction)
                    {
                        //if the cell was a junction, break out of the loop
                        break;
                    }
                    else
                    {
                        //if the cell wasn't a junction, mark the cell as checked and continue from it
                        nextCellInPath.MarkAsChecked();
                        walker = nextCellInPath;
                    }
                }
                else
                {
                    throw new System.InvalidOperationException($"Filling in until junktion failed :: there should be one next cell in {walker}'s path each time");
                }

                yield return(null);
            }
        }