public static HashSet <Point> generateMaze(int width, int height) { var V = new HashSet <Point>(); var discovered = RecursiveBacktrackerAlgorithm.ReturnDict(width, height); var maze = new HashSet <Point>(); var weights = returnWeights(discovered.Keys.ToList()); var startV = new Point(5, 3); var currentV = startV; discovered[startV] = true; var r = new Random(); var mazeEntry = new Point(5, 2); maze.Add(mazeEntry); maze.Add(currentV); while (true) { var availableVertices = Program.returnUnvisitedNeighbours(discovered, currentV); foreach (var vertex in availableVertices.Where(vertex => !V.Contains(vertex))) { V.Add(vertex); } if (V.Count == 0) { break; } var lowestWeightVertex = ExtractMinV(V, weights); var visitedNeighbours = returnVisitedNeighbours(discovered, lowestWeightVertex); var newVertex = visitedNeighbours[r.Next(visitedNeighbours.Count)]; var wallV = RecursiveBacktrackerAlgorithm.pointMidPoint(newVertex, lowestWeightVertex); maze.Add(wallV); maze.Add(lowestWeightVertex); currentV = lowestWeightVertex; V.Remove(currentV); discovered[currentV] = true; } var mazeExit = RecursiveBacktrackerAlgorithm.returnExit(width, height); maze.Add(mazeExit); return(maze); }
public static HashSet <Point> generateMaze(int width, int height) { var startV = new Point(5, 3); var currentV = startV; var prev = startV; var maze = new HashSet <Point> { new Point(5, 2), currentV }; var r = new Random(); var visited = RecursiveBacktrackerAlgorithm.ReturnDict(width, height); Program.setBothColours(ConsoleColor.White); visited[currentV] = true; while (unvisitedVertices(visited)) { var surroundingVertices = returnNeighbours(visited, currentV); var temporaryVertex = surroundingVertices[r.Next(surroundingVertices.Count)]; if (!visited[temporaryVertex]) { var wallV = RecursiveBacktrackerAlgorithm.pointMidPoint(currentV, temporaryVertex); visited[temporaryVertex] = true; maze.Add(wallV); maze.Add(temporaryVertex); } currentV = temporaryVertex; } var mazeExit = RecursiveBacktrackerAlgorithm.returnExit(width, height); maze.Add(mazeExit); return(maze); }
/// <summary> /// generates a hamiltonian graph which contains every vertex in the maze /// pseudocode: /// while there are unvisited positions: /// if there are unvisited adjacent vertices /// perform a non overlapping random walk /// else /// pick a random adjacent vertex that isn't connected to the trapped point /// connect to the random vertex, named the target vertex /// indentify the two adjacent vertices that are next to the target vertex /// run depth first search from one of the two adjacent vertices until the stack is empty or until the trapped point is reached /// if the trapped point is reached then remove the vertex that connected it /// make the current vertex the vertex adjacent to the vertex that was just removed that isn't the target vertex /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <returns> /// Returns a hashset which contains points that are the maze /// </returns> //todo add scoring to the random vertex walk in order to improve efficiency, need to fix start/endpoint thing public static HashSet <Point> generateMaze(int width, int height) { var startV = new Point(5, 3); var endV = new Point(9, 3); var currentV = startV; var visited = RecursiveBacktrackerAlgorithm.ReturnDict(width, height); var maze = new HashSet <Point>(); visited[startV] = true; maze.Add(startV); var r = new Random(); Program.setBothColours(ConsoleColor.White); Program.printPoint(currentV); while (true) { var availableVertices = Program.returnUnvisitedNeighbours(visited, currentV); if (availableVertices.Count > 0) { Program.setBothColours(ConsoleColor.White); var temporaryV = availableVertices[r.Next(availableVertices.Count)]; visited[temporaryV] = true; var wallV = RecursiveBacktrackerAlgorithm.pointMidPoint(currentV, temporaryV); maze.Add(wallV); maze.Add(temporaryV); Program.printPoint(wallV); Program.printPoint(temporaryV); currentV = temporaryV; } else { Program.setBothColours(ConsoleColor.White); var endPoint = currentV; Program.printPoint(endPoint); //end point is selected as the current as it has no neighbours //all surrounding points, doesnt take into account the maze at all var neighbours = returnAdjacentVertices(endPoint); //the valid available neighbouring vertices var validChoices = neighbours.Where(potentialVertex => !isConnected(maze, endPoint, potentialVertex) & visited.ContainsKey(potentialVertex)).ToList(); //chooses a random vertex from the available surrounding vertices var targetVertex = validChoices[r.Next(validChoices.Count)]; //draws the edge and the target vertices in green var wall = RecursiveBacktrackerAlgorithm.pointMidPoint(targetVertex, endPoint); Program.printPoint(wall); Program.printPoint(targetVertex); (Point, Point)verticesToAdd = (wall, targetVertex); //gets new surrounding vertices with the target vertex as the centre neighbours = returnVertices(targetVertex); //adjacent nodes from the target vertex; the edges that connect the target vertex to the adjacent vertices var connectedVertices = neighbours.Where(potentialVertex => maze.Contains(potentialVertex)).ToList(); //run depth first search to see if there is a loop in the maze coming from one of the adjacent vertices //sets the root equal to come of the adjacent vertices var root = connectedVertices.First(); //create a temporary maze that doesnt include the target node so that the search is forced down a single path var tempMaze = maze; tempMaze.Remove(targetVertex); //create a visited dictionary var d = maze.ToDictionary(v => v, v => false); //return the depth first search result var isconnected = connectedVertex(tempMaze, root, endPoint, d); var pointToBeRemoved = root; //deciding which adjacent vertex to remove if (!isconnected) { pointToBeRemoved = connectedVertices.Last(); } //removing the vertex Program.setBothColours(ConsoleColor.Black); Program.printPoint(pointToBeRemoved); maze.Remove(pointToBeRemoved); //get the new point to begin the random walk from neighbours = Program.returnAdjacentVertices(maze, pointToBeRemoved); foreach (var v in neighbours.Where(v => !v.Equals(targetVertex))) { currentV = v; break; } visited[currentV] = true; maze.Add(verticesToAdd.Item1); maze.Add(verticesToAdd.Item2); } if (currentV.Equals(endV)) { if (!unvisitedVertices(visited)) { break; } } } var startAndEnd = returnStartAndGoal(maze); maze = removeDuplicate(maze); maze.Reverse(); maze.Add(startAndEnd.Item1); maze.Reverse(); maze.Add(startAndEnd.Item2); Program.setBothColours(ConsoleColor.Green); Program.printPoint(maze.First()); Program.setBothColours(ConsoleColor.Red); Program.printPoint(maze.Last()); Console.ReadKey(); return(maze); }
private static bool isConnected(HashSet <Point> maze, Point currentPoint, Point newPoint) => maze.Contains(RecursiveBacktrackerAlgorithm.pointMidPoint(currentPoint, newPoint));
public static HashSet <Point> generateMaze(int width, int height) { var startV = new Point(5, 3); var currentV = startV; var visited = RecursiveBacktrackerAlgorithm.ReturnDict(width, height); var maze = new HashSet <Point>(); var mazeEntry = new Point(5, 2); maze.Add(mazeEntry); visited[startV] = true; maze.Add(startV); var r = new Random(); while (unvisitedVertices(visited)) { var availableVertices = Program.returnUnvisitedNeighbours(visited, currentV); if (availableVertices.Count > 0) { var temporaryV = availableVertices[r.Next(availableVertices.Count)]; visited[temporaryV] = true; var wallV = RecursiveBacktrackerAlgorithm.pointMidPoint(currentV, temporaryV); maze.Add(wallV); maze.Add(temporaryV); currentV = temporaryV; } else { foreach (Point v in visited.Keys) { var visitedNeighbours = PrimsAlgorithm.returnVisitedNeighbours(visited, v); if (visitedNeighbours.Count == 0 || visited[v]) { continue; } else { var newVertex = visitedNeighbours[r.Next(visitedNeighbours.Count)]; var wallV = RecursiveBacktrackerAlgorithm.pointMidPoint(newVertex, v); maze.Add(wallV); maze.Add(v); currentV = v; break; } } visited[currentV] = true; } } var mazeExit = RecursiveBacktrackerAlgorithm.returnExit(width, height); maze.Add(mazeExit); return(maze); }
public static HashSet <Point> generateMaze(int width, int height) { var r = new Random(); var visited = RecursiveBacktrackerAlgorithm.ReturnDict(width, height); var cameFrom = resetCameFrom(visited); //Choose any vertex at random and add it to the UST. //Select any vertex that is not already in the UST and perform a random walk until you encounter a vertex that is in the UST. //Add the vertices and edges touched in the random walk to the UST. //Repeat 2 and 3 until all vertices have been added to the UST. var UST = new HashSet <Point>(); var currentV = visited.Keys.ToList()[r.Next(visited.Keys.Count)]; var prev = currentV; visited[currentV] = true; var maze = new HashSet <Point> { new Point(5, 2), currentV }; UST.Add(currentV); currentV = getUnvisitedVertex(visited); var firstCell = currentV; while (unvisitedVertices(visited)) { var surroundingVertices = returnNeighbours(visited, currentV); var temporaryVertex = surroundingVertices[r.Next(surroundingVertices.Count)]; cameFrom[prev] = temporaryVertex; if (UST.Contains(temporaryVertex)) { temporaryVertex = firstCell; var verticesToBeAdded = new List <Point> { temporaryVertex }; do { if (!cameFrom.ContainsKey(temporaryVertex)) { break; } temporaryVertex = cameFrom[temporaryVertex]; verticesToBeAdded.Add(temporaryVertex); } while (!UST.Contains(temporaryVertex)); for (int i = 0; i < verticesToBeAdded.Count - 1; i++) { var v1 = verticesToBeAdded[i]; var v2 = verticesToBeAdded[i + 1]; var wall = RecursiveBacktrackerAlgorithm.pointMidPoint(v1, v2); visited[v1] = true; maze.Add(wall); maze.Add(v1); UST.Add(v1); } cameFrom = resetCameFrom(visited); if (!unvisitedVertices(visited)) { break; } currentV = getUnvisitedVertex(visited); prev = currentV; firstCell = currentV; } else { currentV = temporaryVertex; cameFrom[prev] = currentV; prev = currentV; } } var mazeExit = RecursiveBacktrackerAlgorithm.returnExit(width, height); maze.Add(mazeExit); return(maze); }