//Connect all completely unconnected points to a connected point, making sure all cells are reachable. void ConnectUnconnectedPoints(LevelBlockRequirements[,] basicGrid) { int hBlocks = Width / BlockWidth, vBlocks = Height / BlockHeight; //Store which blocks weren't connected. bool[,] isConnected = new bool[hBlocks, vBlocks]; List<Point> unconnectedPoints = new List<Point>(); for (int i = 0; i < hBlocks; i++) { for (int j = 0; j < vBlocks; j++) { isConnected[i, j] = ! basicGrid[i, j].IsOnlyWalls(); if (! isConnected[i, j]) unconnectedPoints.Add(new Point(i, j)); } } bool connectedAnythingThisRound; while (unconnectedPoints.Count > 0) { connectedAnythingThisRound = false; List<Point> removedUnconnectedPoints = new List<Point>(); //A list to store points we remove as changing a list during foreach is impossible unconnectedPoints.Shuffle(); //Shuffle the points so that they connect in a more random way. foreach (Point point in unconnectedPoints) { int i = point.X, j = point.Y; //Temporary store the x and y of this point. List<Point> possiblePoints = new List<Point>(); //Points to connect to. if (i > 0 && isConnected[i - 1, j]) possiblePoints.Add(new Point(i - 1, j)); if (i < hBlocks - 1 && isConnected[i + 1, j]) possiblePoints.Add(new Point(i + 1, j)); if (j > 0 && isConnected[i, j - 1]) possiblePoints.Add(new Point(i, j - 1)); if (j < vBlocks - 1 && isConnected[i, j + 1]) possiblePoints.Add(new Point(i, j + 1)); if (possiblePoints.Count != 0) { //Connect this point to a random other one. ConnectPoints(basicGrid, new List<Point>() { point, possiblePoints.GetRandomItem() }); isConnected[i, j] = true; //Mark this point as connected. connectedAnythingThisRound = true; removedUnconnectedPoints.Add(point); } } foreach (Point point in removedUnconnectedPoints) unconnectedPoints.Remove(point); //Give up if we couldn't connect anything at all. if (! connectedAnythingThisRound) break; } }
//Connect any number of points on the level grid. void ConnectPoints(LevelBlockRequirements[,] basicGrid, List<Point> points) { if (points.Count == 0) return; //Choose a random point and connect that to each other point. //This automatically guarantees that each point is connected to each other point, as //you can always travel to the first point and then to the target point. Point point = points.GetRandomItem(); for (int i = 0; i < points.Count; i++) { Point otherPoint = points[i]; if (point == otherPoint) continue; //Check how far we have to travel Point distanceDifference = new Point(otherPoint.X - point.X, otherPoint.Y - point.Y); //And store the directions we have to take into a RandomCollection of directions RandomCollection<Direction> directionsToTravel = new RandomCollection<Direction>(); if (distanceDifference.X < 0) directionsToTravel.Add(Direction.Left, -distanceDifference.X); if (distanceDifference.X > 0) directionsToTravel.Add(Direction.Right, distanceDifference.X); if (distanceDifference.Y < 0) directionsToTravel.Add(Direction.Up, -distanceDifference.Y); if (distanceDifference.Y > 0) directionsToTravel.Add(Direction.Down, distanceDifference.Y); //Then actually travel from the first point to the second one. Point position = point; while (directionsToTravel.Count != 0) { switch (directionsToTravel.Take()) { case Direction.Left: basicGrid[position.X, position.Y].LeftSideType = SideType.Exit; position.X -= 1; basicGrid[position.X, position.Y].RightSideType = SideType.Exit; break; case Direction.Right: basicGrid[position.X, position.Y].RightSideType = SideType.Exit; position.X += 1; basicGrid[position.X, position.Y].LeftSideType = SideType.Exit; break; case Direction.Up: basicGrid[position.X, position.Y].TopSideType = SideType.Exit; position.Y -= 1; basicGrid[position.X, position.Y].BottomSideType = SideType.Exit; break; case Direction.Down: basicGrid[position.X, position.Y].BottomSideType = SideType.Exit; position.Y += 1; basicGrid[position.X, position.Y].TopSideType = SideType.Exit; break; } } } }