Пример #1
0
        public Map(int width, int height, T value)
        {
            this.Width = width;
            this.Height = height;
            data = new T[width, height];
            keys = new BinaryMatrix(width, height);

            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    data[i, j] = value;
                }
            }
        }
Пример #2
0
        // The following code is based on the pseudocode on Wikipedia for A* search algorithm
        // https://en.wikipedia.org/wiki/A*_search_algorithm#Pseudocode
        // It's been modified by Dylan Liu for the purpose of this exercise and for better performance.
        // For example, in the peseudocode, gScore and fScore calculation is done after the neighbor is added to the openSet.
        // This requires passing a reference of a node to the openSet instead of an instance, so that its fScore can later be modified.
        // Dylan Liu moved the fScore and gScore calculation ahead of adding the neighbor to the open set to avoid passing reference,
        // because it is uncommon and negatively affect performance to pass reference in C#.

        public bool SearchSolution(int solutionLineThickness = 1)
        {
            if (sourceImage == null)
            {
                Console.WriteLine("Source image: " + sourceImageName + " is not loaded.");
                return(false);
            }

            // find the start and goal pixel from the source image
            var success = FindStartNGoal();

            if (!success)
            {
                return(false);
            }

            // The set of nodes already evaluated
            var closedSet = new BinaryMatrix(Width, Height);

            // The set of currently discovered nodes that are not evaluated yet.
            var openSet = new BinaryMatrix(Width, Height);

            // A priority queue to remove the node with th lowest score
            var queue = new PriorityQueue <Node>();

            // 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.
            var cameFrom = new Map <Vector2D>(Width, Height);

            // For each node, the cost of getting from the start node to that node.
            var gScore = new Map <double>(Width, Height, double.PositiveInfinity);

            // The cost of going from start to start is zero.
            gScore[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.
            var fScore = new Map <double>(Width, Height, double.PositiveInfinity);

            // Add the start into the queue and openSet
            var startNode = new Node(start, gScore[start] + HeuristicCostEstimate(start, goal));

            queue.Enqueue(startNode);
            openSet[start] = 1;

            while (!queue.IsEmpty())
            {
                #region Code for showing search progress and debug purposes
                count++;
                if (isDebugOn)
                {
                    percentage = count * 100 / (Width * Height);
                    //sourceImage.DrawPoint(current, Color.Yellow); // draw all the pixels that haven been visited
                    if (percentage - prev_percentage > 1)
                    {
                        Console.WriteLine(percentage.ToString() + "% of the total pixels were processed.");
                        prev_percentage = percentage;
                    }
                }

                if (count > Width * Height) // It's impossible to visit all the pixels and yet still no solution.
                {
                    Console.WriteLine("Pathfinding is terminated due to either repeat visit to the same pixels.");
                    return(false);
                }
                #endregion

                Vector2D current = (queue.Dequeue()).Vector2D;
                openSet[current]   = 0;
                closedSet[current] = 1;

                if (current == goal)
                {
                    if (isDebugOn)
                    {
                        Console.WriteLine("Pathfinding complete.");
                    }
                    ReconstructPath(cameFrom, current, solutionLineThickness);
                    return(true);
                }

                var neighbors = current.Neighbors();
                foreach (Vector2D neighbor in neighbors)
                {
                    if (neighbor.IsOutSideBound(0, 0, Width, Height))
                    {
                        continue; // Ignore the neighbor which is out side the bounds of the image
                    }
                    if (closedSet[neighbor] == 1)
                    {
                        continue; // Ignore the neighbor which is already evaluated.
                    }
                    if (sourceImage.GetPixel(neighbor.x, neighbor.y).IsWall())
                    {
                        continue;                                  // Ignore the neighbor which is a wall
                    }
                    double tentative_gScore = gScore[current] + 1; // in this case, distance between current and neight is always 1, in other cases use Vector2D.DistanceBetween(current, neighbor);
                    if (tentative_gScore < gScore[neighbor])
                    {
                        // This path is the best until now. Record it!
                        cameFrom[neighbor] = current;
                        gScore[neighbor]   = tentative_gScore;
                        fScore[neighbor]   = gScore[neighbor] + HeuristicCostEstimate(neighbor, goal);
                    }

                    // Discover a new node
                    var neighborNode = new Node(neighbor, fScore[neighbor]);
                    if (openSet[neighbor] != 1)
                    {
                        queue.Enqueue(neighborNode);
                        openSet[neighbor] = 1;
                    }
                }
            }
            if (isDebugOn)
            {
                Console.WriteLine("Pathfinding failed. There is no solution to this maze.");
            }
            return(false);
        }