Esempio n. 1
0
        public void Solve(IMazeGrid maze, Action <IEnumerable <IMazeCell> > solvedResultCallback)
        {
            Graph <IMazeCell> graph = maze.GenerateGraph();

            // stack of graph nodes
            Stack <GraphNode <IMazeCell> > stack = new Stack <GraphNode <IMazeCell> >();

            // Routes Collection
            LinkedList <GraphNode <IMazeCell> > visited = new LinkedList <GraphNode <IMazeCell> >();

            GraphNode <IMazeCell> startNode = (GraphNode <IMazeCell>)graph.Nodes.FindByValue(maze.Start);

            stack.Push(startNode);

            GraphNode <IMazeCell> currentNode = null;

            while (stack.Count > 0)
            {
                currentNode = stack.Pop();

                _logger.LogTrace($"Poped Node: {currentNode.Value.ToString()}");

                if (visited.Contains(currentNode))
                {
                    continue;
                }

                visited.AddFirst(currentNode);

                if (maze.Finish.Equals(currentNode.Value))
                {
                    _logger.LogTrace($"Found Finish Node: {currentNode.Value.ToString()}");

                    solvedResultCallback(TraceSolvedPath(visited));
                }

                // Examine neighbor nodes
                foreach (GraphNode <IMazeCell> neighbor in currentNode.Neighbors)
                {
                    if (!visited.Contains(neighbor))
                    {
                        stack.Push(neighbor);

                        _logger.LogTrace($"Push Node: {neighbor.Value.ToString()}");
                    }
                    else
                    {
                        _logger.LogTrace($"Node: {neighbor.Value.ToString()} is visited");
                    }
                }
            }
        }
Esempio n. 2
0
        public void Solve(IMazeGrid maze, Action <IEnumerable <IMazeCell> > solvedResultCallback)
        {
            Graph <IMazeCell> graph = maze.GenerateGraph();

            // stack of graph nodes
            LinkedList <GraphNode <IMazeCell> > visited = new LinkedList <GraphNode <IMazeCell> >();  //collecting all routes

            GraphNode <IMazeCell> startNode = (GraphNode <IMazeCell>)graph.Nodes.FindByValue(maze.Start);
            GraphNode <IMazeCell> endNode   = (GraphNode <IMazeCell>)graph.Nodes.FindByValue(maze.Finish);

            visited.AddFirst(startNode);

            // make the first call
            BreadthFirst(startNode, endNode, visited, solvedResultCallback);
        }
