public List<Cell> Solve(Cell[,] maze, Cell startingCell, Cell endingCell) { var q = new Queue<Cell>(); startingCell["parent"] = startingCell; q.Enqueue(startingCell); while (q.Peek() != endingCell) { Cell current = q.Dequeue(); foreach (Cell cell in current.Neighbors) if (cell["parent"] == null) { cell["parent"] = current; q.Enqueue(cell); } } var solution = RebuildPath(endingCell); foreach (var cell in maze) cell.ClearAdditionalValues(); return solution; }
//Do not use this implementation... it's so slow! public List<Cell> Solve(Cell[,] maze, Cell startingCell, Cell endingCell) { var open = new List<Cell>(); var closed = new List<Cell>(); startingCell["g"] = 0; startingCell["h"] = EstimateDistance(startingCell, endingCell); startingCell["f"] = (int)startingCell["g"] + (int)startingCell["h"]; open.Add(startingCell); while(true) { open.Sort((c1, c2) => (int)c1["f"] - (int)c2["f"]); var current = open[0]; open.RemoveAt(0); closed.Add(current); if (current == endingCell) break; var neighbour = new [] {current.North, current.East, current.South, current.West}; foreach (var cell in neighbour) { if (cell == null || closed.Contains(cell)) continue; if (open.Contains(cell)) { if ((int)current["g"] + 1 < (int)cell["g"]) { cell["g"] = (int) current["g"] + 1; cell["f"] = (int) cell["g"] + (int)cell["h"]; cell["parent"] = current; } } else { cell["g"] = (int)current["g"] + 1; cell["h"] = EstimateDistance(cell, endingCell); cell["f"] = (int)cell["g"] + (int)cell["h"]; cell["parent"] = current; open.Add(cell); } } } var solution = RebuildPath(endingCell); foreach (var cell in maze) cell.ClearAdditionalValues(); return solution; }
private static List<Cell> RebuildPath(Cell endingCell) { List<Cell> ret = new List<Cell>(); Cell current = endingCell; do { ret.Add(current); current = current["parent"] as Cell; } while (current != null); ret.Reverse(); return ret; }
private static int EstimateDistance(Cell cell, Cell endingCell) { return Math.Abs(cell.X - endingCell.X) + Math.Abs(cell.Y - endingCell.Y); }
public Cell[,] Build(int width, int height) { var rnd = new Random(); var maze = new Cell[width, height]; int x, y; int startX = x = rnd.Next(width); int startY = y = rnd.Next(height); var directions = new List<int>(); var history = new Stack<Cell>(); for (int i = 0; i < width; i++) for (int j = 0; j < height; j++) { maze[i, j] = new Cell(i, j); maze[i, j]["processed"] = false; } history.Push(maze[x,y]); do { maze[x, y]["processed"] = true; directions.Clear(); if (y - 1 >= 0 && !(bool)maze[x, y - 1]["processed"]) directions.Add(0); if (x + 1 < width && !(bool)maze[x + 1, y]["processed"]) directions.Add(1); if (y + 1 < height && !(bool)maze[x, y + 1]["processed"]) directions.Add(2); if (x - 1 >= 0 && !(bool)maze[x - 1, y]["processed"]) directions.Add(3); if (directions.Count == 0) { var lastCell = history.Pop(); x = lastCell.X; y = lastCell.Y; continue; } switch (directions[rnd.Next(directions.Count)]) { case 0: maze[x, y].North = maze[x, y - 1]; maze[x, y - 1].South = maze[x, y]; y -= 1; break; case 1: maze[x, y].East = maze[x + 1, y]; maze[x + 1, y].West = maze[x, y]; x += 1; break; case 2: maze[x, y].South = maze[x, y + 1]; maze[x, y + 1].North = maze[x, y]; y += 1; break; case 3: maze[x, y].West = maze[x - 1, y]; maze[x - 1, y].East = maze[x, y]; x -= 1; break; } history.Push(maze[x, y]); } while (x != startX || y != startY); foreach (var cell in maze) cell.ClearAdditionalValues(); return maze; }