Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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);
        }
        static void testAll()
        {
            (int, int)mazeDimenations = (Console.WindowWidth - 8, Console.WindowHeight - 5);

            Console.ForegroundColor = ConsoleColor.Green;
            Console.Write("generating maze...");

            var mazes = new HashSet <HashSet <Point> >();

            var thread = new Thread(
                () =>
            {
                mazes.Add(BoruvkasAlgorithm.generateMaze(mazeDimenations.Item1, mazeDimenations.Item2));
            });
            var thread2 = new Thread(
                () =>
            {
                mazes.Add(PrimsAlgorithm.generateMaze(mazeDimenations.Item1, mazeDimenations.Item2));
            });
            var thread3 = new Thread(
                () =>
            {
                mazes.Add(KruskalsAlgorithm.generateMaze(mazeDimenations.Item1, mazeDimenations.Item2));
            });
            var thread4 = new Thread(
                () =>
            {
                mazes.Add(RecursiveBacktrackerAlgorithm.generateMaze(mazeDimenations.Item1, mazeDimenations.Item2));
            });
            var thread5 = new Thread(
                () =>
            {
                mazes.Add(HuntandKill.generateMaze(mazeDimenations.Item1, mazeDimenations.Item2));
            });

            var threadList = new List <Thread>
            {
                thread,
                thread2,
                thread3,
                thread4,
                thread5
            };

            foreach (var t in threadList)
            {
                t.Start();
            }
            ;


            Console.Clear();

            if (thread.IsAlive | thread2.IsAlive | thread3.IsAlive | thread4.IsAlive)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write("generating mazes...");
            }

            while (thread.IsAlive | thread2.IsAlive | thread3.IsAlive | thread4.IsAlive)
            {
                //if a maze is still being generated then don't go onto the code below
            }

            Console.SetCursorPosition(0, 0);
            Console.ForegroundColor = ConsoleColor.Red;
            Console.Write("finished generating mazes");

            foreach (HashSet <Point> maze in mazes)
            {
                setBothColours(ConsoleColor.White);
                printMaze(maze);
                Depth_first_Search.solveMaze(maze);
                Thread.Sleep(800);

                resetWindow();
            }
        }
        /// <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 availableVertices = RecursiveBacktrackerAlgorithm.ReturnDict(width, height).Keys.ToList();

            var maze = new HashSet <Point>();

            var usedVertices = new HashSet <Point>();

            var weights = BoruvkasAlgorithm.returnEdgeWeights(width, height, availableVertices);
            var V       = BoruvkasAlgorithm.assignInitialSetNumbers(availableVertices);

            var mazeEntry = new Point(5, 2);

            maze.Add(mazeEntry);

            //pick random edge/lowest weight edge
            //combine set of connected trees IF NOT IN THE SAME SET
            //remove edge
            //repeat

            while (!BoruvkasAlgorithm.singleSet(V))
            {
                foreach (Point v in availableVertices)
                {
                    var lowestWeightEdge = BoruvkasAlgorithm.returnLowestWeightEdge(weights);

                    if (lowestWeightEdge.IsEmpty)
                    {
                        continue;
                    }

                    var connectedVertices = BoruvkasAlgorithm.returnNodes(availableVertices, lowestWeightEdge);

                    var setNumber1 = V[connectedVertices.First()];
                    var setNumber2 = V[connectedVertices.Last()];


                    if (setNumber1 != setNumber2)
                    {
                        V = BoruvkasAlgorithm.assignSetNumber(V, setNumber1, setNumber2);

                        weights.Remove(lowestWeightEdge);

                        if (!maze.Contains(connectedVertices.First()))
                        {
                            maze.Add(connectedVertices.First());
                        }
                        if (!maze.Contains(connectedVertices.Last()))
                        {
                            maze.Add(connectedVertices.Last());
                        }
                        maze.Add(lowestWeightEdge);
                    }
                    weights.Remove(lowestWeightEdge);
                }
            }

            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);
        }