예제 #1
0
    public void changepath(Vector3 s, Vector3 e)
    {
        grid.NodeItem StartNode = Grid.GetGrid(s);     //将开始和结束的坐标转换成节点坐标
        grid.NodeItem EndNode   = Grid.GetGrid(e);

        //定义开启列表和关闭列表
        //开启列表:存储可以成为下一个父节点的节点
        //关闭列表:存储成为过父节点的节点
        List <grid.NodeItem>    OpenList  = new List <grid.NodeItem>();
        HashSet <grid.NodeItem> CloseList = new HashSet <grid.NodeItem>();

        OpenList.Add(StartNode);

        while (OpenList.Count > 0)
        {
            //将开启列表的第一个节点记录下来
            grid.NodeItem ParentNode = OpenList[0];

            //遍历开启列表寻找parent
            for (int i = 0; i < OpenList.Count; i++)
            {
                //若开启列表中的节点的总花费更小或不变并且到终点的花费更小
                if (OpenList[i].fCost <= ParentNode.fCost && OpenList[i].gCost < ParentNode.gCost)
                {
                    ParentNode = OpenList[i];
                }
            }

            //将找到的父节点从开启列表中删除,加入关闭列表
            OpenList.Remove(ParentNode);
            CloseList.Add(ParentNode);

            //若父节点为终点节点则停止更新路程花费并且生成路径
            if (ParentNode == EndNode)
            {
                //生成路径
                ShowPath(StartNode, EndNode);
                return;
            }

            // 判断周围节点,选择一个最优的节点
            foreach (var item in Grid.GetNearNode(ParentNode))
            {
                // 如果是墙或者已经在关闭列表中
                if (item.isWall || CloseList.Contains(item))
                {
                    continue;
                }
                // 计算当前相领节点现开始节点距离
                int newCost = ParentNode.gCost + updatecost(ParentNode, item);
                // 如果距离更小,或者原来不在开始列表中
                if (newCost < item.gCost || !OpenList.Contains(item))
                {
                    // 更新与开始节点的距离
                    item.gCost = newCost;
                    // 更新与终点的距离
                    item.hCost = updatecost(item, EndNode);
                    // 更新父节点为当前选定的节点
                    item.parent = ParentNode;
                    // 如果节点是新加入的,将它加入打开列表中
                    if (!OpenList.Contains(item))
                    {
                        OpenList.Add(item);
                    }
                }
            }
        }
        ShowPath(StartNode, null);
    }