//This Herus Function is used only for GBFS Algorithm so it only calculate the Manhattam distance public void Heurs(MazeNode Goal) { int Heuristic = 0; Console.WriteLine("Calculating for: " + this.x + " , " + this.y); Console.WriteLine(Goal.x.ToString() + " , " + Goal.y.ToString()); Heuristic += Math.Abs(this.x - Goal.x) + Math.Abs(this.y - Goal.y); // setting the state heurisitc cost. this.costh = Heuristic; }
// Given a valid finish node with a linked list back to the start node // will draw a path on the bitmap image from finish to start public void ColorPathFromFinishToStart(MazeNode finishNode) { MazeNode current = finishNode; while (current != null) { maze.SetPixel(current.GetX(), current.GetY(), pathColor); current = current.GetParent(); } }
//This Herus method is used for A* Algorithm it will calculate the Manhattam distance to goal and start public void Heurs(MazeNode Goal, MazeNode Start) { Console.WriteLine("Calculating for: " + this.x + " , " + this.y); Console.WriteLine(Goal.x.ToString() + " , " + Goal.y.ToString()); Console.WriteLine(Start.x.ToString() + " , " + Start.y.ToString()); this.costh = Math.Abs(this.x - Goal.x) + Math.Abs(this.y - Goal.y); this.costg += this.parent.costg + 1; // setting the state heurisitc cost. this.costf = this.costh + this.costg; Console.WriteLine("F: " + this.costf.ToString()); }
//Will count the current level of the current node based on its fathers recursively public int getCurrentLevel(MazeNode node) { int nLevel = 0; MazeNode current = node; while (current != null) { nLevel += 1; current = current.GetParent(); } return(nLevel); }
// Method does all the steps to solve the entire maze // if null is returned the maze cannot be solved // Returns Bitmap of the maze image with a solution path drawn public MazeNode SolveMaze(string algorithmType) { MazeNode finishNode = null; MazeNode startNode = FindStartFromColor(); // If no start pixel could be found, cannot solve maze return null if (startNode == null) { return(finishNode); } switch (algorithmType) { case "Breadth First Search": // Try to find the finish node from the start doing bfs finishNode = DoBreadthFirstSearch(startNode); break; case "Depth First Search": // Try to find the finish node from the start doing dfs finishNode = DoDepthFirstSearch(startNode); break; case "Iterative Depth First Search": // Try to find the finish node from the start doing idfs finishNode = DoIterativeDepthFirstSearch(startNode); break; case "Greedy Best First Search": // Try to find the finish node from the start doing gbfs finishNode = DoGreedyFirstSearch(startNode); break; case "A* Search": //Try to find the finish node from the start doing A* finishNode = DoAStarSearch(startNode); break; default: break; } if (finishNode == null) { return(finishNode); } // with the finish node having a linked list back to start // color the path back to the start node in the bitmap image ColorPathFromFinishToStart(finishNode); return(finishNode); }
private void BTN_Solve_Click(object sender, RoutedEventArgs e) { DateTime startedTime; DateTime finalizedTime; // Get the file names that will be working on from command line string outputPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location); // For this project these define the start, end, wall and path colors for the maze // Just change these if you want to solve a maze with different requirements System.Drawing.Color start = System.Drawing.Color.Red; System.Drawing.Color end = System.Drawing.Color.Blue; System.Drawing.Color wall = System.Drawing.Color.Black; System.Drawing.Color path = System.Drawing.Color.GreenYellow; // Load the maze from the first argument filename Bitmap mazeImage = new Bitmap(ImagePath); // initialize path finder with the image and colors to operate with PathFinder pf = new PathFinder(mazeImage, start, end, wall, path); // get the solved maze bitmap from pathfinder startedTime = DateTime.Now; MazeNode resultPath = pf.SolveMaze(COMBO_Type.SelectedValue.ToString()); finalizedTime = DateTime.Now; Lbl_coordinates.Content = "Elapsed Time:" + finalizedTime.Subtract(startedTime).TotalSeconds.ToString() + " seconds. "; mazeImage = pf.Maze; if (mazeImage == null) { MessageBox.Show("Could not solve maze"); } else { LIST_Solution.Items.Clear(); MazeNode current = resultPath; while (current != null) { LIST_Solution.Items.Add("(" + current.GetX() + ", " + current.GetY() + ")"); current = current.GetParent(); } Lbl_coordinates.Content = Lbl_coordinates.Content + LIST_Solution.Items.Count.ToString() + " elements"; // Save the solved maze image into the output file path mazeImage.Save(outputPath + @"\solved_maze.png"); fileUri = new Uri(outputPath + @"\solved_maze.png"); IMG_Maze.Source = new BitmapImage(fileUri); } }
private int getColumnIndexPositionOfValue(Bitmap maze, int x, int y, MazeNode Goal) { int position = 0; for (int indx = 0; indx < 3; indx++) { for (int jndx = 0; jndx < 3; jndx++) { if (maze.GetPixel(x, y).ToArgb().Equals(maze.GetPixel(Goal.x, Goal.y).ToArgb())) { position = jndx; } } } return(position); }
//This method is used for A* algorithm private void AddAllUnvisitedChildren(MazeNode current, List <MazeNode> q, MazeNode Goal, MazeNode Start) { int x = current.GetX(); int y = current.GetY(); List <MazeNode> temp = new List <MazeNode>(); // Left pixel. If it is not out of bounds and previously not visited if (x - 1 >= 0 && !visited[x - 1, y]) { visited[x - 1, y] = true; temp.Add(new MazeNode(x - 1, y, current)); } // Right pixel. If it is not out of bounds and previously not visited if (x + 1 < maze.Width && !visited[x + 1, y]) { visited[x + 1, y] = true; temp.Add(new MazeNode(x + 1, y, current)); } // top pixel. If it is not out of bounds and previously not visited if (y - 1 >= 0 && !visited[x, y - 1]) { visited[x, y - 1] = true; temp.Add(new MazeNode(x, y - 1, current)); } // bottom pixel. If it is not out of bounds and previously not visited if (y + 1 < maze.Height && !visited[x, y + 1]) { visited[x, y + 1] = true; temp.Add(new MazeNode(x, y + 1, current)); } AStarSC MyComparer = new AStarSC(); foreach (MazeNode child in temp) { child.Heurs(Goal, Start); } temp.Sort(MyComparer); foreach (MazeNode child in temp) { q.Add(child); } }
public MazeNode DoAStarSearch(MazeNode start) { // Initialize all visited pixels to false visited = new bool[maze.Width, maze.Height]; // Queue will be used to do bfs. Initialize it with the start node List <MazeNode> nodeStack = new List <MazeNode>(); nodeStack.Add(start); MazeNode current; MazeNode Goal = start.Goal(maze); //int nCurrentLevel=0; // keep looking until there are no more nodes in the queue while (nodeStack.Count != 0) { int count = nodeStack.Count(); current = nodeStack[count - 1]; nodeStack.RemoveAt(count - 1); // Skip any walls if (IsWallNode(current)) { continue; } // If its a finish node, we are done return this node if (IsFinishNode(current)) { //Console.WriteLine(nCurrentLevel.ToString()); return(current); } AddAllUnvisitedChildren(current, nodeStack, Goal, start); //nCurrentLevel = getCurrentLevel(current); } // if no finish node was found, maze cannot be solved with given // start or maze parameters were not set correctly. return(null); }
public MazeNode DoIterativeDepthFirstSearch(MazeNode start) { Stack <MazeNode> nodeStack = new Stack <MazeNode>(); visited = new bool[maze.Width, maze.Height]; int maxLevel = 0; while (true) { nodeStack.Clear(); clearVisited(maze.Width, maze.Height); int nCurrentLevel; nodeStack.Push(start); maxLevel += 1; // keep looking until there are no more nodes in the queue while (nodeStack.Count > 0) { MazeNode current = nodeStack.Pop(); visited[current.GetX(), current.GetY()] = true; // Skip any walls if (IsWallNode(current)) { continue; } // If its a finish node, we are done return this node if (IsFinishNode(current)) { return(current); } AddAllUnvisitedChildren(current, nodeStack); nCurrentLevel = getCurrentLevel(current); if (nCurrentLevel >= maxLevel) { //Console.WriteLine(maxLevel.ToString()); break; } } } }
public MazeNode Goal(Bitmap maze) { MazeNode goal = null; System.Drawing.Color end = System.Drawing.Color.Blue; for (int i = 0; i < maze.Width; i++) { for (int j = 0; j < maze.Height; j++) { // found a start pixel. Return a new MazeNode with no parent // This will the be end of all linked list paths and // lets ColorPathFromFinishToStart end if (maze.GetPixel(i, j).ToArgb().Equals(end.ToArgb())) { goal = new MazeNode(i, j, null); } } } return(goal); }
public void SetParent(MazeNode p) { parent = p; }
public MazeNode() { parent = null; }
// checks if the node has the same color as a finishing pixel. // this can be edited to put any custom finish point public bool IsFinishNode(MazeNode node) { return(maze.GetPixel(node.GetX(), node.GetY()).ToArgb().Equals(finishColor.ToArgb())); }
// Returns true if the node's pixel color is a wallColor public bool IsWallNode(MazeNode node) { // Dont need to check out of bounds since AddAllUnvisitedChildren does bounds checking return(maze.GetPixel(node.GetX(), node.GetY()).ToArgb().Equals(wallColor.ToArgb())); }