Ejemplo n.º 1
0
    //Returns the shortest path from start to dest. If the dest can not be reached befor remainingEnergy runs out (or for other reasons), returns null.
    public List<Tile> getPath(Vector2i start, Vector2i dest, int remainingEnergy)
    {
        if(!_tiles.ContainsKey(dest) || !_tiles.ContainsKey(start) || start.manhattandistance(dest) > remainingEnergy)
        {
            return null;
        }

        List<Tile> path = new List<Tile>();

        Dictionary<Tile, int> distanceFromStart = new Dictionary<Tile, int>();  //Minimum distance from start to each tile.
        Dictionary<Tile, Tile> tileOrigins = new Dictionary<Tile, Tile>();  //Originating tile. (Also acts as a closed list).
        List<Tile> openNodes = new List<Tile>();

        openNodes.Add(_tiles[start]);
        tileOrigins[_tiles[start]] = _tiles[start];
        distanceFromStart[_tiles[start]] = 0;

        Tile curNode, curNeighbor;
        int curDistance;
        bool done = false;
        //While there are still open nodes
        while(!done && openNodes.Count > 0)
        {
            //Pop the first node
            curNode = openNodes[0];
            openNodes.RemoveAt(0);
            
            //For each of its neighbors, get the distance to that neighbor if it exists, and add the distance from start to the current node to that distance to get the distance from start to that neighbor through the current node.
            for(int i = 0; i < 4; i++)
            {
                curNeighbor = curNode.neighbors[i];

                if(curNeighbor == null)
                {
                    continue;
                }

                curDistance = Tile.terrainPenalty[(int)curNeighbor.Type] + distanceFromStart[curNode];

                //If the neighbor has already been found, if the distance through the cur tile to the neighbor is less than the current known shortest distance, change the neighbor's tile origin and distance.
                if(tileOrigins.ContainsKey(curNeighbor) && (distanceFromStart[curNeighbor] > curDistance))
                {
                    tileOrigins[curNeighbor] = curNode;
                    distanceFromStart[curNeighbor] = curDistance;
                }
                else if(!tileOrigins.ContainsKey(curNeighbor) && curDistance <= remainingEnergy) //Else if this is the first time the tile has been found, add it to open nodes and set the tile origins and distance from start.
                {
                    tileOrigins[curNeighbor] = curNode;
                    distanceFromStart[curNeighbor] = curDistance;
                    openNodes.Add(curNeighbor);
                }
                //If the neighbor can not physically be reached, do not add it to open nodes.
            }
        }

        //If the destination tile was not reached, there is no path to that tile.
        if(!tileOrigins.ContainsKey(_tiles[dest]))
        {
            return null;
        }

        curNode = _tiles[dest];
        path.Add(curNode);

        //Recreate the path.
        while(curNode.Position != start)
        {
            curNode = tileOrigins[curNode];
            path.Insert(0, curNode);
        }
        path.Insert(0, _tiles[start]);
        return path;
    }