C# A* 算法 和 Dijkstra 算法 结合使用

本文介绍了在C#中如何使用A*和Dijkstra算法寻找路径,包括算法原理、节点表示、优先级评估以及示例代码。展示了如何在Node类中存储节点信息,并在Pathfinding类中实现这两种搜索算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前一篇:路径搜索算法 A* 算法 和 Dijkstra 算法-优快云博客文章浏览阅读330次,点赞9次,收藏5次。Dijkstra算法使用优先队列来管理待处理的节点,通过不断选择最短距离的节点进行扩展,更新相邻节点的距离值。Dijkstra算法使用一个距离数组来记录起始节点到每个节点的最短距离,通过选择当前距离最小的节点进行扩展,更新与该节点相邻节点的距离值。算法通过估价函数值 f(n) = g(n) + h(n) 来评估节点的优先级,其中 g(n) 是实际移动代价,h(n) 是从当前节点到目标节点的估计代价。请注意,这只是一个简单的示例,实际的路径搜索算法根据具体的场景和需求可能需要更复杂的实现。https://blog.youkuaiyun.com/hefeng_aspnet/article/details/135356191

以下是一个示例的C#语言下的A*算法和Dijkstra算法的完整代码:

using System;
using System.Collections.Generic;

public class Node
{
    public int x;
    public int y;
    public bool isWalkable;
    public List<Node> neighbors;
    public Node parent;
    public int gCost; // 从起点到当前节点的实际移动代价
    public int hCost; // 从当前节点到目标节点的估算代价

    public Node(int x, int y, bool isWalkable)
    {
        this.x = x;
        this.y = y;
        this.isWalkable = isWalkable;
        neighbors = new List<Node>();
    }

    public int fCost { get { return gCost + hCost; } }
}

public class Pathfinding
{
    // A*算法寻找路径
    public static List<Node> AStar(Node startNode, Node endNode)
    {
        List<Node> openSet = new List<Node>();
        HashSet<Node> closedSet = new HashSet<Node>();
        openSet.Add(startNode);

        while (openSet.Count > 0)
        {
            Node currentNode = openSet[0];
            for (int i = 1; i < openSet.Count; i++)
            {
                if (openSet[i].fCost < currentNode.fCost || openSet[i].fCost == currentNode.fCost && openSet[i].hCost < currentNode.hCost)
                {
                    currentNode = openSet[i];
                }
            }

            openSet.Remove(currentNode);
            closedSet.Add(currentNode);

            if (currentNode == endNode)
            {
                return GeneratePath(startNode, endNode);
            }

            foreach (Node neighbor in currentNode.neighbors)
            {
                if (!neighbor.isWalkable || closedSet.Contains(neighbor))
                {
                    continue;
                }

                int newCostToNeighbor = currentNode.gCost + GetDistance(currentNode, neighbor);
                if (newCostToNeighbor < neighbor.gCost || !openSet.Contains(neighbor))
                {
                    neighbor.gCost = newCostToNeighbor;
                    neighbor.hCost = GetDistance(neighbor, endNode);
                    neighbor.parent = currentNode;

                    if (!openSet.Contains(neighbor))
                    {
                        openSet.Add(neighbor);
                    }
                }
            }
        }

        return null;
    }

    // Dijkstra算法寻找路径
    public static List<Node> Dijkstra(Node startNode, Node endNode)
    {
        Dictionary<Node, int> distance = new Dictionary<Node, int>();
        Dictionary<Node, Node> previous = new Dictionary<Node, Node>();
        List<Node> unvisited = new List<Node>();

        foreach (Node node in GetAllNodes())
        {
            distance[node] = int.MaxValue;
            previous[node] = null;
            unvisited.Add(node);
        }

        distance[startNode] = 0;

        while (unvisited.Count > 0)
        {
            Node current = null;

            foreach (Node node in unvisited)
            {
                if (current == null || distance[node] < distance[current])
                {
                    current = node;
                }
            }

            if (current == endNode)
            {
                return GeneratePath(startNode, endNode);
            }

            unvisited.Remove(current);

            foreach (Node neighbor in current.neighbors)
            {
                int altDistance = distance[current] + GetDistance(current, neighbor);

                if (altDistance < distance[neighbor])
                {
                    distance[neighbor] = altDistance;
                    previous[neighbor] = current;
                }
            }
        }

        return null;
    }

    // 计算两个节点之间的距离
    public static int GetDistance(Node nodeA, Node nodeB)
    {
        int distanceX = Math.Abs(nodeA.x - nodeB.x);
        int distanceY = Math.Abs(nodeA.y - nodeB.y);

        return distanceX + distanceY;
    }

    // 生成路径
    public static List<Node> GeneratePath(Node startNode, Node endNode)
    {
        List<Node> path = new List<Node>();
        Node currentNode = endNode;

        while (currentNode != startNode)
        {
            path.Add(currentNode);
            currentNode = currentNode.parent;
        }

        path.Reverse();
        return path;
    }

