如何根据g分数修正路径?

我构建了一个A*引擎,用于在由方形节点组成的网格中寻找最佳路径。每个节点有八个可能的连接到其他节点(上、下、左、右、左上、右上、左下、右下)。

我遇到了一个问题,无法根据节点的g分数来修正路径。这种修正必须在发现当前节点的连接节点(相邻节点)时进行,对于每个已经在开放列表中但不在关闭列表中或不可通行的相邻节点,我需要做一些检查,以确定该节点是否更适合路径,并使用g分数来做出决定。问题是我不知道该如何做。

我有一个简单的代码,用于发现相邻节点:

private ArrayList discoverChildren(Node parent) {    ArrayList discoveredNodes = new ArrayList();    if (parent.upNode != null &&         parent.upNode.isWalkable &&        !closedList.Contains(parent.upNode)) {        if (!openList.Contains(parent.upNode)) {            openList.Add(parent.upNode);            parent.upNode.parent = parent;            calculateScores(parent.upNode);            discoveredNodes.Add(parent.upNode);        } else {            // 在这里我必须检查是否需要更改路径并更新分数        }           } ...

回答:

我找到了一个解决方案,但该解决方案在一种情况下无法给出正确的路径。我将公布我所有的代码,以便大家可以改进和使用这个解决方案。如果你以任何方式改进了这个代码,请在这里发布,以便我们可以看到你的解决方案。谢谢!

首先,我在我的calculateScore(…)方法及其调用的方法中进行了更改。然后,我实现了之前帖子中缺失的代码。

节点类:

using System;using UnityEngine;using System.Collections;public class Node {    public Cell cell {get; set;} // 与此节点链接的Unity组件    public bool isWalkable {get; set;}    public int x {get; set;}    public int z {get; set;}    public Node rightNode {get; set;}    public Node leftNode {get; set;}    public Node upNode {get; set;}    public Node downNode {get; set;}    public Node upLeftNode {get; set;}    public Node upRightNode {get; set;}    public Node downLeftNode {get; set;}    public Node downRightNode {get; set;}    public Node[] children {get; set;}    public Node parent {get; set;}    public int gScore {get; set;}    public int hScore {get; set;}    public int fScore {get; set;}    public void setGScore(Node start, bool isPenaltyApplied) {        if (start.parent == null) {            gScore = 0;        } else {            if (isPenaltyApplied) {                gScore = start.parent.gScore + 14;            } else {                gScore = start.parent.gScore + 10;            }        }    }    public void setHScore(Node destination, bool isPenaltyApplied) {        if (parent == null) {            hScore = 0;            return;        }        if (parent.hScore == 0) {            hScore = Node.calculateHeuristic(this, destination) * 10;        } else {            hScore = parent.hScore + 10;        }        if (isPenaltyApplied) {            hScore += 10;        }    }    public void updateFScore() {        fScore = gScore + hScore;    }    public Node[] getAllChildren() {        if (this.children == null) {            Node[] children = new Node[8];            children[0] = rightNode;            children[1] = leftNode;            children[2] = upNode;            children[3] = downNode;            children[4] = upLeftNode;            children[5] = upRightNode;            children[6] = downLeftNode;            children[7] = downRightNode;            this.children = children;        }        return this.children;    }    public static int calculateHeuristic(Node from, Node to) {        int distance = 0;        int startX = from.x;        int startZ = from.z;        int destinationX = to.x;        int destinationZ = to.z;        while (startX != destinationX) {            if (startX < destinationX) {                startX++;            } else if (startX > destinationX) {                startX--;            }            distance++;        }        while (startZ != destinationZ) {            if (startZ < destinationZ) {                startZ++;            } else if (startZ > destinationZ) {                startZ--;            }            distance++;        }        return distance;     }}

引擎类:

using System;using UnityEngine;using System.Collections;public class Engine {    private ArrayList openList;    private ArrayList closedList;    private ArrayList potentialPaths;    public ArrayList path {get; private set;}    public Node startNode {get; set;}    public Node destinationNode {get; set;}    public bool isPathFound {get; set;}    public void startEngine() {        if (startNode != null && destinationNode != null) {            openList = new ArrayList();            closedList = new ArrayList();            traverseNodes();            if (isPathFound) {                path = findPath();            }        }    }    private ArrayList findPath() {        ArrayList bestPath = new ArrayList();        Node currentNode = destinationNode;        while (!object.ReferenceEquals(currentNode, startNode)) {            bestPath.Add(currentNode);            clearUnnecessaryNode(currentNode);            currentNode = currentNode.parent;        }        bestPath.Add(currentNode);        return bestPath;    }    private void clearUnnecessaryNode(Node node) {        Node firstParent = node.parent;        if (object.ReferenceEquals(firstParent, startNode)) {            return;        }        Node secondParent = firstParent.parent;        if (object.ReferenceEquals(node.upRightNode, secondParent)) {            if (node.rightNode != null &&                node.upNode != null &&                node.rightNode.isWalkable &&                node.upNode.isWalkable) {                node.parent = secondParent;                path.Remove(firstParent);            }        }        if (object.ReferenceEquals(node.upLeftNode, secondParent)) {            if (node.leftNode != null &&                node.upNode != null &&                node.leftNode.isWalkable &&                node.upNode.isWalkable) {                node.parent = secondParent;                path.Remove(firstParent);            }        }        if (object.ReferenceEquals(node.downLeftNode, secondParent)) {            if (node.leftNode != null &&                node.downNode != null &&                node.leftNode.isWalkable &&                node.downNode.isWalkable) {                node.parent = secondParent;                path.Remove(firstParent);            }        }        if (object.ReferenceEquals(node.downRightNode, secondParent)) {            if (node.rightNode != null &&                node.downNode != null &&                node.rightNode.isWalkable &&                node.downNode.isWalkable) {                node.parent = secondParent;                path.Remove(firstParent);            }        }    }    private void traverseNodes() {        Node bestNode = startNode;        openList.Add(bestNode);        calculateScores(bestNode, false);        while (!object.ReferenceEquals(bestNode, destinationNode)) {            discoverChildren(bestNode);            closedList.Add(bestNode);            openList.Remove(bestNode);            bestNode = chooseBestNode(bestNode);            if (bestNode == null) {                // 未找到路径                return;            }            if (object.ReferenceEquals(bestNode, destinationNode)) {                closedList.Add(bestNode);            }        }        // 成功        isPathFound = true;    }    private void calculateScores(Node node, bool isPenaltyApplied) {        node.setGScore(startNode, isPenaltyApplied);        node.setHScore(destinationNode, isPenaltyApplied);        node.updateFScore();    }    private ArrayList discoverChildren(Node parent) {        ArrayList discoveredNodes = new ArrayList();        int currentCost = 0;        int newCost = 0;        if (parent.upNode != null &&             parent.upNode.isWalkable &&            !closedList.Contains(parent.upNode)) {            if (!openList.Contains(parent.upNode)) {                openList.Add(parent.upNode);                parent.upNode.parent = parent;                calculateScores(parent.upNode, false);                discoveredNodes.Add(parent.upNode);            } else {                currentCost = parent.upNode.parent.gScore + parent.upNode.gScore;                newCost = parent.gScore + parent.upNode.gScore;                if (newCost < currentCost) {                    parent.upNode.parent = parent;                    calculateScores(parent.upNode, false);                }            }               }        if (parent.downNode != null &&             parent.downNode.isWalkable &&            !closedList.Contains(parent.downNode)) {            if (!openList.Contains(parent.downNode)) {                openList.Add(parent.downNode);                parent.downNode.parent = parent;                calculateScores(parent.downNode, false);                discoveredNodes.Add(parent.downNode);            } else {                currentCost = parent.downNode.parent.gScore + parent.downNode.gScore;                newCost = parent.gScore + parent.downNode.gScore;                if (newCost < currentCost) {                    parent.downNode.parent = parent;                    calculateScores(parent.downNode, false);                }            }        }        if (parent.leftNode != null &&             parent.leftNode.isWalkable &&            !closedList.Contains(parent.leftNode)) {            if (!openList.Contains(parent.leftNode)) {                openList.Add(parent.leftNode);                parent.leftNode.parent = parent;                calculateScores(parent.leftNode, false);                discoveredNodes.Add(parent.leftNode);            } else {                currentCost = parent.leftNode.parent.gScore + parent.leftNode.gScore;                newCost = parent.gScore + parent.leftNode.gScore;                if (newCost < currentCost) {                    parent.leftNode.parent = parent;                    calculateScores(parent.leftNode, false);                }            }        }        if (parent.rightNode != null &&             parent.rightNode.isWalkable &&            !closedList.Contains(parent.rightNode)) {            if (!openList.Contains(parent.rightNode)) {                openList.Add(parent.rightNode);                parent.rightNode.parent = parent;                calculateScores(parent.rightNode, false);                discoveredNodes.Add(parent.rightNode);            } else {                currentCost = parent.rightNode.parent.gScore + parent.rightNode.gScore;                newCost = parent.gScore + parent.rightNode.gScore;                if (newCost < currentCost) {                    parent.rightNode.parent = parent;                    calculateScores(parent.rightNode, false);                }            }        }        if (parent.upRightNode != null &&             parent.upNode != null &&            parent.rightNode != null &&            parent.upRightNode.isWalkable &&             parent.upNode.isWalkable &&            parent.rightNode.isWalkable &&            !closedList.Contains(parent.upRightNode)) {            if (!openList.Contains(parent.upRightNode)) {                openList.Add(parent.upRightNode);                parent.upRightNode.parent = parent;                calculateScores(parent.upRightNode, true);                discoveredNodes.Add(parent.upRightNode);            } else {                currentCost = parent.upRightNode.parent.gScore + parent.upRightNode.gScore;                newCost = parent.gScore + parent.upRightNode.gScore;                if (newCost < currentCost) {                    parent.upRightNode.parent = parent;                    calculateScores(parent.upRightNode, true);                }            }        }        if (parent.upLeftNode != null &&             parent.upNode != null &&            parent.leftNode != null &&            parent.upLeftNode.isWalkable &&             parent.upNode.isWalkable &&            parent.leftNode.isWalkable &&            !closedList.Contains(parent.upLeftNode)) {            if (!openList.Contains(parent.upLeftNode)) {                openList.Add(parent.upLeftNode);                parent.upLeftNode.parent = parent;                calculateScores(parent.upLeftNode, true);                discoveredNodes.Add(parent.upLeftNode);            } else {                currentCost = parent.upLeftNode.parent.gScore + parent.upLeftNode.gScore;                newCost = parent.gScore + parent.upLeftNode.gScore;                if (newCost < currentCost) {                    parent.upLeftNode.parent = parent;                    calculateScores(parent.upLeftNode, true);                }            }        }        if (parent.downRightNode != null &&             parent.downNode != null &&            parent.rightNode != null &&            parent.downRightNode.isWalkable &&             parent.downNode.isWalkable &&            parent.rightNode.isWalkable &&            !closedList.Contains(parent.downRightNode)) {            if (!openList.Contains(parent.downRightNode)) {                openList.Add(parent.downRightNode);                parent.downRightNode.parent = parent;                calculateScores(parent.downRightNode, true);                discoveredNodes.Add(parent.downRightNode);            } else {                currentCost = parent.downRightNode.parent.gScore + parent.downRightNode.gScore;                newCost = parent.gScore + parent.downRightNode.gScore;                if (newCost < currentCost) {                    parent.downRightNode.parent = parent;                    calculateScores(parent.downRightNode, true);                }            }        }        if (parent.downLeftNode != null &&             parent.downNode != null &&            parent.leftNode != null &&            parent.downLeftNode.isWalkable &&             parent.downNode.isWalkable &&            parent.leftNode.isWalkable &&            !closedList.Contains(parent.downLeftNode)) {            if (!openList.Contains(parent.downLeftNode)) {                openList.Add(parent.downLeftNode);                parent.downLeftNode.parent = parent;                calculateScores(parent.downLeftNode, true);                discoveredNodes.Add(parent.downLeftNode);            } else {                currentCost = parent.downLeftNode.parent.gScore + parent.downLeftNode.gScore;                newCost = parent.gScore + parent.downLeftNode.gScore;                if (newCost < currentCost) {                    parent.downLeftNode.parent = parent;                    calculateScores(parent.downLeftNode, true);                }            }        }        return discoveredNodes;    }    private Node chooseBestNode(Node closedNode) {        if (openList.Count == 0) {            return null;        }        Node bestNode = (Node)openList[0];        foreach (Node node in openList) {            if (node.fScore < bestNode.fScore) {                bestNode = node;            } else if (node.fScore == bestNode.fScore) {                if (node.gScore < bestNode.gScore) {                    bestNode = node;                } else if (object.ReferenceEquals(node, closedNode.upNode) ||                    object.ReferenceEquals(node, closedNode.leftNode) ||                    object.ReferenceEquals(node, closedNode.rightNode) ||                    object.ReferenceEquals(node, closedNode.downNode)) {                    // 优先考虑不在当前单元格角落的单元格                    bestNode = node;                }            }        }        return bestNode;    }}

Related Posts

L1-L2正则化的不同系数

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

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

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

f1_score metric in lightgbm

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

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

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

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

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

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

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

发表回复

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