/// <summary> /// Recursive backtracking maze generation algorithm. /// </summary> /// <param name="currentPos"></param> private void CarvePassage(Point currentPos) { this.Board[currentPos.Y, currentPos.X].Point = new Point(currentPos.X, currentPos.Y); this.Board[currentPos.Y, currentPos.X].Visited = true; this.Board[currentPos.Y, currentPos.X].position_in_iteration = ++iterationcount; List <Direction> validDirections = GetAllDirections(); ValidateDirections(currentPos, validDirections); //If there is no valid direction we have found a dead end. if (validDirections.Count == 0) { this.Board[currentPos.Y, currentPos.X].isdeadend = true; Points.Add(new Tuple <Cell, Direction>(this.Board[currentPos.Y, currentPos.X], Direction.Invalid)); } while (validDirections.Count > 0) { Direction rndDirection = Direction.Invalid; if (validDirections.Count > 1) { rndDirection = validDirections[rng.Next(validDirections.Count)]; } else if (validDirections.Count == 1) { rndDirection = validDirections[0]; } this.Board[currentPos.Y, currentPos.X].visited_count = ++this.Board[currentPos.Y, currentPos.X].visited_count; RemoveWall(currentPos, rndDirection); validDirections.Remove(rndDirection); Point newPos = GetAdjPos(currentPos, rndDirection); Points.Add(new Tuple <Cell, Direction>(this.Board[currentPos.Y, currentPos.X], rndDirection)); statesChangeRecall.OnStatusUpdated(); Thread.Sleep(1); CarvePassage(newPos); ValidateDirections(currentPos, validDirections); } }
public void Evolve() { statesChangeRecall.IsEngineRunning = true; // algorithm Location current = null; Location start = null; Location target = null; Location error = new Location(); var openList = new List <Location>(); var closedList = new List <Location>(); for (int x = 0; x < Map.GetLength(0); x++) { for (int y = 0; y < Map.GetLength(1); y++) { switch (Map[x, y].Type) { case LocationType.START_POINT: if (start == null) { start = new Location() { X = x, Y = y, }; } else { start = error; } break; case LocationType.END_POINT: if (target == null) { target = new Location() { X = x, Y = y, }; } else { target = error; } break; case LocationType.WALL: break; default: break; } Map[x, y].Status = LocationStatus.NULL; Map[x, y].IsSlopeMove = false; Map[x, y].SlopePath = new List <Location>(); } } // if multiple start/targer found, return if (start == error || target == error || start == null || target == null) { statesChangeRecall.IsEngineRunning = false; statesChangeRecall.OnStatusUpdated(); return; } // start by adding the original position to the open list openList.Add(start); int g = 0; while (openList.Count > 0) { // get the square with the lowest F score var lowest = openList.Min(l => l.F); current = openList.First(l => l.F == lowest); // add the current square to the closed list closedList.Add(current); // show current square on the map current.Status = LocationStatus.SEARCHED; if (current.IsSlopeMove) { var lowestSlopeSquare = current.SlopePath.Min(l => l.F); var slopeSquare = current.SlopePath.First(l => l.F == lowestSlopeSquare); slopeSquare.Status = LocationStatus.SEARCHED; } statesChangeRecall.OnStatusUpdated(); System.Threading.Thread.Sleep(5); // remove it from the open list openList.Remove(current); // if we added the destination to the closed list, we've found a path if (closedList.FirstOrDefault(l => l.X == target.X && l.Y == target.Y) != null) { break; } var adjacentSquares = GetWalkableAdjacentSquares(current.X, current.Y, Map); //g++; foreach (var adjacentSquare in adjacentSquares) { // if this adjacent square is already in the closed list, ignore it if (closedList.FirstOrDefault(l => l.X == adjacentSquare.X && l.Y == adjacentSquare.Y) != null) { continue; } // if it's not in the open list... if (openList.FirstOrDefault(l => l.X == adjacentSquare.X && l.Y == adjacentSquare.Y) == null) { // compute its score, set the parent adjacentSquare.G = g + current.G + ComputeHScore(adjacentSquare.X, adjacentSquare.Y, current.X, current.Y); adjacentSquare.H = ComputeHScore(adjacentSquare.X, adjacentSquare.Y, target.X, target.Y); adjacentSquare.F = adjacentSquare.G + adjacentSquare.H; adjacentSquare.Parent = current; // and add it to the open list openList.Insert(0, adjacentSquare); } else { // test if using the current G score makes the adjacent square's F score // lower, if yes update the parent because it means it's a better path if (g + current.G + ComputeHScore(adjacentSquare.X, adjacentSquare.Y, current.X, current.Y) + adjacentSquare.H < adjacentSquare.F) { adjacentSquare.G = g + current.G + ComputeHScore(adjacentSquare.X, adjacentSquare.Y, current.X, current.Y); adjacentSquare.F = adjacentSquare.G + adjacentSquare.H; adjacentSquare.Parent = current; } } } } // Show result if (closedList.FirstOrDefault(l => l.X == target.X && l.Y == target.Y) != null) { // Path found while (current != null) { if (Map[current.X, current.Y].Type == LocationType.SPACE) { Map[current.X, current.Y].Status = LocationStatus.PATH; statesChangeRecall.OnStatusUpdated(); } current = current.Parent; System.Threading.Thread.Sleep(5); } } else { // No path found while (closedList.Count != 0) { Location l = closedList.First(); l.Status = LocationStatus.ERROR; closedList.Remove(l); statesChangeRecall.OnStatusUpdated(); System.Threading.Thread.Sleep(1); } } // end statesChangeRecall.IsEngineRunning = false; statesChangeRecall.OnStatusUpdated(); }