/// <summary> /// Returns an enumerator that creates a maze by linking cells using the HuntAndKill algorithm /// </summary> /// <param name="service"></param> /// <returns></returns> public override IEnumerator CreateMazeRoutine(MazeGenerationService service) { //create data structures necessary for algorithm to work List <MazeCell> visited = new List <MazeCell>(); //set starting point MazeCell walker = service.RootCell; walker.MarkAsVisited(); visited.Add(walker); //loop untill all cells have been visited long totalCells = service.Cells.LongLength; while (visited.Count != totalCells) { //check if the current walker has unvisited neighbours List <MazeCell> unvisitedNeighbours = service.GetUnVisitedNeighbours(walker); if (unvisitedNeighbours.Count > 0) { //pick a random unvisited neighbour and mark it as visited MazeCell randomUnvisitedNeighbour = unvisitedNeighbours[Random.Range(0, unvisitedNeighbours.Count)]; randomUnvisitedNeighbour.MarkAsVisited(); visited.Add(randomUnvisitedNeighbour); //create passage between cell and neighbour walker.CreatePassage(randomUnvisitedNeighbour); randomUnvisitedNeighbour.CreatePassage(walker); //the random unvisited neighbour is now the walker walker = randomUnvisitedNeighbour; } else { //scan the grid for a hunted cell that is unvisited but has visited neighbours and mark it as visited MazeCell huntedCell = GetRandomUnVisitedCellWithVisitedNeighbours(service); huntedCell.MarkAsVisited(); visited.Add(huntedCell); //fetch one of its visited neighbours and link it with the hunted cell List <MazeCell> visitedNeighbours = service.GetVisitedNeighbours(huntedCell); MazeCell randomVisitedNeighbour = visitedNeighbours[Random.Range(0, visitedNeighbours.Count)]; huntedCell.CreatePassage(randomVisitedNeighbour); randomVisitedNeighbour.CreatePassage(huntedCell); //the hunted cell is now the walker walker = huntedCell; } walker.ShowAsStep(true); yield return(null); walker.ShowAsStep(false); } CompletedRoutine(); }
/// <summary> /// Returns an enumerator that creates a maze by linking cells using the recursive backtracking algorithm /// </summary> /// <param name="service"></param> /// <returns></returns> public override IEnumerator CreateMazeRoutine(MazeGenerationService service) { //create data structures necessary for algorithm to work Stack <MazeCell> stack = new Stack <MazeCell>(); List <MazeCell> visited = new List <MazeCell>(); //set starting point MazeCell startCell = service.RootCell; startCell.MarkAsVisited(); visited.Add(startCell); stack.Push(startCell); //loop until all cells have been visited long totalCells = service.Cells.LongLength; while (visited.Count != totalCells) { //pick the cell to branch from, from the top of the stack and retreive its neighbours MazeCell newest = stack.Peek(); List <MazeCell> neighbours = service.GetUnVisitedNeighbours(newest); if (neighbours.Count > 0) { //pick a random neighbour from the list MazeCell neighbour = neighbours[Random.Range(0, neighbours.Count)]; //set it as visited and add it to the visited list neighbour.MarkAsVisited(); visited.Add(neighbour); //create passage between newest and neighbour newest.CreatePassage(neighbour); neighbour.CreatePassage(newest); //push the neighbour to the stack stack.Push(neighbour); } else { //if no unvisited neighbours are available, backtrack by popping the stack stack.Pop(); } newest.ShowAsStep(true); yield return(null); newest.ShowAsStep(false); } CompletedRoutine(); }
/// <summary> /// Returns an Enumerator that creates a maze by linking cells using the growing tree algorithm its prim version /// </summary> /// <param name="service"></param> public override IEnumerator CreateMazeRoutine(MazeGenerationService service) { //create data structures necessary for algorithm to work List <MazeCell> bag = new List <MazeCell>(); List <MazeCell> visited = new List <MazeCell>(); //set starting point MazeCell startPoint = service.RootCell; startPoint.MarkAsVisited(); visited.Add(startPoint); bag.Add(startPoint); //loop until all cells have been visited long totalCells = service.Cells.LongLength; while (visited.Count != totalCells) { //pick a random cell from the bag and check if it has unvisited neighbours MazeCell randomCell = bag[Random.Range(0, bag.Count)]; List <MazeCell> unvisitedNeighbours = service.GetUnVisitedNeighbours(randomCell); if (unvisitedNeighbours.Count > 0) { //pick a random unvisited neighbour and mark it as visited MazeCell randomUnvisitedNeighbour = unvisitedNeighbours[Random.Range(0, unvisitedNeighbours.Count)]; randomUnvisitedNeighbour.MarkAsVisited(); visited.Add(randomUnvisitedNeighbour); //create passage between cell and neighbour randomCell.CreatePassage(randomUnvisitedNeighbour); randomUnvisitedNeighbour.CreatePassage(randomCell); //add the random unvisited neighbour to the bag bag.Add(randomUnvisitedNeighbour); } else { //if the cell doesn't have any unvisited neighbours, remove it from the bag bag.Remove(randomCell); } randomCell.ShowAsStep(true); yield return(null); randomCell.ShowAsStep(false); } CompletedRoutine(); }
/// <summary> /// Returns an enumerator that creates a maze by linking cells using prim's algorithm /// </summary> /// <param name="service"></param> /// <returns></returns> public override IEnumerator CreateMazeRoutine(MazeGenerationService service) { //create data structures necessary for algorithm to work MazeCell[] cells = service.Cells.Cast <MazeCell>().ToArray(); List <MazeCell> frontier = new List <MazeCell>(); //set starting point MazeCell startCell = service.RootCell; startCell.MarkAsVisited(); //add neighbours of starting cell to frontier frontier.AddRange(service.GetNeighbours(startCell)); while (frontier.Count != 0) { //pick a random frontier cell, mark it as visited and remove it from the frontier MazeCell randomFrontierCell = frontier[Random.Range(0, frontier.Count)]; randomFrontierCell.MarkAsVisited(); frontier.Remove(randomFrontierCell); //pick a random visited neighbour of it and link it with it List <MazeCell> visitedNeighbours = service.GetVisitedNeighbours(randomFrontierCell); if (visitedNeighbours.Count > 0) { MazeCell randomVisitedNeighbour = visitedNeighbours[Random.Range(0, visitedNeighbours.Count)]; randomFrontierCell.CreatePassage(randomVisitedNeighbour); randomVisitedNeighbour.CreatePassage(randomFrontierCell); } //add unvisited neighbours of it to the frontier if they aren't already in it List <MazeCell> unvisitedNeighbours = service.GetUnVisitedNeighbours(randomFrontierCell); foreach (MazeCell cell in unvisitedNeighbours) { if (!frontier.Contains(cell)) { frontier.Add(cell); } } randomFrontierCell.ShowAsStep(true); yield return(null); randomFrontierCell.ShowAsStep(false); } CompletedRoutine(); }