Exemple #1
0
 void PaintPathBack(TileObject currentTile) //starting from the exit tile change the color of the tiles along the path
 {
     if (currentTile.IsStart == true)       // when you hit the start tile stop
     {
         return;
     }
     else if (currentTile.IsExit == true)// if the exit tile has no path to it stop
     {
         if (currentTile.PreviouseTile != null)
         {
             PaintPathBack(currentTile.PreviouseTile);
         }
     }
     else
     {
         currentTile.SetColor(Color.cyan);         //change the color of the tiles on the path
         PaintPathBack(currentTile.PreviouseTile); // calls it self again
     }
 }
        public List <Tile> FindPath(List <List <TileObject> > myList, TileObject startPoint, TileObject exitPoint, Vector2 gridLength)
        {
            //This seaction initalises the code used for the algorithm such as movement direction and heuristc
            int searchDirections;//is used to determine if you are allowed to move diagonal while searching for a path

            if (GameController.Diagonal == true)
            {
                searchDirections = 8;//search all squares touching yours
            }
            else
            {
                searchDirections = 4; //search up, down, left, right
            }
            int  searchType = 4;      // determines which directions the heuristic will check. same as above
            bool isEcludian = false;

            switch (GameController.SearchType)// 0 manhaton. 1 diagonal. 2 Ecludian
            {
            case 0:
                searchType = 4;
                isEcludian = false;
                break;

            case 1:
                searchType = 8;
                isEcludian = false;
                break;

            case 2:
                searchType = 8;
                isEcludian = true;
                break;
            }


            for (int X = 0; X < myList.Count; X++)//sets all the values to a high number as we canot store infinity in a float
            {
                for (int Y = 0; Y < myList[X].Count; Y++)
                {
                    myList[X][Y].EstimatedCost  = 999999;
                    myList[X][Y].HasBeenChanged = false;
                    myList[X][Y].HasBeenChecked = false;
                }
            }


            List <TileObject> searchList = new List <TileObject>();                         //this is the open list which is used to store the current possible path options

            myList[(int)exitPoint.Position.x][(int)exitPoint.Position.y].EstimatedCost = 0; // set the exit node estimated cost to 0 so we can use it as the start point for the heuristic
            Vector2 cT        = exitPoint.Position;
            int     stopper   = 0;
            int     stop      = 100000;//the maximuim limit the algorithm can cycle before it is stopped. This is put in to reduced the number of computer crashes due to bad logic
            int     searchRef = 0;

            searchList.Add(myList[(int)exitPoint.Position.x][(int)exitPoint.Position.y]);
            float      bakeMod     = 1f;//can be used to adjust the amount of influence the heuristic has on path finding. make it lower to have it closer to a Dijkstras or higher makes it closer to Best first search. I have left it at 1 as it shows it in its best comparison for this application
            Vector2    tileToCheck = cT;
            TileObject tileBeingChecked;
            float      moveCost = 1f;

            while (stopper < stop)                   //while there are unchecked nodes or while the stoppper is below its allowed limit
            {
                for (int i = 0; i < searchType; i++) // if its 4 it only checks up down left right. if its 8 it goes diagonal as well
                {
                    switch (i)                       //sets what tile to check next based on the position of the current tile. also sets the cost to move to that tile based to the searchtype settings
                    {
                    case 0:
                        tileToCheck = new Vector2(cT.x + 1, cT.y);    //right
                        moveCost    = 1;
                        break;

                    case 1:
                        tileToCheck = new Vector2(cT.x, cT.y + 1);    //up
                        moveCost    = 1;
                        break;

                    case 2:
                        tileToCheck = new Vector2(cT.x - 1, cT.y);    //left
                        moveCost    = 1;
                        break;

                    case 3:
                        tileToCheck = new Vector2(cT.x, cT.y - 1);    //down
                        moveCost    = 1;
                        break;

                    case 4:
                        tileToCheck = new Vector2(cT.x + 1, cT.y + 1);    //up right
                        moveCost    = 1.4f;
                        break;

                    case 5:
                        tileToCheck = new Vector2(cT.x + 1, cT.y - 1);    //down Right
                        moveCost    = 1.4f;
                        break;

                    case 6:
                        tileToCheck = new Vector2(cT.x - 1, cT.y - 1);    //down left
                        moveCost    = 1.4f;
                        break;

                    case 7:
                        tileToCheck = new Vector2(cT.x - 1, cT.y + 1);    //up right
                        moveCost    = 1.4f;
                        break;
                    }
                    if (isEcludian == true)// in an Ecludian Heuristic it is assumed that moving in any direction is the same cost and therefore the cost will allways be 1
                    {
                        moveCost = 1;
                    }
                    if (tileToCheck.x < gridLength.x && tileToCheck.x >= 0 && tileToCheck.y < gridLength.y && tileToCheck.y >= 0)// if the tile is not inside the grid skip it
                    {
                        tileBeingChecked = myList[(int)tileToCheck.x][(int)tileToCheck.y];
                        if (myList[(int)cT.x][(int)cT.y].EstimatedCost + (moveCost * bakeMod) < tileBeingChecked.EstimatedCost && tileBeingChecked.HasBeenChanged == false) //checks if the cost of the current tile is less than the current lowest cost to get to that tile
                        {
                            tileBeingChecked.EstimatedCost  = myList[(int)cT.x][(int)cT.y].EstimatedCost + (moveCost * bakeMod);                                            // sets the cost of the node by adding the movement cost to the tile from the current tile
                            tileBeingChecked.HasBeenChanged = true;
                            searchList.Add(tileBeingChecked);                                                                                                               //adds the tileBeingChecked to the open list
                        }
                    }
                }
                searchRef = 0;
                for (int i = 0; i < searchList.Count; i++)//finds the next lowest tile to the Heuristic to set is value
                {
                    if (searchList[i].EstimatedCost < searchList[searchRef].EstimatedCost)
                    {
                        searchRef = i;
                    }
                }

                if (searchList.Count == 0)//once all tiles have been set break the while loop
                {
                    Debug.Log("No more options");
                    break;
                }
                cT = searchList[searchRef].Position;
                searchList.RemoveAt(searchRef);
            }
            Debug.Log("Set Path");



            List <Tile> changeLog = new List <Tile>(); //Creates a new List to recorded the changes made by the algorithm

            for (int X = 0; X < myList.Count; X++)     //sets all the values to a high number as we canot store infinity in a int
            {
                for (int Y = 0; Y < myList[X].Count; Y++)
                {
                    myList[X][Y].Cost           = 999999;
                    myList[X][Y].HasBeenChanged = false;
                    myList[X][Y].HasBeenChecked = false;
                }
            }
            myList[(int)startPoint.Position.x][(int)startPoint.Position.y].Cost = 0;
            cT      = startPoint.Position;
            stopper = 0;
            stop    = 100000;
            searchList.Clear();
            searchList = new List <TileObject>();
            searchRef  = 0;
            searchList.Add(myList[(int)startPoint.Position.x][(int)startPoint.Position.y]);
            while (stopper < stop)                         //while there are unchecked nodes or while the stoppper is below its allowed limit
            {
                for (int i = 0; i < searchDirections; i++) // if its 4 it only checks up down left right. if its 8 it goes diagonal as well
                {
                    switch (i)                             //sets what tile to check next based on the position of the current tile. also sets the cost to move to that tile based to the search direction setting
                    {
                    case 0:
                        tileToCheck = new Vector2(cT.x + 1, cT.y);    //right
                        moveCost    = 1;
                        break;

                    case 1:
                        tileToCheck = new Vector2(cT.x, cT.y + 1);    //up
                        moveCost    = 1;
                        break;

                    case 2:
                        tileToCheck = new Vector2(cT.x - 1, cT.y);    //left
                        moveCost    = 1;
                        break;

                    case 3:
                        tileToCheck = new Vector2(cT.x, cT.y - 1);    //down
                        moveCost    = 1;
                        break;

                    case 4:
                        tileToCheck = new Vector2(cT.x + 1, cT.y + 1);    //up right
                        moveCost    = 1.4f;
                        break;

                    case 5:
                        tileToCheck = new Vector2(cT.x + 1, cT.y - 1);    //down Right
                        moveCost    = 1.4f;
                        break;

                    case 6:
                        tileToCheck = new Vector2(cT.x - 1, cT.y - 1);    //down left
                        moveCost    = 1.4f;
                        break;

                    case 7:
                        tileToCheck = new Vector2(cT.x - 1, cT.y + 1);    //up right
                        moveCost    = 1.4f;
                        break;
                    }

                    if (tileToCheck.x < gridLength.x && tileToCheck.x >= 0 && tileToCheck.y < gridLength.y && tileToCheck.y >= 0)// if the tile is not inside the grid skip it
                    {
                        tileBeingChecked = myList[(int)tileToCheck.x][(int)tileToCheck.y];
                        if (tileBeingChecked.IsWall == false && tileBeingChecked.HasBeenChanged == false)
                        {
                            if (myList[(int)cT.x][(int)cT.y].Cost + moveCost < tileBeingChecked.Cost || tileBeingChecked.HasBeenChanged == false)//checks if the cost of the current tile is less than the current lowest cost to get to that tile
                            {
                                tileBeingChecked.PreviouseTile  = myList[(int)cT.x][(int)cT.y];
                                tileBeingChecked.Cost           = myList[(int)cT.x][(int)cT.y].Cost + moveCost; // sets the cost of the tile by adding the movement cost to the node from the current tile
                                tileBeingChecked.HasBeenChanged = true;
                                tileBeingChecked.TileColor      = Color.blue;                                   //changes the color that will be stored to blue as blue is the color used to represent tiles in the open set
                                searchList.Add(tileBeingChecked);                                               //adds the tileBeingChecked to the open list
                                changeLog.Add(new Tile(tileBeingChecked));                                      //adds the action to the change log
                            }
                        }
                    }
                }
                myList[(int)cT.x][(int)cT.y].TileColor = Color.grey;   //changes the color of the tile to grey as that is the colour used to show that it has been checked
                changeLog.Add(new Tile(myList[(int)cT.x][(int)cT.y])); //adds the action to the change log
                searchRef = 0;                                         //sets the referance to 0 so it starts at the first item in the open list
                for (int i = 0; i < searchList.Count; i++)
                {
                    if (searchList[i].ActualCost() < searchList[searchRef].ActualCost())//if searchlist[i] has a lower actual cost then the current searchRef tile that tile is now the searchRef tile
                    {
                        searchRef = i;
                    }
                    else if (searchList[i].ActualCost() == searchList[searchRef].ActualCost()) //if searchlist[i] has the same actual cost as current searchRef tile......
                    {
                        if (searchList[i].EstimatedCost < searchList[searchRef].EstimatedCost) //if that tile has a lower Heurstic cost then the current SearchRef tile that tile is now the searchRef tile
                        {
                            searchRef = i;
                        }
                    }
                }

                if (searchList.Count == 0)//if the search list is empty break the while loop
                {
                    Debug.Log("No more options");
                    break;
                }
                if (searchList[searchRef].Position == exitPoint.Position)// if you found the exit break the while loop
                {
                    Debug.Log("Found Exit");
                    break;
                }
                cT = searchList[searchRef].Position; //set the lowest found seachRef to the current tile
                searchList.RemoveAt(searchRef);      //Remove the current tile from the open set
                stopper += 1;                        //increment stopper
            }
            Debug.Log("FoundPath");
            GameController.NumberOfTilesSearched = (changeLog.Count / 2); // the number of tiles checked is half the number of actions taken to find the tiles as each tile that is checked is first added to teh open set and then checked after
            return(changeLog);                                            //send the recorded chang log back to the pathfinder interface
        }
