Пример #1
0
        /// <summary>
        /// Performs the visit part of Depth First Search
        /// Reference: DFS Algorithm taken from introduction to algorithms book, page 604
        /// </summary>
        /// <param name="nodes">List of nodes</param>
        /// <param name="n">Node to visit</param>
        /// <param name="time">Time taken to visit node</param>
        /// <returns></returns>
        private int DFSVisit(List <DFSNode> nodes, DFSNode n, int time)
        {
            // Increment time, assign discovered time (n.DiscoverTime) and new color to node
            // Gray = Visited, but isn't finished with this node yet
            time++;
            n.DiscoverTime = time;
            n.Color        = DFSNode.Colors.Grey;

            foreach (var edge in _edges[n.Node])
            {
                // Get the first node, which is pointed to by the current node. Other ordering could also be used
                var dfsNode = nodes.First(dfsnode => dfsnode.Node == edge.In);

                if (dfsNode.Color == DFSNode.Colors.White)
                {
                    time = DFSVisit(nodes, dfsNode, time);
                }
            }

            // We've finished visiting this node, and is able to set the color to black
            // and set the finish time (v.FinisedTime)
            n.Color = DFSNode.Colors.Black;
            time++;
            n.FinishedTime = time;
            return(time);
        }
Пример #2
0
    public override void FindPath(Vector2 startPosition, Vector2 targetPosition)
    {
        // Start stopwatch.
        stopwatch.Restart();
        stopwatch.Start();

        // Find start and end node positions.
        DFSNode startNode  = (DFSNode)grid.NodeFromWorldPoint(startPosition);
        DFSNode targetNode = (DFSNode)grid.NodeFromWorldPoint(targetPosition);

        // Initalise Lists & HastSets.
        List <DFSNode>  visitedSet = new List <DFSNode>();
        List <DFSNode>  order      = new List <DFSNode>();
        Stack <DFSNode> openSet    = new Stack <DFSNode>();

        startNode.History = new List <DFSNode>();
        visitedSet.Add(startNode);
        openSet.Push(startNode);  // Add starting node to open set, we start searching from here.

        while (openSet.Count > 0) // While there are nodes in the open set, loop.
        {
            DFSNode currentNode = openSet.Pop();

            if (!order.Contains(currentNode))
            {
                order.Add(currentNode);
            }

            foreach (DFSNode neighbourNode in grid.GetNeighbours(currentNode))     // Loop over each neighbour of the current node.
            {
                if (!neighbourNode.Walkable || visitedSet.Contains(neighbourNode)) // If the neighbour is not walkable, or has already been sorted into the closed set...
                {
                    continue;
                }

                neighbourNode.History = new List <DFSNode>(currentNode.History);
                neighbourNode.History.Add(currentNode);
                visitedSet.Add(neighbourNode);
                openSet.Push(neighbourNode);

                if (!order.Contains(neighbourNode))
                {
                    order.Add(neighbourNode);
                }

                if (neighbourNode == targetNode) // If we have reached the target node...
                {
                    neighbourNode.History.Add(neighbourNode);
                    RetracePath(targetNode, order.ConvertAll(x => (Node)x));
                    openSet.Clear();
                    stopwatch.Stop();
                    break;
                }
            }
        }

        waypoints = RetracePath(targetNode, order.ConvertAll(x => (Node)x));
        unit.PathToPosition(startPosition, targetPosition, waypoints);
    }
Пример #3
0
        public List <DFSNode> GetDFSNodes()
        {
            List <DFSNode> dfsNodes = new List <DFSNode>();

            foreach (DfsNode dfsNodeInformation in DfsNode.GetInstances())
            {
                DFSNode dfsNodeData = new DFSNode(dfsNodeInformation.Name, dfsNodeInformation.Root, dfsNodeInformation.Description, dfsNodeInformation.Timeout);

                dfsNodes.Add(dfsNodeData);
            }

            return(dfsNodes);
        }
Пример #4
0
    /// <summary>
    /// Retrace the found path from the start to end node, including the order that the path was found in.
    /// </summary>
    protected override Vector2[] RetracePath(Node endNode, List <Node> order)
    {
        List <Node> path        = new List <Node>();
        DFSNode     currentNode = (DFSNode)endNode;

        path = currentNode.History.ConvertAll(x => (Node)x);
        path[0].IsStartNode = true;
        endNode.IsEndNode   = true;
        grid.Path           = path;
        grid.Order          = order.ConvertAll(x => (Node)x);
        grid.ShowFinalPath();
        nodesVisitedText.text = "Nodes Visited: " + order.Count + " in " + stopwatch.ElapsedMilliseconds + "ms";

        Vector2[] waypoints = ConvertToWaypoints(path);
        return(waypoints);
    }
