예제 #1
0
 public static List <Position> DrawLine(Tile start, Tile destination, DrawContoller draw_option)
 {
     if (start == destination)
     {
         return(new List <Position>()
         {
             start.position
         });
     }
     return(DrawLine(start.position, destination.position, draw_option));
 }
예제 #2
0
    public static List <Position> DrawLine(Position start, Position destination, DrawContoller draw_option)
    {
        Stopwatch timer = new Stopwatch();

        timer.Reset();
        timer.Start();
        if (start == destination)
        {
            return(new List <Position>()
            {
                start
            });
        }
        Dictionary <Position, AStarData> data_map = new Dictionary <Position, AStarData>();
        List <Position> quick_search  = new List <Position>();
        List <Position> medium_search = new List <Position>();
        List <Position> slow_search   = new List <Position>();

        // first position is tile, second position is x = distance travelled and y = waste
        quick_search.Add(start);
        data_map.Add(start, new AStarData(new Position(-1, -1), 0, 0));
        List <Position> result       = new List <Position>();
        Position        current_tile = start;
        bool            path_found   = false;

        while (quick_search.Count + medium_search.Count + slow_search.Count > 0 && !path_found && !draw_option.QuickStop())
        {
            data_map[current_tile] = new AStarData(data_map[current_tile], true);
            Position goal_direction = GetDirection(current_tile, destination);
            for (int i = -1; i <= 1; i++)
            {
                for (int j = -1; j <= 1; j++)
                {
                    Position adjacent_tile = GetAdjacent(current_tile, i, j);
                    if (map.ContainsKey(adjacent_tile))
                    {
                        if (adjacent_tile == destination)
                        {
                            if (draw_option.GetDistance(current_tile, adjacent_tile) > 0)
                            {
                                float distance = data_map[current_tile].distance + draw_option.GetDistance(current_tile, adjacent_tile);
                                float waste    = data_map[current_tile].waste;
                                data_map.Add(adjacent_tile, new AStarData(current_tile, distance, waste));
                                path_found = true;
                            }
                        }
                        else
                        {
                            float distance = draw_option.GetDistance(current_tile, adjacent_tile);
                            if (distance > 0)
                            {
                                distance += data_map[current_tile].distance;
                                float waste = data_map[current_tile].waste + Mathf.Abs(goal_direction.x - i) + Mathf.Abs(goal_direction.y - j);
                                if (!data_map.ContainsKey(adjacent_tile))
                                {
                                    data_map.Add(adjacent_tile, new AStarData(current_tile, distance, waste));
                                }
                                else
                                {
                                    if (data_map[adjacent_tile].distance > distance)
                                    {
                                        data_map[adjacent_tile] = new AStarData(current_tile, distance, waste, data_map[adjacent_tile].ventured);
                                    }
                                }
                                if (!data_map[adjacent_tile].ventured)
                                {
                                    if (waste == data_map[current_tile].waste)
                                    {
                                        if (!quick_search.Contains(adjacent_tile))
                                        {
                                            quick_search.Add(adjacent_tile);
                                        }
                                        if (medium_search.Contains(adjacent_tile))
                                        {
                                            medium_search.Remove(adjacent_tile);
                                        }
                                        else if (slow_search.Contains(adjacent_tile))
                                        {
                                            slow_search.Remove(adjacent_tile);
                                        }
                                    }
                                    else if (waste - data_map[current_tile].waste < 2)
                                    {
                                        if (!medium_search.Contains(adjacent_tile))
                                        {
                                            medium_search.Add(adjacent_tile);
                                        }
                                        if (slow_search.Contains(adjacent_tile))
                                        {
                                            slow_search.Remove(adjacent_tile);
                                        }
                                    }
                                    else
                                    {
                                        if (!slow_search.Contains(adjacent_tile))
                                        {
                                            slow_search.Add(adjacent_tile);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (quick_search.Count > 0)
            {
                //Sort Quick Search
                quick_search.Sort((tile1, tile2) => data_map[tile1].waste.CompareTo(data_map[tile2].waste));
                current_tile = quick_search[0];
                quick_search.Remove(current_tile);
            }
            else if (medium_search.Count > 0)
            {
                //Sort medium_search
                medium_search.Sort((tile1, tile2) => data_map[tile1].waste.CompareTo(data_map[tile2].waste));
                current_tile = medium_search[0];
                medium_search.Remove(current_tile);
            }
            else if (slow_search.Count > 0)
            {
                slow_search.Sort((tile1, tile2) => data_map[tile1].waste.CompareTo(data_map[tile2].waste));
                current_tile = slow_search[0];
                slow_search.Remove(current_tile);
            }
        }
        if (!data_map.ContainsKey(destination))
        {
            throw new NoPathException(start + " to " + destination + " has no path");
        }
        AStarData item = data_map[destination];

        result.Add(destination);
        while (data_map.ContainsKey(item.previous_tile))
        {
            result.Add(item.previous_tile);
            item = data_map[item.previous_tile];
        }
        result.Reverse();
        return(result);
    }