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));
        }
Пример #4
0
        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();
            }
        }