Пример #5
0
 public bool checkDFSNodeInStack(DFSNode node)
 {
     foreach (DFSNode item in this.DFSNodes)
     {
         if (item.Equals(node))
         {
             Console.WriteLine("Node is in stack already u f*****g numb");
             return true;
         }
     }
     return false;
 }
Пример #6
0
        public void getDFSChildren(DFSNode node)
        {
            int x = node.X;
            int y = node.Y;
            if (!checkRightSide())
            {
                DFSNode rightChild = new DFSNode(x + 1, y);
                rightChild.ParentNode = node;
                if (!checkDFSNodeInStack(rightChild))
                {
                    node.RightChild = rightChild;
                }
            }

            if (!checkTopSide())
            {
                DFSNode topChild = new DFSNode(x, y + 1);
                topChild.ParentNode = node;
                if (!checkDFSNodeInStack(topChild))
                    node.TopChild = topChild;
            }

            if (!checkLeftSide())
            {
                DFSNode leftChild = new DFSNode(x - 1, y);
                leftChild.ParentNode = node;
                if (!checkDFSNodeInStack(leftChild))
                    node.LeftChild = leftChild;
            }

            if (!checkBottomSide())
            {
                DFSNode bottomChild = new DFSNode(x, y - 1);
                bottomChild.ParentNode = node;
                if (!checkDFSNodeInStack(bottomChild))
                    node.BottomChild = bottomChild;
            }
        }
    /// <summary>
    /// Create a new instance of the grid, instantiating the corresponding active algorithms nodes.
    /// </summary>
    public void CreateGrid()
    {
        CheckExistingGrid();

        grid = new Node[gridSizeX, gridSizeY];
        Vector2 bottomLeft = (Vector2)transform.position - Vector2.right * gridWorldSize.x / 2 - Vector2.up * gridWorldSize.y / 2; // Calculate the bottom left position of the grid by starting from the centre (transform.position) and subtracting half the length and height of the grid.

        // Cycle through every position of the grid.
        for (int y = 0; y < gridSizeY; y++)
        {
            for (int x = 0; x < gridSizeX; x++)
            {
                Vector2 worldPoint = bottomLeft + Vector2.right * (x * nodeDiameter + nodeRadius) + Vector2.up * (y * nodeDiameter + nodeRadius); // Calculate position the node is in the world based on position in the grid and node size.
                bool    walkable   = true;                                                                                                        // Flag as not being obstructed by default.

                // CircleCast at the current position of the grid to check if there are any obstacles, useful for adapting to level design changes.
                if (Physics2D.CircleCast(worldPoint, nodeRadius, Vector2.zero, 0.5f, unwalkableMask))
                {
                    walkable = false; // Flag as being obstructed if an obstacle was overalpping the circlecast.
                }

                // Instantiate node game object and scale to set size.
                GameObject _nodeGO = Instantiate(node, worldPoint, Quaternion.identity);
                _nodeGO.transform.localScale = Vector3.one * (nodeDiameter - distanceBetweenNodes);

                // Assign active algorithms node class to the node game object and store at the current grid position.
                switch (PathfinderFactory.ActiveAlgorithm)
                {
                case PathfinderFactory.Pathfinding.AStar:
                    AStarNode _aStarNode = _nodeGO.AddComponent <AStarNode>();
                    _aStarNode.SetValues(walkable, worldPoint, x, y);
                    grid[x, y] = _aStarNode;
                    break;

                case PathfinderFactory.Pathfinding.Dijkstra:
                    DijkstraNode _dijkstraNode = _nodeGO.AddComponent <DijkstraNode>();
                    _dijkstraNode.SetValues(walkable, worldPoint, x, y);
                    grid[x, y] = _dijkstraNode;
                    break;

                case PathfinderFactory.Pathfinding.BFS:
                    BFSNode _BFSNode = _nodeGO.AddComponent <BFSNode>();
                    _BFSNode.SetValues(walkable, worldPoint, x, y);
                    grid[x, y] = _BFSNode;
                    break;

                case PathfinderFactory.Pathfinding.DFS:
                    DFSNode _DFSNode = _nodeGO.AddComponent <DFSNode>();
                    _DFSNode.SetValues(walkable, worldPoint, x, y);
                    grid[x, y] = _DFSNode;
                    break;
                }
            }
        }

        if (previousObstaclePoints != null) // If any previous obstacles are recorded...
        {
            // Loop over each, calculate the node that has taken their position and flag them as not walkable.
            foreach (Vector2 point in previousObstaclePoints)
            {
                Node node = NodeFromWorldPoint(point);
                node.Walkable = false;
            }
        }

        if (previousStartPosition != Vector2.zero) // If a previous start position exists...
        {
            // Calculate the node that has taken its position and flag as start node.
            Node node = NodeFromWorldPoint(previousStartPosition);
            node.IsStartNode = true;
            PathfindingManager.instance.startNode = node.transform;
        }

        if (previousEndPosition != Vector2.zero) // If a previous end position exists...
        {
            // Calculate the node that has taken its position and flag as end node.
            Node node = NodeFromWorldPoint(previousEndPosition);
            node.IsEndNode = true;
            PathfindingManager.instance.endNode = node.transform;
        }

        UpdateNodeColours();
    }
