/// <summary>
        /// Recursively compares all possible routes and finds the shorted
        /// possible distance
        /// </summary>
        private int ShortestDistanceToAll(VisitNode fromNode, IEnumerable <VisitNode> nodesToVisit,
                                          List <NodeRoute> availableRoutes, bool returnToOrigin)
        {
            int result = Int32.MaxValue;

            foreach (VisitNode n in nodesToVisit)
            {
                if (n == fromNode)
                {
                    continue;
                }
                VisitNode[] subtract  = new VisitNode[] { n };
                var         findRoute = from r in availableRoutes
                                        where r.FromNode == fromNode && r.ToNode == n
                                        select r;
                int distanceTravelled = findRoute.First().DistanceTravelled;
                if (nodesToVisit.Count() > 1)
                {
                    distanceTravelled += ShortestDistanceToAll(n, nodesToVisit.Except(subtract),
                                                               availableRoutes, returnToOrigin);
                }
                else
                {
                    // Sabotage non-origin node scores
                    if (returnToOrigin && !n.IsStartPosition)
                    {
                        return(10000);
                    }
                }
                if (distanceTravelled < result)
                {
                    result = distanceTravelled;
                }
            }
            return(result);
        }
Beispiel #2
0
        public int DistanceBetween(VisitNode startNode, VisitNode endNode)
        {
            int consoleTop         = Console.CursorTop;
            Tuple <int, int> start = new Tuple <int, int>(startNode.XPosition, startNode.YPosition);
            Tuple <int, int> goal  = new Tuple <int, int>(endNode.XPosition, endNode.YPosition);

            List <string> closedSet = new List <string>();
            // The set of currently discovered nodes still to be evaluated.
            // Initially, only the start node is known.
            List <string> openSet = new List <string>();

            openSet.Add(HashTuple(start));

            // For each node, which node it can most efficiently be reached from.
            // If a node can be reached from many nodes, cameFrom will eventually contain the
            // most efficient previous step.
            Dictionary <string, string> cameFrom = new Dictionary <string, string>();

            // For each node, the cost of getting from the start node to that node.
            Dictionary <string, int> gScore = new Dictionary <string, int>();

            // The cost of going from start to start is zero.
            gScore[HashTuple(start)] = 0;

            // For each node, the total cost of getting from the start node to the goal
            // by passing by that node. That value is partly known, partly heuristic.
            Dictionary <string, int> fScore = new Dictionary <string, int>();

            // For the first node, that value is completely heuristic.
            fScore[HashTuple(start)] = EstimateMoveCost(start, goal);

            while (openSet.Count > 0)
            {
                // VisualizePuzzle(consoleTop, goal.Item1, goal.Item2, cameFrom);

                foreach (var open in openSet)
                {
                    if (!fScore.ContainsKey(open))
                    {
                        Console.WriteLine("Value (" + open + ") is in the open set but doesn't have a score");
                    }
                }

                var findBestScoreInOpenSet = from o in openSet
                                             join n in fScore
                                             on o equals n.Key
                                             select n;
                var current = ParseTupleHash(findBestScoreInOpenSet.OrderBy(o => o.Value).First().Key);

                if (HashTuple(current) == HashTuple(goal))
                {
                    return(reconstruct_path(cameFrom, HashTuple(current)).Count - 1);
                }

                openSet.Remove(HashTuple(current));
                closedSet.Add(HashTuple(current));

                List <Tuple <int, int> > neighbours = CalcNeighbours(current);

                foreach (var neighbour in neighbours)
                {
                    // Ignore the neighbor which is already evaluated.
                    if (closedSet.Contains(HashTuple(neighbour)))
                    {
                        continue;
                    }
                    // The distance from start to a neighbor
                    int tentative_gScore = gScore[HashTuple(current)] + 1;
                    // Discover a new node
                    if (!openSet.Contains(HashTuple(neighbour)))
                    {
                        openSet.Add(HashTuple(neighbour));
                    }
                    else
                    // This is not a better path.
                    if (tentative_gScore >= gScore[HashTuple(neighbour)])
                    {
                        continue;
                    }

                    // This path is the best until now. Record it!
                    cameFrom[HashTuple(neighbour)] = HashTuple(current);
                    gScore[HashTuple(neighbour)]   = tentative_gScore;
                    fScore[HashTuple(neighbour)]   = gScore[HashTuple(neighbour)] +
                                                     EstimateMoveCost(neighbour, goal);
                }
            }

            return(-1);
        }