/// <summary> /// Returns an enumerator that solves the maze by creating a solution path using the WallFollower Algorithm /// </summary> /// <param name="service"></param> public override IEnumerator SolveMazeRoutine(MazeSolvingService service) { //set starting point MazeCell walker = service.EntranceCell; walker.MarkAsPartOfSolution(); //store direction for manipulation Vector2Int direction = Vector2Int.left; //loop until exit has been reached by the walker MazeCell exitCell = service.ExitCell; while (walker != exitCell) { //try first walking left and then walking forward. Rotate right if both fail MazeCell nextCellInPath = null; if (service.GetNextCellInPathRelative(walker, GetValueRotatedLeft(direction), ref nextCellInPath)) { //if we can walk left, first rotate left Rotate(ANGLE_LEFT, ref direction); //make the next cell in the path and the passage towards it part of the solution nextCellInPath.MarkAsPartOfSolution(); nextCellInPath.MarkWallAsPartOfSolution(walker); walker.MarkWallAsPartOfSolution(nextCellInPath); } else if (service.GetNextCellInPathRelative(walker, direction, ref nextCellInPath)) { //make the next cell in the path and the passage towards it part of the solution nextCellInPath.MarkAsPartOfSolution(); nextCellInPath.MarkWallAsPartOfSolution(walker); walker.MarkWallAsPartOfSolution(nextCellInPath); } else { //rotate right to look for a new way to walk left or forward Rotate(ANGLE_RIGHT, ref direction); } if (nextCellInPath != null) { //if the next cell in the path was found, we can walk on from it walker = nextCellInPath; if (service.DebugMode) { walker.SetDirectionArrow(direction); walker.ShowDirectionArrow(true); } } yield return(null); } CompletedRoutine(); }
/// <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 solves the maze by creating a solution path using the DeadEndFilling Algorithm /// </summary> /// <param name="service"></param> public override IEnumerator SolveMazeRoutine(MazeSolvingService service) { //fill dead ends of the maze until junktions are found IEnumerable <MazeCell> deadEnds = service.Cells.Cast <MazeCell>().Where(cell => cell.IsDeadEnd); foreach (MazeCell deadEnd in deadEnds) { yield return(CheckUntilJunctionRoutine(deadEnd, service)); } //start walking from the entrance MazeCell walker = service.EntranceCell; walker.MarkAsPartOfSolution(); yield return(null); //loop until the walker is at the exit MazeCell exitCell = service.ExitCell; while (walker != exitCell) { //get the next cell that is on current path List <MazeCell> nextCellsInPath = service.GetNextCellsInPath(walker); if (nextCellsInPath.Count == 1) { //make the cell part of the path solution MazeCell nextCellInPath = nextCellsInPath[0]; nextCellInPath.MarkAsPartOfSolution(); //mark its walls as part of the solution aswell walker.MarkWallAsPartOfSolution(nextCellInPath); nextCellInPath.MarkWallAsPartOfSolution(walker); //the next cell in the path is now the walker walker = nextCellInPath; } else { throw new System.InvalidOperationException($"The solution path could not be created from {walker.name} with {nextCellsInPath.Count} next cells in path :: this is unintended behaviour!"); } yield return(null); } CompletedRoutine(); }