Пример #8
0
    private void Update()
    {
        if (Input.GetMouseButtonDown(0) && !Input.GetKey(KeyCode.LeftControl))
        {
            Ray        ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit))
            {
                if (hit.transform.gameObject.GetComponent <DFSNode>() != null)
                {
                    if (begin == null)
                    {
                        begin = hit.transform.gameObject.GetComponent <DFSNode>();
                        hit.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.green;;
                    }
                    else
                    {
                        begin.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.white;
                        begin = hit.transform.gameObject.GetComponent <DFSNode>();
                        hit.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.green;;
                    }
                }
            }
        }

        if (Input.GetMouseButtonDown(1) && !Input.GetKey(KeyCode.LeftControl))
        {
            Ray        ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit))
            {
                if (hit.transform.gameObject.GetComponent <DFSNode>() != null)
                {
                    if (end == null)
                    {
                        end = hit.transform.gameObject.GetComponent <DFSNode>();
                        hit.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.red;;
                    }
                    else
                    {
                        end.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.white;
                        end = hit.transform.gameObject.GetComponent <DFSNode>();
                        hit.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.red;;
                    }
                }
            }
        }

        if (Input.GetKeyDown(KeyCode.C))
        {
            foreach (DFSNode node in pathNodes)
            {
                node.transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.white;
            }

            alreadyBeenNodes.Clear();
            nodeParent.Clear();
            pathNodes.Clear();
            toDoNodes.Clear();
            result.text = "Result:";
            loops       = 0;
        }
    }
Пример #9
0
    protected List <DFSNode> Generate(DFSNode start, DFSNode goal)
    {
        toDoNodes.Add(start);
        nodeParent.Add(start, null);

        while (toDoNodes.Count > 0)
        {
            DFSNode currentNode = toDoNodes[toDoNodes.Count - 1];

            alreadyBeenNodes.Add(currentNode);
            toDoNodes.Remove(currentNode);

            if (currentNode == goal)
            {
                DFSNode backTrack = goal;
                do
                {
                    pathNodes.Add(backTrack);
                    backTrack = nodeParent[backTrack];
                }while (backTrack != null);
                pathNodes.Reverse();

                if (loops > 0)
                {
                    loops--;
                    alreadyBeenNodes.Clear();
                    nodeParent.Clear();
                    pathNodes.Clear();
                    toDoNodes.Clear();
                    Generate(begin, end);
                    return(null);
                }
                else
                {
                    for (int i = 1; i < pathNodes.Count - 1; i++)
                    {
                        pathNodes[i].transform.gameObject.GetComponent <MeshRenderer>().material.color = Color.yellow;
                    }

                    sw.Stop();
                    result.text = "Result: " + sw.ElapsedMilliseconds + "ms & " + pathNodes.Count + " Nodes";
                    sw.Reset();
                    return(pathNodes);
                }
            }

            foreach (DFSNode nextNode in currentNode.connections)
            {
                if (toDoNodes.Contains(nextNode) | alreadyBeenNodes.Contains(nextNode))
                {
                    //Nothing
                }
                else
                {
                    toDoNodes.Add(nextNode);
                    nodeParent.Add(nextNode, currentNode);
                }
            }
        }
        return(null);
    }