    // 获取所有节点
    public static List<Node> GetAllNodes()
    {
        List<Node> allNodes = new List<Node>();

        // 在这里根据实际场景生成所有节点并设置邻居节点

        return allNodes;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Node startNode = new Node(0, 0, true); // 起始节点
        Node endNode = new Node(9, 9, true);  // 目标节点

        // 使用A*算法寻找路径
        List<Node> aStarPath = Pathfinding.AStar(startNode, endNode);

        if (aStarPath != null)
        {
            Console.WriteLine("A* Algorithm - Path Found:");
            foreach (Node node in aStarPath)
            {
                Console.WriteLine("(" + node.x + ", " + node.y + ")");
            }
        }
        else
        {
            Console.WriteLine("A* Algorithm - No Path Found.");
        }

        // 使用Dijkstra算法寻找路径
        List<Node> dijkstraPath = Pathfinding.Dijkstra(startNode, endNode);

        if (dijkstraPath != null)
        {
            Console.WriteLine("Dijkstra Algorithm - Path Found:");
            foreach (Node node in dijkstraPath)
            {
                Console.WriteLine("(" + node.x + ", " + node.y + ")");
            }
        }
        else
        {
            Console.WriteLine("Dijkstra Algorithm - No Path Found.");
        }
    }
}
        在示例代码中,我们定义了一个 Node 类来表示节点对象,该类包含节点的坐标、是否可行走、邻居节点等信息。然后,我们在 Pathfinding 类中实现了 A*算法和 Dijkstra 算法来寻找路径。GetDistance 函数用于计算两个节点之间的距离,GeneratePath 函数用于生成路径,GetAllNodes 函数用于获取所有节点。

        在 Main 函数中,我们创建了起始节点和目标节点,并使用 A*算法和 Dijkstra 算法分别寻找路径。最后,将路径打印出来。

        请注意,示例代码中只包含了算法的实现逻辑,您需要根据实际情况创建地图、设置节点可行走状态、设置邻居节点等操作。

此为用C#写的A*算法源代码 using System; using System.Collections.Generic; using System.Text; using System.Drawing; namespace EtSoft.AStarLib { public class AStar { private StarNodeCollection openList = new StarNodeCollection(); private StarNodeCollection closeList = new StarNodeCollection(); public StarNode currentNode = null; #region 构造函数 /// <summary> /// 使用指定的地图对象、起点终点初始化A星算法 /// </summary> /// <param name="map">地图对象</param> public AStar(Map map) { this.map = map; } /// <summary> /// /// </summary> /// <param name="map">地图对象</param> /// <param name="start">起点坐标</param> /// <param name="end">终点坐标</param> public AStar(Map map, Point start, Point end) : this(map) { this.start = new StarNode(start); this.end = new StarNode(end); openList.Add(new StarNode(start)); //AddStartNodeToOpenList(this.start); } /// <summary> /// /// </summary> /// <param name="map">地图对象</param> /// <param name="startX">起点X坐标</param> /// <param name="startY">起点Y坐标</param> /// <param name="endX">终点X坐标</param> /// <param name="endY">终点Y坐标</param> public AStar(Map map, int startX, int startY, int endX, int endY) : this(map, new Point(startX, startY), new Point(endX, endY)) { } #endregion #region 属性 protected Map map; /// <summary> /// 地图数据 /// </summary> public Map Map { get { return map; } set { map = value; } } private StarNode start = null; /// <summary> /// 起点坐标,如果没有设置起点,返回null /// </summary> public StarNode Start { get { return start; } set { start = value; openList.Clear(); openList.Add(start); //AddNodeToOpenList(start); } } private StarNode end = null; /// <summary> /// 终点坐标,如果没有设置终点,返回null /// </summary> public StarNode End { get { return end; } set { end = value; } } private StarNodeCollection path; /// <summary> /// 返回路径节点集合,没有路径则返回null /// </summary> public StarNodeCollection Path { get { return path; } } private bool allDirection = false; /// <summary> /// true,允许八方向寻路 /// </summary> public bool AllDirection { get { return allDirection; } set { allDirection = value; } } #endregion /// <summary> /// 开始寻路 /// </summary> public void StartSearchPath() { if (start == null) throw new InvalidNodeException(InvalidNodeTypes.NoStart); if (end == null) throw new InvalidNodeException(InvalidNodeTypes.NoEnd); path = null; openList.Clear(); closeList.Clear(); currentNode = start; SearchPath(currentNode); } //寻路递归,受保护的虚方法,允许在子类重写寻路算法 protected virtual void SearchPath(StarNode starNode) { //currentNode = starNode; openList.Remove(starNode); closeList.Add(starNode); AddNodeToOpenList(); if (closeList.Contains(end)) { //如果终点在关闭列表中,找到路径 StarNode node=starNode.Parent; path = new StarNodeCollection(); do { path.Add(node); node = node.Parent; } while (node != null && !node.Equals(start)); path.Reverse(); return; } else if (openList.Count == 0) { //终点不在关闭列表,开放列表已空,没有可通行的路径 return; } currentNode = GetNextNode(); //迭代过程 SearchPath(currentNode); } /// <summary> /// 获得当前节点的下一个最佳节点 /// </summary> /// <returns></returns> public StarNode GetNextNode() { openList.SortByF(); return openList[0]; } /// <summary> /// 把当前点周围可通过的点加入到开放列表中 /// </summary>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

csdn_aspnet

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值