/// <summary> /// Find a solution to a map. /// </summary> /// <param name="map">Map to solve.</param> /// <param name="strategy">Strategy to use to solve the map.</param> /// <returns></returns> public static MapPath FindPath( Map map, ITraversalStrategy strategy, string options = null) { return new MapPath(strategy.Traverse(map, options)); }
static void Main(string[] args) { // Display help. if ((args.Length == 0) || (args[0] == "-?") || (args[0] == "/?") || (args[0].ToLower() == "help")) { OutputHelp(); return; } // Forgot to specify solution path. if (args.Length < 2) { Console.WriteLine("No destination image path specified."); return; } // Collect file paths. string sourcePath = args[0]; string outputPath = args[1]; // Optional strategy option specified. string strategyOption = null; if (args.Length > 2) strategyOption = args[2]; // Attempt to load the image. Bitmap sourceImage; try { sourceImage = new Bitmap(sourcePath); } catch (Exception) { Console.WriteLine("Source file is not a valid image format."); return; } // TODO: Allow other strategies if time allows. Map map = new Map(sourceImage); MapPath path = PathFinder.FindPath(map, Strategies.BreadthFirst, strategyOption); // No solution found. if (path == null) { Console.WriteLine("No path could be found to solve the maze."); Console.WriteLine("Are you using the correct colors?"); return; } PathFinder.OutputBitmap(path, map, outputPath); System.Console.WriteLine("Solution saved successfully to " + outputPath); }
/// <summary> /// Loads the map. /// </summary> private static void LoadMap() { _map = new Map(10, 20); _map.Close(1, 5); _map.Close(2, 5); _map.Close(3, 5); _map.Close(4, 5); _map.Close(5, 5); _map.Close(6, 5); _map.Close(7, 5); }
/// <summary> /// Save a solved map to an image file. /// </summary> /// <param name="path"></param> /// <param name="map"></param> /// <param name="outputPath"></param> public static void OutputBitmap( MapPath path, Map map, string outputPath) { // Get pixels from original map data. byte[] pixels = path.TraceOverMap(map); // Output the bitmap. string extension = Path.GetExtension(outputPath); BitmapEncoder encoder; switch (extension) { default: encoder = new BmpBitmapEncoder(); break; case ".png": encoder = new PngBitmapEncoder(); break; case ".gif": encoder = new GifBitmapEncoder(); break; case ".tif": case "tiff": encoder = new TiffBitmapEncoder(); break; case ".jpg": case "jpeg": encoder = new JpegBitmapEncoder(); break; case ".wmp": encoder = new WmpBitmapEncoder(); break; } Console.WriteLine(extension); // TODO: Figure out why files have no compression. int stride = map.Width * Map.BytesPerPixel; BitmapSource bitmapSource = BitmapSource.Create( map.Width, map.Height, 96, 96, PixelFormats.Bgra32, null, pixels, stride); encoder.Frames.Add(BitmapFrame.Create(bitmapSource)); using (FileStream filestream = new FileStream(outputPath, FileMode.Create)) { encoder.Save(filestream); } }
/// <summary> /// Simple way to avoid the target. /// </summary> /// <param name="target">The target to avoid.</param> /// <param name="map">The map that the agent is traveling on.</param> public void Avoid(Agent target, Map map) { var iterations = 0; int newX = X, newY = Y; var targetNode = map[target.X, target.Y]; var currentDist = map[X, Y].DistanceTo(targetNode); // Only 10 steps are needed. while (iterations < 20) { var neighbours = map.NeighbourNodes(map[newX, newY]); // Check which neighbour node that leads furthest away from the target. foreach (Node neighbour in neighbours) { if (neighbour.Closed) continue; var tempDist = neighbour.DistanceTo(targetNode); if (tempDist > currentDist) { currentDist = tempDist; var optimalNeighbour = neighbours.IndexOf(neighbour); newX = neighbours[optimalNeighbour].X; newY = neighbours[optimalNeighbour].Y; } } iterations++; } // Find the path to the target location. Path = AStar.FindPathTo(map[X, Y], map[newX, newY], map); Move(); }
public void FindPathWithBreadthFirstStrategy() { Map map; ITraversalStrategy strategy = Strategies.BreadthFirst; MapPath solution; map = new Map(this.simpleMap); solution = PathFinder.FindPath(map, strategy); PathFinder.OutputBitmap(solution, map, "simpleSolution.png"); Assert.IsNotNull(solution); map = new Map(this.largeMap); solution = PathFinder.FindPath(map, strategy); PathFinder.OutputBitmap(solution, map, "largeSolution.png"); Assert.IsNotNull(solution); // TODO: Technically, this fails, because the path goes through // some diagonal walls. map = new Map(this.organicMap); solution = PathFinder.FindPath(map, strategy); PathFinder.OutputBitmap(solution, map, "organicSolution.png"); Assert.IsNotNull(solution); }
/// <summary> /// Finds the shortest path from [fleeing] to [chasing] using the AStar algorithm. /// </summary> /// <param name="start">The node to fleeing at.</param> /// <param name="end">The node to chasing at.</param> /// <param name="map">The map.</param> /// <returns>The path as a list of nodes.</returns> public static List<Node> FindPathTo(Node start, Node end, Map map) { // Create lists var path = new List<Node>(); _open = new List<Node>(); _closed = new List<Node>(); // Create fleeing node var tempStart = start; tempStart.CameFrom = null; tempStart.GScore = 0; tempStart.FScore = tempStart.GScore + tempStart.DistanceTo(end); AddToOpenList(tempStart); // While open is not empty... while (_open.Count > 0) { var current = _open[0]; // If we found the goal ... if (current.Equals(end)) { // ... Create the path. path = ReconstructPath(current); break; } _open.Remove(current); AddToClosedList(current); // For all neighbour nodes foreach (var neighbour in map.NeighbourNodes(current)) { if (neighbour.Closed) continue; // Calculate scores. var tentativeGScore = current.GScore + neighbour.Cost; var tentativeFScore = tentativeGScore + neighbour.DistanceTo(end); // If the neighbour is in the closed list and the tentativeFScore is higher // than the neighbour's, skip it. if (_closed.Contains(neighbour) && tentativeFScore >= _closed[_closed.IndexOf(neighbour)].FScore) { continue; } // If the neighbour is not in the open list, add it. if (!_open.Contains(neighbour) && map.WithinMap(neighbour)) { neighbour.CameFrom = current; neighbour.GScore = tentativeGScore; neighbour.FScore = tentativeFScore; AddToOpenList(neighbour); continue; } // If the neighbour is in the open list, modify it. if (_open.Contains(neighbour) && map.WithinMap(neighbour)) { var indexOfNeighbour = _open.IndexOf(neighbour); if (tentativeFScore < _open[indexOfNeighbour].FScore) { _open[indexOfNeighbour].CameFrom = current; _open[indexOfNeighbour].GScore = tentativeGScore; _open[indexOfNeighbour].FScore = tentativeFScore; } } } } return path; }
/// <summary> /// Chase the target using the aStar algorithm. /// </summary> /// <param name="target">The target to chase.</param> /// <param name="map">The map the agent is traveling on.</param> public void Chase(Agent target, Map map) { Path = AStar.FindPathTo(map[X, Y], map[target.X, target.Y], map); Move(); }