巡路算法

比较闲,看了网上的思路后写了一个玩玩

public class MapManager
{
    private int mapMaxRow = 0;
    private int mapMaxCol = 0;
    private int[,] mapInfo;
    //终点坐标
    private int finalRowIndex = 0;
    private int finalColIndex = 0;

    //起点坐标
    private int startRowIndex = 0;
    private int startColIndex = 0;

    /// <summary>
    /// 结果列表
    /// </summary>
    public List<MapInfo> resList = new List<MapInfo>();
    private Dictionary<string, MapInfo> dic_open = new Dictionary<string, MapInfo>();//开放列表
    private Dictionary<string, MapInfo> dic_close = new Dictionary<string, MapInfo>();//关闭列表
    public MapManager(int mapMaxRow, int mapMaxCol, int startRowIndex, int startColIndex, int finalRowIndex, int finalColIndex)
    {
        this.mapMaxRow = mapMaxRow;
        this.mapMaxCol = mapMaxCol;
        mapInfo = new int[this.mapMaxRow, this.mapMaxCol];
        this.startRowIndex = startRowIndex;
        this.startColIndex = startColIndex;
        this.finalRowIndex = finalRowIndex;
        this.finalColIndex = finalColIndex;
    }

    /// <summary>
    /// 添加障碍物
    /// </summary>
    /// <param name="rowIndex"></param>
    /// <param name="colIndex"></param>
    public void AddObstacle(int rowIndex, int colIndex)
    {
        mapInfo[rowIndex, colIndex] = (int)PointType.OBSTACLE;
    }

    /// <summary>
    /// 初始化地图
    /// </summary>
    public void InitMap()
    {
        for (int i = 0; i < mapMaxRow; i++)
        {
            for (int j = 0; j < mapMaxCol; j++)
            {
                mapInfo[i, j] = (int)PointType.EMPTY;
            }
        }

        mapInfo[startRowIndex, startColIndex] = (int)PointType.START;//设置起点
        mapInfo[finalRowIndex, finalColIndex] = (int)PointType.END;//设置终点
    }


    /// <summary>
    /// 获取地图显示内容 0空地□、1障碍■、2起点○、3终点●、4路线▲
    /// </summary>
    /// <param name="rowIndex"></param>
    /// <param name="colIndex"></param>
    /// <returns></returns>
    private string GetMapDes(int rowIndex, int colIndex)
    {
        switch ((PointType)mapInfo[rowIndex, colIndex])
        {
            case PointType.EMPTY:
                return "";//空地
            case PointType.OBSTACLE:
                return "";//障碍物
            case PointType.START:
                return "";//起点
            case PointType.END:
                return "";//终点
            case PointType.PATH:
                return "";//路线
            case PointType.TEST_POINT:
                return "";//测试点位
        }

        return "";
    }


    public enum PointType
    {
        /// <summary>
        /// 空地
        /// </summary>
        EMPTY,

        /// <summary>
        /// 障碍物
        /// </summary>
        OBSTACLE,

        /// <summary>
        /// 起点
        /// </summary>
        START,

        /// <summary>
        /// 终点
        /// </summary>
        END,

        /// <summary>
        /// 路径点
        /// </summary>
        PATH,

        /// <summary>
        /// 测试点位
        /// </summary>
        TEST_POINT
    }

    /// <summary>
    /// 显示地图信息
    /// </summary>
    public void ShowMapDes()
    {
        for (int i = 0; i < mapMaxRow; i++)
        {
            string tempDes = GetMapRowDes(i);
            Console.WriteLine(tempDes);
        }
    }

    /// <summary>
    /// 获取某行的地图信息
    /// </summary>
    /// <param name="rowIndex"></param>
    /// <returns></returns>
    private string GetMapRowDes(int rowIndex)
    {
        string res = string.Empty;
        for (int i = 0; i < mapMaxCol; i++)
        {
            res += GetMapDes(rowIndex, i);
        }
        return res;
    }


