public void Small_maze_FindPath_test() { var start = new Point(9, 3); var end = new Point(1, 5); var maze = @" %%%%%%%%%%%%%%%%%%%% %--------------%---% %-%%-%%-%%-%%-%%-%-% %--------P-------%-% %%%%%%%%%%%%%%%%%%-% %.-----------------% %%%%%%%%%%%%%%%%%%%%"; var getCell = GetCell(maze); var getNeighbours = GetNeighbours(getCell); var result = DepthFirstSearch.FindPath(start, getNeighbours, point => point == end).ToArray(); for (var i = 0; i < result.Length - 1; i++) { var twoPoints = result.Skip(i).Take(2).ToArray(); var point1 = twoPoints[0]; var point2 = twoPoints[1]; var distance = Math.Abs(point1.X - point2.X) + Math.Abs(point1.Y - point2.Y); Assert.That(distance, Is.EqualTo(1)); } Assert.That(result.Last(), Is.EqualTo(end)); }
public void FindPath_should_return_empty_enumerqble_when_no_path_found() { var start = new Point(1, 3); var end = new Point(7, 1); const string maze = @" %%%%%%%%% %-------% %%%%%%%%% %P------% %%%%%%%%%"; var getCell = GetCell(maze); var getNeighbours = GetNeighbours(getCell); var result = DepthFirstSearch.FindPath(start, getNeighbours, point => point == end); Assert.That(result, Is.Empty); }
public void Tiny_maze_FindPath_test() { var start = new Point(1, 3); var end = new Point(7, 3); const string maze = @" %%%%%%%%% %-------% %%%%-%%%% %P------% %%%%%%%%%"; Func <Point, char> getCell = p => maze.Split(new[] { Environment.NewLine }, StringSplitOptions.None).Skip(1).ToArray()[p.Y][p.X]; Func <Point, IEnumerable <Point> > getNeighbours = p => { var allPoints = new[] { new Point(p.X, p.Y - 1), // top new Point(p.X + 1, p.Y), // right new Point(p.X, p.Y + 1), // bottom new Point(p.X - 1, p.Y), // left }; return(allPoints.Where(x => getCell(x) != '%')); }; var result = DepthFirstSearch.FindPath(start, getNeighbours, point => point == end).ToArray(); for (var i = 0; i < result.Length - 1; i++) { var twoPoints = result.Skip(i).Take(2).ToArray(); var point1 = twoPoints[0]; var point2 = twoPoints[1]; var distance = Math.Abs(point1.X - point2.X) + Math.Abs(point1.Y - point2.Y); Assert.That(distance, Is.EqualTo(1)); } Assert.That(result.Last(), Is.EqualTo(end)); }
static void Main() { var start = new Point(9, 3); var end = new Point(1, 8); Func <Point, char> getCell = GetCell(MAZE); Func <Point, IEnumerable <Point> > getNeighbours = GetNeighbours(getCell); Func <Point, Point, int> getCost = (from, to) => getCell(to) == '@' ? 4:1; Func <Point, int> manhattanHeuristic = (to) => Math.Abs(to.X - end.X) + Math.Abs(to.Y - end.Y); Func <Point, double> manhattanHeuristicD = (to) => Math.Abs(to.X - end.X) + Math.Abs(to.Y - end.Y); var millisecondsTimeout = 100; var algorithms = new Dictionary <int, Tuple <string, Func <IEnumerable <Point> >, Func <IEnumerable <Point> > > > { { 1, "Depth First Search", () => DepthFirstSearch.Explore(start, getNeighbours), () => DepthFirstSearch.FindPath(start, getNeighbours, p => p.Equals(end)) }, { 2, "Breadth First Search", () => BreadthFirstSearch.Explore(start, getNeighbours), () => BreadthFirstSearch.FindPath(start, getNeighbours, p => p.Equals(end)) }, { 3, "Dijkstra", () => Dijkstra.Explore(start, getNeighbours, getCost), () => Dijkstra.FindPath(start, getNeighbours, getCost, p => p.Equals(end)) }, { 4, "Greedy Best-First Search (with manhattan)", () => GreedyBestFirstSearch.Explore(start, getNeighbours, manhattanHeuristic), () => GreedyBestFirstSearch.FindPath(start, getNeighbours, manhattanHeuristic, p => p.Equals(end)) }, { 5, "A* (with manhattan)", () => AStar.Explore(start, getNeighbours, getCost, manhattanHeuristicD), () => AStar.FindPath(start, getNeighbours, getCost, manhattanHeuristicD, p => p.Equals(end)) }, }; int choice = 0; while (choice != 10) { Console.Clear(); Console.WriteLine("Choose traversal algorithm :"); foreach (var algorithm in algorithms) { Console.WriteLine($"\t{algorithm.Key} - {algorithm.Value.Item1}"); } while (choice == 0) { int.TryParse(Console.ReadLine(), out choice); } var currentMaze = MAZE; var result = algorithms[choice].Item2(); var path = algorithms[choice].Item3().ToList(); var visited = new List <Point>(); foreach (var item in result) { visited.Add(item); var lines = currentMaze.Split(new[] { Environment.NewLine }, StringSplitOptions.None); var line = lines[item.Y].ToCharArray(); line[item.X] = '*'; lines[item.Y] = new string(line); currentMaze = string.Join(Environment.NewLine, lines); DisplayMaze(currentMaze, visited.Count, 0, 0, algorithms[choice].Item1); Thread.Sleep(millisecondsTimeout); if (item == end) { break; } } foreach (var item in path) { var lines = currentMaze.Split(new[] { Environment.NewLine }, StringSplitOptions.None); var line = lines[item.Y].ToCharArray(); line[item.X] = '+'; lines[item.Y] = new string(line); currentMaze = string.Join(Environment.NewLine, lines); } var pathcost = path.Aggregate(0, (current, point) => current + getCost(Point.Empty, point)); DisplayMaze(currentMaze, visited.Count(), path.Count(), pathcost, algorithms[choice].Item1); choice = 0; Console.WriteLine(); Console.WriteLine($"Press any key to reset"); Console.Read(); } }