A*(A星)算法未能完全正常工作

我在为大学作业实现A星搜索方法,所以需要从头开始构建,但我在使其正确工作方面遇到了些问题。以下是我问题的图片:

灰色方块 = 起点,绿色 = 终点,黄色 = 路径

如你所见,它确实找到了一个路径,但不是最简单的路径。

这是我的实现代码:

public List<node> updateAstar(){    //清空所有列表    openedNodes.Clear();    closedNodes.Clear();    nodesToLook.Clear();    //检查起点和终点是否正常    if(startPos!=null && endPos!=null){        float F;        node currentNote=Grid.getNodeAtPos(startPos);        openedNodes.Add(currentNote);        int i = 0;        int size = 100;        while(currentNote.type!=tilesType.END){            if(i<=size){ //调试用,防止无限循环                 nodesToLook.Clear();                foreach(node nearNode in currentNote.getNearestTiles()){                    if(closedNodes.Find(r => ((r.pos.x==nearNode.pos.x)&&(r.pos.y==nearNode.pos.y)))==null){                        nodesToLook.Add(nearNode);                    }                }                float bestValue=float.PositiveInfinity;                node bestNode=new node();                foreach(node lookingNode in nodesToLook){                    //检查当前节点是否不在关闭列表中                    if((closedNodes.Find(r => ((r.pos.x==lookingNode.pos.x)&&(r.pos.y==lookingNode.pos.y)))==null)                        &&(openedNodes.Find(r => ((r.pos.x==lookingNode.pos.x)&&(r.pos.y==lookingNode.pos.y)))==null)                         && lookingNode.type!=tilesType.BLOCK){                        //计算F=G+H                        //假设路径编号为0,仅为问题说明之用                        F=lookingNode.G[pathNumber]+lookingNode.H[pathNumber];                        if(F<bestValue){                            bestValue=F;                            bestNode=lookingNode;                        }else                            closedNodes.Add(lookingNode);                    }                }                openedNodes.Add(bestNode);                currentNote=bestNode;                i++;            }else{                Debug.Log("Error getting better path");                break;            }        }    }else Debug.Log("Current path does not have an startpos nor endpos");    return openedNodes;}

这是我如何实例化每个节点的代码(我将其保存在矩阵中):

coordinate posAux=new coordinate();this.myNodes=new node[columnNumber,lineNumber];this.lineNumber=lineNumber;this.columnNumber=columnNumber;for(int y=0;y<lineNumber;y++){                      // Y Desce = linhas    for(int x=0; x<columnNumber; x++){               // X vai pro lado = colunas        //根据矩阵位置创建节点        posAux.Set(x, y);        tilesType type;        node current=new node(posAux);        //更新上方和左侧节点        //"nodeDireita"表示右节点,"nodeEsquerda"表示左节点        if(x-1>=0){                             current.nodeEsquerda=myNodes[x-1, y];            myNodes[x-1, y].nodeDireita=current;        }                     if(y-1>=0){            current.nodeAcima=myNodes[x, y-1];            current.nodeAcima.nodeAbaixo=current;        }        //Unity相关内容,用于根据对象类型视觉设置节点类型        Collider[] colliders;        if((colliders = Physics.OverlapSphere(coordinate.gridToUnity(posAux), 3f)).Length >0){            foreach(Collider collider in colliders){                objScript obj = collider.gameObject.GetComponent<objScript>();                current.type=obj.type;                if(current.type==tilesType.START){                    path Path = new path (obj.pos, obj.posEnd, this);                    addPath (Path);                     Path.numeroPath=paths.IndexOf(Path);                }            }        }        myNodes[x,y]=current;    }}   //为节点添加H和G向量以支持多个路径//为每个节点创建支持多个路径的向量int numeroPaths = paths.Count;for (int y = 0; y < lineNumber; y++) {    for (int x = 0; x < columnNumber; x++) {         myNodes [x, y].H=new float[numeroPaths];        myNodes [x, y].G=new float[numeroPaths];    }}//为每个路径的每个节点计算启发式和G//计算每个路径中每个节点的启发式和Gforeach (path Path in paths) {    coordinate start=Path.startPos, end=Path.endPos;    int numeroPath=paths.IndexOf(Path);    for (int y = 0; y < lineNumber; y++) {        for (int x = 0; x < columnNumber; x++) {             coordinate pos = myNodes [x, y].pos;            //G和H使用曼哈顿距离            /*Mathf.Sqrt(Mathf.Pow((start.x - pos.x), 2) + Mathf.Pow((start.y - pos.y), 2)); 欧几里得距离 - 不适用于x.x */            myNodes [x, y].H[numeroPath]=Mathf.Abs(pos.x-end.x) + Mathf.Abs(pos.y-end.y);            myNodes [x, y].G[numeroPath]=Mathf.Abs(start.x-pos.x) + Mathf.Abs(start.y-pos.y);        }    }}

代码参考:

node 是一个自定义类,包含我使用曼哈顿公式定义的”G”和”H”,以及”x”、”y”、”BLOCK”或”NORMAL”(位置的可用性)

openedNodes 是一个列表,我将路径的正确节点放入其中

closedNodes 是我检查过的节点,但它们的”F”值较大;

nodesToLook 是用于检查的邻居节点。

感谢任何帮助。谢谢。


回答:

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注