    /// <summary>
    /// 获取路线
    /// </summary>
    public void GetRoad()
    {
        //先把障碍物放进关闭列表
        for (int i = 0; i < mapMaxRow; i++)
        {
            for (int j = 0; j < mapMaxCol; j++)
            {
                if (mapInfo[i, j] == (int)PointType.OBSTACLE || mapInfo[i, j] == (int)PointType.START)//障碍物、起点、终点跳过检测
                {
                    MapInfo mapInfo = new MapInfo();
                    mapInfo.rowIndex = i;
                    mapInfo.colIndex = j;
                    dic_close.Add(i + "," + j, mapInfo);
                }
            }
        }


        GetPathList(startRowIndex, startColIndex, finalRowIndex, finalColIndex);

        GetResList(finalRowIndex, finalColIndex, ref resList);
        for (int i = 0; i < resList.Count; i++)
        {
            if (resList[i].rowIndex == startRowIndex && resList[i].colIndex == startColIndex)
            {
                return;
            }
            mapInfo[resList[i].rowIndex, resList[i].colIndex] = (int)PointType.PATH;
        }
    }


    /// <summary>
    /// 获取路径点位
    /// </summary>
    /// <param name="rowIndex"></param>
    /// <param name="colIndex"></param>
    /// <param name="finalRowIndex"></param>
    /// <param name="finalColIndex"></param>
    private void GetPathList(int rowIndex, int colIndex, int finalRowIndex, int finalColIndex)
    {

        if (rowIndex < 0 || colIndex < 0)
        {
            return;
        }
        Dictionary<string, MapInfo> dic_roundPoints = GetRoundPoints(rowIndex, colIndex);

        if (dic_roundPoints.Count <= 0)
        {
            return;
        }

        //判断是否有点位在关闭列表,如果有,就删除,这一步是为了剔除障碍物和已经用过的路径点
        IsExistsCloseListAndDelete(ref dic_roundPoints);


        if (dic_roundPoints.Count > 0)
        {
            AddToOpen(dic_roundPoints);//将周围点位添加进开放列表
        }
        if (dic_open.ContainsKey(rowIndex + "," + colIndex))
        {
            dic_close.Add(rowIndex + "," + colIndex, dic_open[rowIndex + "," + colIndex]);
            dic_open.Remove(rowIndex + "," + colIndex);
        }



        if (dic_open.ContainsKey(finalRowIndex + "," + finalColIndex))
        {
            return;//说明到达了终点
        }

        //找出最小的点
        dic_open = dic_open.OrderBy(p => p.Value.f).ToDictionary(p => p.Key, o => o.Value);
        if (dic_open.Count <= 0)
{
    return;
}
MapInfo tempParent
= dic_open.First().Value; if (dic_open.Count <= 0) { return; } GetPathList(tempParent.rowIndex, tempParent.colIndex, finalRowIndex, finalColIndex); } /// <summary> /// 将源集合添加进开放列表 /// </summary> /// <param name="oriDic"></param> private void AddToOpen(Dictionary<string, MapInfo> oriDic) { Dictionary<string, MapInfo>.Enumerator it = oriDic.GetEnumerator(); while (it.MoveNext()) { if (!dic_open.ContainsKey(it.Current.Key)) { dic_open.Add(it.Current.Key, it.Current.Value); } else { //需要判断,如果新值比原来的小就更新 if (it.Current.Value.f <= dic_open[it.Current.Key].f) { dic_open[it.Current.Key] = it.Current.Value; } } } } /// <summary> /// 获取结果列表 /// </summary> private void GetResList(int rowIndex, int colIndex, ref List<MapInfo> resList) { int parentX = -1; int parentY = -1; if (dic_open.ContainsKey(rowIndex + "," + colIndex)) { parentX = dic_open[rowIndex + "," + colIndex].parent.rowIndex; parentY = dic_open[rowIndex + "," + colIndex].parent.colIndex; } if (dic_close.ContainsKey(rowIndex + "," + colIndex)) { parentX = dic_close[rowIndex + "," + colIndex].parent.rowIndex; parentY = dic_close[rowIndex + "," + colIndex].parent.colIndex; } if (parentX == -1 || parentY == -1) { return; } MapInfo resP = new MapInfo(); resP.rowIndex = parentX; resP.colIndex = parentY; resList.Add(resP); if (resP.rowIndex != startRowIndex || resP.colIndex != startColIndex)//如果父节点不是起点,则继续往前推进 { GetResList(resP.rowIndex, resP.colIndex, ref resList); } } /// <summary> /// 源list中的点位是否存在关闭列表,存在就删除 /// </summary> /// <param name="dic_ori"></param> private void IsExistsCloseListAndDelete(ref Dictionary<string, MapInfo> dic_ori) { List<MapInfo> temp = new List<MapInfo>(); Dictionary<string, MapInfo>.Enumerator it = dic_ori.GetEnumerator(); while (it.MoveNext()) { if (dic_close.ContainsKey(it.Current.Key)) { temp.Add(it.Current.Value); } } for (int i = 0; i < temp.Count; i++) { dic_ori.Remove(temp[i].rowIndex + "," + temp[i].colIndex); } } /// <summary> /// 获取上方点位 /// </summary> /// <param name="rowIndex"></param> /// <param name="colIndex"></param> /// <returns></returns> private MapInfo GetUpPoint(int rowIndex, int colIndex) { if (rowIndex - 1 < 0) { return null; } MapInfo mapInfo = new MapInfo(); mapInfo.rowIndex = rowIndex - 1; mapInfo.colIndex = colIndex; mapInfo.g = GetG(mapInfo.rowIndex, mapInfo.colIndex, rowIndex, colIndex); mapInfo.h = GetH(mapInfo.rowIndex, mapInfo.colIndex, finalRowIndex, finalColIndex); mapInfo.f = mapInfo.g + mapInfo.h; mapInfo.parent.rowIndex = rowIndex; mapInfo.parent.colIndex = colIndex; return mapInfo; } /// <summary> /// 獲取下方的點位 /// </summary> /// <param name="rowIndex"></param> /// <param name="colIndex"></param> /// <returns></returns> private MapInfo GetDownPoint(int rowIndex, int colIndex) { if (rowIndex + 1 >= mapMaxRow) { return null; } MapInfo mapInfo = new MapInfo(); mapInfo.rowIndex = rowIndex + 1; mapInfo.colIndex = colIndex; mapInfo.g = GetG(mapInfo.rowIndex, mapInfo.colIndex, rowIndex, colIndex); mapInfo.h = GetH(mapInfo.rowIndex, mapInfo.colIndex, finalRowIndex, finalColIndex); mapInfo.f = mapInfo.g + mapInfo.h; mapInfo.parent.rowIndex = rowIndex; mapInfo.parent.colIndex = colIndex; return mapInfo; } /// <summary> /// 获取左边点位 /// </summary> /// <param name="rowIndex"></param> /// <param name="colIndex"></param> /// <returns></returns> private MapInfo GetLeftPoint(int rowIndex, int colIndex) { if (colIndex - 1 < 0) { return null; } MapInfo mapInfo = new MapInfo(); mapInfo.rowIndex = rowIndex; mapInfo.colIndex = colIndex - 1; mapInfo.g = GetG(mapInfo.rowIndex, mapInfo.colIndex, rowIndex, colIndex); mapInfo.h = GetH(mapInfo.rowIndex, mapInfo.colIndex, finalRowIndex, finalColIndex); mapInfo.f = mapInfo.g + mapInfo.h; mapInfo.parent.rowIndex = rowIndex; mapInfo.parent.colIndex = colIndex; return mapInfo; } /// <summary> /// 获取右边点位 /// </summary> /// <param name="rowIndex"></param> /// <param name="colIndex"></param> /// <returns></returns> private MapInfo GetRightPoint(int rowIndex, int colIndex) { if (colIndex + 1 >= mapMaxCol) { return null; } MapInfo mapInfo = new MapInfo(); mapInfo.rowIndex = rowIndex; mapInfo.colIndex = colIndex + 1; mapInfo.g = GetG(mapInfo.rowIndex, mapInfo.colIndex, rowIndex, colIndex); mapInfo.h = GetH(mapInfo.rowIndex, mapInfo.colIndex, finalRowIndex, finalColIndex); mapInfo.f = mapInfo.g + mapInfo.h; mapInfo.parent.rowIndex = rowIndex; mapInfo.parent.colIndex = colIndex; return mapInfo; } /// <summary> /// 获取左上点位 /// </summary> /// <param name="rowIndex"></param> /// <param name="colIndex"></param> /// <returns></returns> private MapInfo GetLeftUpPoint(int rowIndex, int colIndex) { if (rowIndex - 1 < 0 || colIndex - 1 < 0) { return null; } MapInfo mapInfo = new MapInfo(); mapInfo.rowIndex = rowIndex - 1; mapInfo.colIndex = colIndex - 1; mapInfo.g = GetG(mapInfo.rowIndex, mapInfo.colIndex, rowIndex, colIndex); mapInfo.h = GetH(mapInfo.rowIndex, mapInfo.colIndex, finalRowIndex, finalColIndex); mapInfo.f = mapInfo.g + mapInfo.h; mapInfo.parent.rowIndex = rowIndex; mapInfo.parent.colIndex = colIndex; return mapInfo; } /// <summary> /// 获取右上点位 /// </summary> /// <param name="rowIndex"></param> /// <param name="colIndex"></param> /// <returns></returns> private MapInfo GetRightUpPoint(int rowIndex, int colIndex) { if (rowIndex - 1 < 0 || colIndex + 1 >= mapMaxCol) { return null; } MapInfo mapInfo = new MapInfo(); mapInfo.rowIndex = rowIndex - 1; mapInfo.colIndex = colIndex + 1; mapInfo.g = GetG(mapInfo.rowIndex, mapInfo.colIndex, rowIndex, colIndex); mapInfo.h = GetH(mapInfo.rowIndex, mapInfo.colIndex, finalRowIndex, finalColIndex); mapInfo.f = mapInfo.g + mapInfo.h; mapInfo.parent.rowIndex = rowIndex; mapInfo.parent.colIndex = colIndex; return mapInfo; } /// <summary> /// 获取左下点位 /// </summary> /// <param name="rowIndex"></param> /// <param name="colIndex"></param> /// <returns></returns> private MapInfo GetLeftDownPoint(int rowIndex, int colIndex) { if (rowIndex + 1 >= mapMaxRow || colIndex - 1 < 0) { return null; } MapInfo mapInfo = new MapInfo(); mapInfo.rowIndex = rowIndex + 1; mapInfo.colIndex = colIndex - 1; mapInfo.g = GetG(mapInfo.rowIndex, mapInfo.colIndex, rowIndex, colIndex); mapInfo.h = GetH(mapInfo.rowIndex, mapInfo.colIndex, finalRowIndex, finalColIndex); mapInfo.f = mapInfo.g + mapInfo.h; mapInfo.parent.rowIndex = rowIndex; mapInfo.parent.colIndex = colIndex; return mapInfo; } /// <summary> /// 获取右下点位 /// </summary> /// <param name="rowIndex"></param> /// <param name="colIndex"></param> /// <returns></returns> private MapInfo GetRightDownPoint(int rowIndex, int colIndex) { if (rowIndex + 1 >= mapMaxRow || colIndex + 1 >= mapMaxCol) { return null; } MapInfo mapInfo = new MapInfo(); mapInfo.rowIndex = rowIndex + 1; mapInfo.colIndex = colIndex + 1; mapInfo.g = GetG(mapInfo.rowIndex, mapInfo.colIndex, rowIndex, colIndex); mapInfo.h = GetH(mapInfo.rowIndex, mapInfo.colIndex, finalRowIndex, finalColIndex); mapInfo.f = mapInfo.g + mapInfo.h; mapInfo.parent.rowIndex = rowIndex; mapInfo.parent.colIndex = colIndex; return mapInfo; } /// <summary> /// 获取H估值 该点位到目标点位的(非欧几里得距离,也非麦哈顿距离,实际距离,横移一格算10,斜方向移动算14) /// 公式结果: /// H = abs(abs(fy - y) - abs(fx - x))*10 + abs((fx - x)和(fy - y)绝对值小的那一个)*14 /// </summary> /// <returns></returns> private int GetH(int rowIndex, int colIndex, int finalRowIndex, int finalColIndex) { int temp = Math.Min(Math.Abs(finalColIndex - colIndex), Math.Abs(finalRowIndex - rowIndex)); int res = Math.Abs(Math.Abs(finalColIndex - colIndex) - Math.Abs(finalRowIndex - rowIndex)) * 10 + temp * 14; return res; } /// <summary> /// 获取g估值 上一个节点+当前的xy坐标的 /// </summary> /// <param name="rowIndex"></param> /// <param name="colIndex"></param> /// <param name="parentRowIndex"></param> /// <param name="parentColIndex"></param> /// <returns></returns> private int GetG(int rowIndex, int colIndex, int parentRowIndex, int parentColIndex) { int res = 0; if (dic_open.ContainsKey(parentRowIndex + "," + parentColIndex)) { res = dic_open[parentRowIndex + "," + parentColIndex].g;//父节点的g值 } else {
       if(dic_close.CntainsKey(parentRowIndex + "," + parentColIndex))   res
= dic_close[parentRowIndex + "," + parentColIndex].g; } if (rowIndex == parentRowIndex || colIndex == parentColIndex)//说明是同一列或者行 { res += 10; } else { //说明是斜方向的 res += 14; } return res; } /// <summary> /// 获取周围的节点 /// </summary> public Dictionary<string, MapInfo> GetRoundPoints(int rowIndex, int colIndex) { Dictionary<string, MapInfo> list_roundPoint = new Dictionary<string, MapInfo>(); //正常来说是8个方向的点位 //左边 MapInfo lp = GetLeftPoint(rowIndex, colIndex); if (lp != null) { list_roundPoint.Add(lp.rowIndex + "," + lp.colIndex, lp); } //右边 MapInfo rp = GetRightPoint(rowIndex, colIndex); if (rp != null) { list_roundPoint.Add(rp.rowIndex + "," + rp.colIndex, rp); } //上面 MapInfo up = GetUpPoint(rowIndex, colIndex); if (up != null) { list_roundPoint.Add(up.rowIndex + "," + up.colIndex, up); } //下面 MapInfo dp = GetDownPoint(rowIndex, colIndex); if (dp != null) { list_roundPoint.Add(dp.rowIndex + "," + dp.colIndex, dp); } //左上 MapInfo lup = GetLeftUpPoint(rowIndex, colIndex); if (lup != null) { list_roundPoint.Add(lup.rowIndex + "," + lup.colIndex, lup); } //右上 MapInfo rup = GetRightUpPoint(rowIndex, colIndex); if (rup != null) { list_roundPoint.Add(rup.rowIndex + "," + rup.colIndex, rup); } //左下 MapInfo ldp = GetLeftDownPoint(rowIndex, colIndex); if (ldp != null) { list_roundPoint.Add(ldp.rowIndex + "," + ldp.colIndex, ldp); } //右下 MapInfo rdp = GetRightDownPoint(rowIndex, colIndex); if (rdp != null) { list_roundPoint.Add(rdp.rowIndex + "," + rdp.colIndex, rdp); } return list_roundPoint; } /// <summary> /// 地图节点信息 /// </summary> public class MapInfo { public int rowIndex = 0; public int colIndex = 0; /// <summary> /// 点位类型 /// </summary> public int type = 0; /// <summary> /// 跑到此格子的成本 /// </summary> public int g = -1; /// <summary> /// 跑到终点的最短距离(忽略障碍物) /// </summary> public int h = -1; /// <summary> /// 跑到终点的最终成本 /// </summary> public int f = -1; public ParentInfo parent = new ParentInfo(); } public class ParentInfo { public int rowIndex = -1; public int colIndex = -1; } }

 

 

 

调用:

static void Main(string[] args)
{
    MapManager mapManager = new MapManager(20, 20, 2, 3, 17, 17);
    mapManager.InitMap();
  //障碍物自己添加 mapManager.ShowMapDes(); Console.WriteLine(
"-------------------------开始绘制路线---------------------------------"); mapManager.GetRoad(); mapManager.ShowMapDes(); Console.ReadLine(); }

posted on 2022-10-24 14:04  炼金师  阅读(16)  评论(0编辑  收藏  举报

导航