Exemple #3
0
        public List <Tile> FindPath(List <List <TileObject> > myList, TileObject startPoint, TileObject exitPoint, Vector2 gridLength)
        {
            //This seaction initalises the code used for the algorithm such as movement direction
            int searchDirections;//is used to determine if you are allowed to move diagonal while searching for a path

            if (GameController.Diagonal == true)
            {
                searchDirections = 8;//search all squares touching yours
            }
            else
            {
                searchDirections = 4;                  //search up, down, left, right
            }
            List <Tile> changeLog = new List <Tile>(); //Creates a new List to recorded the changes made by the algorithm

            for (int X = 0; X < myList.Count; X++)
            {
                for (int Y = 0; Y < myList[X].Count; Y++)//sets all the values to a high number as we canot store infinity in a int
                {
                    myList[X][Y].Cost           = 999999;
                    myList[X][Y].HasBeenChanged = false;
                    myList[X][Y].HasBeenChecked = false;
                }
            }


            List <TileObject> searchList = new List <TileObject>();                  //this is the open list which is used to store the current possible path options

            myList[(int)startPoint.Position.x][(int)startPoint.Position.y].Cost = 0; // set the start tile cost to 0 so we can use it as the start point
            Vector2 cT        = startPoint.Position;
            int     stopper   = 0;
            int     stop      = 100000;//the maximuim limit the algorithm can cycle before it is stopped. This is put in to reduced the number of computer crashes due to bad logic
            int     searchRef = 0;

            searchList.Add(myList[(int)startPoint.Position.x][(int)startPoint.Position.y]);
            Vector2    tileToCheck = cT;
            TileObject tileBeingChecked;
            float      moveCost = 1;

            while (stopper < stop)                         //while there are unchecked nodes or while the stoppper is below its allowed limit
            {
                for (int i = 0; i < searchDirections; i++) // if its 4 it only checks up down left right. if its 8 it goes diagonal as well
                {
                    switch (i)                             //sets what tile to check next based on the position of the current tile. also sets the cost to move to that tile based to the search direction setting
                    {
                    case 0:
                        tileToCheck = new Vector2(cT.x + 1, cT.y);    //right
                        moveCost    = 1;
                        break;

                    case 1:
                        tileToCheck = new Vector2(cT.x, cT.y + 1);    //up
                        moveCost    = 1;
                        break;

                    case 2:
                        tileToCheck = new Vector2(cT.x - 1, cT.y);    //left
                        moveCost    = 1;
                        break;

                    case 3:
                        tileToCheck = new Vector2(cT.x, cT.y - 1);    //down
                        moveCost    = 1;
                        break;

                    case 4:
                        tileToCheck = new Vector2(cT.x + 1, cT.y + 1);    //up right
                        moveCost    = 1.4f;
                        break;

                    case 5:
                        tileToCheck = new Vector2(cT.x + 1, cT.y - 1);    //down Right
                        moveCost    = 1.4f;
                        break;

                    case 6:
                        tileToCheck = new Vector2(cT.x - 1, cT.y - 1);    //down left
                        moveCost    = 1.4f;
                        break;

                    case 7:
                        tileToCheck = new Vector2(cT.x - 1, cT.y + 1);    //up right
                        moveCost    = 1.4f;
                        break;
                    }


                    if (tileToCheck.x < gridLength.x && tileToCheck.x >= 0 && tileToCheck.y < gridLength.y && tileToCheck.y >= 0)// if the tile is not inside the grid skip it
                    {
                        tileBeingChecked = myList[(int)tileToCheck.x][(int)tileToCheck.y];
                        if (tileBeingChecked.IsWall == false)
                        {
                            if (myList[(int)cT.x][(int)cT.y].Cost + moveCost < tileBeingChecked.Cost || tileBeingChecked.HasBeenChanged == false)//checks if the cost of the current tile is less than the current lowest cost to get to that tile
                            {
                                tileBeingChecked.PreviouseTile  = myList[(int)cT.x][(int)cT.y];
                                tileBeingChecked.Cost           = myList[(int)cT.x][(int)cT.y].Cost + moveCost; // sets the cost of the tile by adding the movement cost to the tile from the current tile
                                tileBeingChecked.HasBeenChanged = true;
                                tileBeingChecked.TileColor      = Color.blue;                                   //changes the color that will be stored to blue as blue is the color used to represent tiles in the open set
                                searchList.Add(tileBeingChecked);                                               //adds the tileBeingChecked to the open list
                                changeLog.Add(new Tile(tileBeingChecked));                                      //adds the action to the change log
                            }
                        }
                    }
                }
                myList[(int)cT.x][(int)cT.y].HasBeenChecked = true;       //removes the node from the list so it doesnt check it again
                myList[(int)cT.x][(int)cT.y].TileColor      = Color.grey; //changes the color of the tile to grey as that is the colour used to show that it has been checked
                changeLog.Add(new Tile(myList[(int)cT.x][(int)cT.y]));    //adds the action to the change log
                searchRef = 0;                                            //sets the referance to 0 so it starts at the first item in the open list

                if (searchList.Count == 0)                                //if the search list is empty break the while loop
                {
                    Debug.Log("No more options");
                    break;
                }
                if (searchList[searchRef].Position == exitPoint.Position)// if you found the exit break the while loop
                {
                    Debug.Log("Found Exit");
                    break;
                }
                cT = searchList[searchRef].Position; //set the lowest found seachRef to the current tile
                searchList.RemoveAt(searchRef);      //Remove the current tile from the open set
                stopper += 1;                        //increment stopper
            }
            Debug.Log("FoundPath");
            GameController.NumberOfTilesSearched = (changeLog.Count / 2); // the number of tiles checked is half the number of actions taken to find the tiles as each tile that is checked is first added to teh open set and then checked after
            return(changeLog);                                            //send the recorded chang log back to the pathfinder interface
        }