Example #1
0
    public WeightedDistances BFSMeetInMiddlePathTo(WeightedMazeCell goal)
    {
        Queue <WeightedMazeCell> grayQueue     = new Queue <WeightedMazeCell>();
        Queue <WeightedMazeCell> grayQueueGoal = new Queue <WeightedMazeCell>();

        grayQueue.Enqueue(this.startingCell);
        grayQueueGoal.Enqueue(goal);

        WeightedDistances distances     = new WeightedDistances(startingCell);
        WeightedDistances distancesGoal = new WeightedDistances(goal);

        bool notFound = true;

        var current = startingCell;

        while (notFound)
        {
            current = grayQueue.Dequeue();

            foreach (var linkedCell in current.Links())
            {
                if (distancesGoal.ContainsKey(linkedCell))
                {
                    notFound = false;
                    if (!distances.ContainsKey(linkedCell))
                    {
                        distances.Add(linkedCell, distances[current] + 1);
                    }
                    current = linkedCell;
                    break;
                }

                if (distances.ContainsKey(linkedCell))
                {
                    continue;
                }

                distances.Add(linkedCell, distances[current] + 1);

                if (grayQueue.Contains(linkedCell))
                {
                    continue;
                }
                grayQueue.Enqueue(linkedCell);
            }

            if (!notFound)
            {
                break;
            }

            current = grayQueueGoal.Dequeue();

            foreach (var linkedCell in current.Links())
            {
                if (distances.ContainsKey(linkedCell))
                {
                    notFound = false;
                    if (!distancesGoal.ContainsKey(linkedCell))
                    {
                        distancesGoal.Add(linkedCell, distancesGoal[current] + 1);
                    }
                    current = linkedCell;
                    break;
                }

                if (distancesGoal.ContainsKey(linkedCell))
                {
                    continue;
                }

                distancesGoal.Add(linkedCell, distancesGoal[current] + 1);

                if (grayQueueGoal.Contains(linkedCell))
                {
                    continue;
                }
                grayQueueGoal.Enqueue(linkedCell);
            }
        }

        WeightedDistances breadcrumbs = new WeightedDistances(this.startingCell);

        breadcrumbs.Add(current, distances[current]);

        WeightedMazeCell breadcrumbsCurrent = current;

        while (current != startingCell)
        {
            foreach (WeightedMazeCell neighbour in current.Links())
            {
                if (!distances.ContainsKey(neighbour))
                {
                    continue;
                }

                if (distances[neighbour] < distances[current])
                {
                    if (!breadcrumbs.ContainsKey(neighbour))
                    {
                        breadcrumbs.Add(neighbour, distances[neighbour]);
                    }
                    else
                    {
                        breadcrumbs[neighbour] = distances[neighbour];
                    }

                    current = neighbour;
                    break;
                }
            }
        }

        current = breadcrumbsCurrent;
        WeightedDistances breadcrumbsGoal = new WeightedDistances(goal);

        while (current != goal)
        {
            foreach (WeightedMazeCell neighbour in current.Links())
            {
                if (!distancesGoal.ContainsKey(neighbour))
                {
                    continue;
                }

                if (distancesGoal[neighbour] < distancesGoal[current])
                {
                    if (!breadcrumbsGoal.ContainsKey(neighbour))
                    {
                        breadcrumbsGoal.Add(neighbour, distancesGoal[neighbour]);
                    }
                    else
                    {
                        breadcrumbsGoal[neighbour] = distancesGoal[neighbour];
                    }

                    current = neighbour;
                    break;
                }
            }
        }

        WeightedMazeCell maxCell = null;
        WeightedMazeCell minCell = null;

        int max = breadcrumbsGoal.MaxDistanceValue();
        int min = breadcrumbsGoal.MinDistanceValue();

        while (max > min)
        {
            foreach (WeightedMazeCell cell in breadcrumbsGoal.Keys)
            {
                if (breadcrumbsGoal[cell] == min)
                {
                    minCell = cell;
                }

                if (breadcrumbsGoal[cell] == max)
                {
                    maxCell = cell;
                }
            }

            breadcrumbsGoal[minCell] = max;
            breadcrumbsGoal[maxCell] = min;
            max--;
            min++;
        }

        max = breadcrumbs.MaxDistanceValue();
        max++;

        foreach (WeightedMazeCell cell in breadcrumbsGoal.Keys)
        {
            breadcrumbs.Add(cell, breadcrumbsGoal[cell] + max);
        }

        return(breadcrumbs);
    }