Esempio n. 3
0
        public void Solve(IMazeGrid maze, Action <IEnumerable <IMazeCell> > solvedResultCallback)
        {
            // the maze graph
            Graph <IMazeCell> graph = maze.GenerateGraph();


            // List of Accepted solutions used to reset the visited nodes
            List <List <GraphNode <IMazeCell> > > solutions = new List <List <GraphNode <IMazeCell> > >();

            // Que of graph nodes
            Queue <GraphNode <IMazeCell> > queue = new Queue <GraphNode <IMazeCell> >();

            // Directory of Predecessor
            Dictionary <GraphNode <IMazeCell>, GraphNode <IMazeCell> > predecessors = new Dictionary <GraphNode <IMazeCell>, GraphNode <IMazeCell> >();

            // List visited nodes
            List <GraphNode <IMazeCell> > visited = new List <GraphNode <IMazeCell> >();

            GraphNode <IMazeCell> currentNode = null;

            GraphNode <IMazeCell> startNode = (GraphNode <IMazeCell>)graph.Nodes.FindByValue(maze.Start);

            queue.Enqueue(startNode);



            while (queue.Count > 0)
            {
                currentNode = queue.Dequeue();

                _logger.LogTrace($"Dequeue Node({currentNode.Value.ToString()})");

                if (visited.Contains(currentNode))
                {
                    continue;
                }

                visited.Add(currentNode);

                if (maze.Finish.Equals(currentNode.Value))
                {
                    _logger.LogTrace($"Finish Node({currentNode.Value.ToString()})");

                    IEnumerable <GraphNode <IMazeCell> > solvedPath = TraceSolvedPath(currentNode, predecessors);

                    // callback Action and returns path.
                    List <IMazeCell> cbPath = new List <IMazeCell>();

                    foreach (var node in solvedPath)
                    {
                        cbPath.Add(node.Value);
                    }

                    solvedResultCallback(cbPath);

                    break;
                }

                foreach (GraphNode <IMazeCell> neighbor in currentNode.Neighbors)
                {
                    if (!visited.Contains(neighbor) && !queue.Contains(neighbor))
                    {
                        // enquew
                        queue.Enqueue(neighbor);

                        // keep track of Predecessor
                        predecessors[neighbor] = currentNode;

                        _logger.LogTrace($"Enqueue Node: {neighbor.Value.ToString()} Predecessor: {currentNode.Value.ToString()}");
                    }
                    else
                    {
                        _logger.LogTrace($"Node({neighbor.Value.ToString()}) is visited");
                    }
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Construct the maze grid and validate for characters and Start/End Point
        /// </summary>
        /// <param name="grid"></param>
        /// <param name="lines"></param>
        /// <param name="mazeHeight"></param>
        /// <param name="mazeWidth"></param>
        private void LoadMazeMapFromStringList(IMazeGrid grid, List <string> lines, int mazeHeight, int mazeWidth)
        {
            _logger.LogInformation($"I found a {mazeWidth} x {mazeHeight} Maze. Moving on to Maze Construction & Validation");

            // Initialize 2D array
            grid.MazeMap = new IMazeCell[mazeHeight, mazeWidth];
            grid.Height  = mazeHeight;
            grid.Width   = mazeWidth;


            int i = 0;

            lines.ForEach(line =>
            {
                for (int j = 0; j < mazeWidth; j++)
                {
                    char c = line[j];

                    if (c == _mazeSettings.WallChar[0])
                    {
                        grid.MazeMap[i, j] = new MazeCell(i, j)
                        {
                            State = CellState.Wall
                        };

                        continue;
                    }
                    else if (c == _mazeSettings.StartChar[0])
                    {
                        grid.MazeMap[i, j] = new MazeCell(i, j)
                        {
                            State = CellState.Path
                        };

                        if (grid.Start == null)
                        {
                            grid.Start = grid.MazeMap[i, j];
                        }
                        else
                        {
                            throw new Exception("I do not support more than one starting points");
                        }
                    }
                    else if (c == _mazeSettings.FinishChar[0])
                    {
                        grid.MazeMap[i, j] = new MazeCell(i, j)
                        {
                            State = CellState.Path
                        };

                        if (grid.Finish == null)
                        {
                            grid.Finish = grid.MazeMap[i, j];
                        }
                        else
                        {
                            throw new Exception("I do not support more than one ending points");
                        }
                    }
                    else if (c == _mazeSettings.OpenChar[0])
                    {
                        grid.MazeMap[i, j] = new MazeCell(i, j)
                        {
                            State = CellState.Path
                        };
                    }
                    else
                    {
                        //Invalid Char.
                        throw new Exception(string.Format("I found a char {0} that this maze was not configured to handle.", c.ToString()));
                    }
                }

                i++;
            });

            // Finaly validate that there is a start and an end point
            if (grid.Start == null || grid.Finish == null)
            {
                throw new Exception($"This maze does not have {((grid.Start == null) ? "a start" : "an end")} point");
            }
        }
Esempio n. 5
0
        public void Load(IMazeGrid grid)
        {
            if (grid == null)
            {
                throw new ArgumentNullException("Maze Grid cannot be null", "grid");
            }

            // Read file into a list of strings and validate lines
            var lines = new List <string>();

            int mazeWidth  = 0;
            int mazeHeight = 0;

            try
            {
                ValidateMazeFile();


                _logger.LogInformation($"Reading Maze File: {_mazeSettings.MazeFile}");

                using (StreamReader sr = new StreamReader(_mazeSettings.MazeFile))
                {
                    while (sr.Peek() >= 0)
                    {
                        // Read the stream to a string, trim to remove white space.
                        string line = sr.ReadLine();

                        // validate line
                        if (string.IsNullOrWhiteSpace(line))
                        {
                            throw new InvalidDataException("File can not contain white space"); // can i kick it ?
                        }
                        // Initialize maze width or validate width
                        if (mazeHeight == 0)
                        {
                            mazeWidth = line.Length;
                        }
                        else
                        {
                            if (!mazeWidth.Equals(line.Length))
                            {
                                throw new InvalidDataException("Lines must have the same width");
                            }
                        }


                        lines.Add(line);
                        mazeHeight++;
                    }
                }
            }
            catch (Exception e)
            {
                // Invalid file or file access

                _logger.LogError(e.Message);
                throw new Exception("Invalid file or file access ", e);
            }

            if (lines.Count == 0)
            {
                throw new Exception("File is empty or does not contain valid lines");
            }


            LoadMazeMapFromStringList(grid, lines, mazeHeight, mazeWidth);
        }
Esempio n. 6
0
        public void Solve(IMazeGrid maze, Action <IEnumerable <IMazeCell> > solvedResultCallback)
        {
            Graph <IMazeCell> graph = maze.GenerateGraph();

            GraphNode <IMazeCell> startNode = (GraphNode <IMazeCell>)graph.Nodes.FindByValue(maze.Start);


            Dictionary <GraphNode <IMazeCell>, GraphNode <IMazeCell> > predecessors = new Dictionary <GraphNode <IMazeCell>, GraphNode <IMazeCell> >();
            List <GraphNode <IMazeCell> >           nodes     = new List <GraphNode <IMazeCell> >();
            Dictionary <GraphNode <IMazeCell>, int> distances = new Dictionary <GraphNode <IMazeCell>, int>();

            GraphNode <IMazeCell> currentNode = null;

            // read all nodes and init distances
            foreach (GraphNode <IMazeCell> vertex in graph.Nodes)
            {
                // start node has 0 distance, all over nodes are unknown and set to Max
                if (vertex.Value.Equals(maze.Start))
                {
                    distances[vertex] = 0;
                }
                else
                {
                    distances[vertex] = int.MaxValue;
                }

                nodes.Add(vertex);
            }

            while (nodes.Count != 0)
            {
                // Find current shortest path point to explore
                nodes.Sort((x, y) => distances[x] - distances[y]);

                currentNode = nodes[0];

                nodes.Remove(currentNode);

                if (currentNode.Value.Equals(maze.Finish))
                {
                    IEnumerable <IMazeCell> solvedPath = TraceSolvedPath(currentNode, predecessors).Reverse();

                    solvedResultCallback(solvedPath); // Calls the callback Action and returns the path.

                    break;
                }

                if (distances[currentNode] == int.MaxValue)
                {
                    break;
                }


                foreach (GraphNode <IMazeCell> neighbor in currentNode.Neighbors)
                {
                    var indx = currentNode.Neighbors.IndexOf(neighbor);

                    // distance of current node + Neighbors Cost ( Cost = paths between nodes )
                    int newDistance = distances[currentNode] + currentNode.Costs[indx];

                    if (newDistance < distances[neighbor])
                    {
                        distances[neighbor]    = newDistance;
                        predecessors[neighbor] = currentNode;
                    }
                }
            }
        }