• A Star算法笔记


    回顾A*算法,偶得一源代码,略有瑕疵,改正之,并置于下。

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading.Tasks;
      6 
      7 namespace AStarOne
      8 {
      9     class AStar
     10     {
     11         public const int OBLIQUE = 14;//sqrt(2.0) is 1.414; they have been amplified.
     12         public const int STEP = 10;
     13         public int[,] AStarArray { get; private set; }
     14         List<Point> CloseList; // Close List
     15         List<Point> OpenList; // Open List
     16 
     17         public AStar(int [,] aStar)
     18         {
     19             this.AStarArray = aStar;
     20             OpenList = new List<Point>(AStarArray.Length);// Impossible to be bigger than the number of all data
     21             CloseList = new List<Point>(AStarArray.Length);
     22         }
     23 
     24         /// <summary>
     25         /// Find an achievable path from start to end
     26         /// </summary>
     27         /// <param name="start"></param>
     28         /// <param name="end"></param>
     29         /// <param name="IsIgnoreCorner">If ignore diagonal spot</param>
     30         /// <returns></returns>
     31         public Point FindPath(Point start, Point end, bool IsIgnoreCorner)
     32         {
     33             OpenList.Add(start);
     34             while (0 != OpenList.Count)
     35             {
     36                 var tempStart = OpenList.MinPoint();// get the minimum F
     37                 OpenList.RemoveAt(0);
     38                 CloseList.Add(tempStart);
     39 
     40                 var surroundPoints = GetSurroundPoints(tempStart, IsIgnoreCorner);// Get surrounding points
     41                 foreach (var point in surroundPoints)
     42                 {
     43                     if (OpenList.Exists(point))// If existing in the open list, choose the minimum G between tempStart and point; Update
     44                     {
     45                         FoundPoint(tempStart, point);
     46                     }
     47                     else
     48                     {
     49                         NotFoundPoint(tempStart, end, point);
     50                     }
     51                 }
     52 
     53                 if (OpenList.Get(end) != null)
     54                     return OpenList.Get(end);
     55             }
     56 
     57             return OpenList.Get(end);
     58         }
     59 
     60         private void FoundPoint(Point tempStart, Point point)
     61         {
     62             var G = CalcG(tempStart, point);
     63             if (G < point.G)// the minimum one
     64             {
     65                 point.ParentPoint = tempStart;
     66                 point.G = G;
     67                 point.CalcF();
     68             }
     69         }
     70 
     71         private void NotFoundPoint(Point tempPoint, Point end, Point point)
     72         {
     73             point.ParentPoint = tempPoint;
     74             point.G = CalcG(tempPoint, point);
     75             point.H = CalcH(end, point);
     76             point.CalcF();
     77             OpenList.Add(point);// This is quite important
     78         }
     79 
     80         private int CalcG(Point start, Point point)// Calc the cost from start to point
     81         {
     82             int G = (Math.Abs(point.X - start.X) + Math.Abs(point.Y - start.Y)) == 1 ? STEP : OBLIQUE;// Should be 1
     83             int parentG = point.ParentPoint != null ? point.ParentPoint.G : 0;
     84             return G + parentG;
     85         }
     86 
     87         private int CalcH(Point end, Point point)// Estimate the cost to reach the target
     88         {
     89             int step = Math.Abs(point.X - end.X) + Math.Abs(point.Y - end.Y);
     90             return step * STEP;
     91         }
     92 
     93         public List<Point> GetSurroundPoints(Point point, bool IsIgnoreCorner)
     94         {
     95             var surroundPoints = new List<Point>(9);
     96 
     97             for (int x = point.X - 1; x <= point.X + 1; x++)
     98             {
     99                 for (int y = point.Y - 1; y <= point.Y + 1; y++)
    100                 {
    101                     if (CanReach(point, x, y, IsIgnoreCorner))
    102                         surroundPoints.Add(x, y);
    103                 }
    104             }
    105 
    106             return surroundPoints;
    107         }
    108 
    109         private bool CanReach(int x, int y)
    110         {
    111             return AStarArray[x, y] == 0;
    112         }
    113 
    114         public bool CanReach(Point start, int x, int y, bool IsIgnoreCorner)
    115         {
    116             if (!CanReach(x, y) || CloseList.Exists(x, y))// Cannot reach or has been handled 
    117             {
    118                 return false;
    119             }
    120             else
    121             {
    122                 if (Math.Abs(x - start.X) + Math.Abs(y - start.Y) == 1)// Adjacent but not diagonal
    123                 {
    124                     return true;
    125                 }
    126                 else
    127                 {
    128                     if (CanReach(Math.Abs(x - 1), y) && CanReach(x, Math.Abs(y - 1)))// Make sure diagnonal but not necessary
    129                     {
    130                         return IsIgnoreCorner;
    131                     }
    132                     else
    133                     {
    134                         return false;
    135                     }
    136                 }
    137             }
    138         }
    139     }
    140 
    141     public class Point
    142     {
    143         public Point ParentPoint { get; set; }
    144         public int F { get; set; } // F = G + H
    145         public int G { get; set; }
    146         public int H { get; set; }
    147         public int X { get; set; }
    148         public int Y { get; set; }
    149 
    150         public Point(int x, int y)
    151         {
    152             this.X = x;
    153             this.Y = y;
    154         }
    155 
    156         public void CalcF()
    157         {
    158             this.F = this.G + this.H;
    159         }
    160     }
    161 
    162     public static class ListHelper
    163     {
    164         public static bool Exists(this List<Point> points, Point point)
    165         {
    166             foreach (var p in points)
    167                 if ((p.X == point.X) && (p.Y == point.Y))
    168                     return true;
    169 
    170              return false;
    171         }
    172 
    173         public static bool Exists(this List<Point> points, int x, int y)
    174         {
    175             foreach (var p in points)
    176                 if ((p.X == x) && (p.Y == y))
    177                     return true;
    178 
    179             return false;
    180         }
    181 
    182         public static Point MinPoint(this List<Point> points)
    183         {
    184             points = points.OrderBy(p => p.F).ToList();
    185             return points[0];
    186         }
    187 
    188         public static void Add(this List<Point> points, int x, int y)
    189         {
    190             points.Add(new Point(x, y));
    191         }
    192 
    193         public static Point Get(this List<Point> points, Point point)
    194         {
    195             foreach (Point p in points)
    196                 if ((p.X == point.X) && (p.Y == point.Y))
    197                     return p;
    198 
    199             return null;
    200         }
    201 
    202         public static void Remove(this List<Point> points, int x, int y)
    203         {
    204             foreach (var point in points)
    205                 if ((point.X == x) && (point.Y == y))
    206                     points.Remove(point);
    207         }
    208     }
    209 }
    View Code

    测试代码如下:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace AStarOne
     8 {
     9     class Program
    10     {
    11         static void Main(string[] args)
    12         {
    13             int[,] array = {
    14                                { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
    15                                { 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1},
    16                                { 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1},
    17                                { 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1},
    18                                { 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1},
    19                                { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1},
    20                                { 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1},
    21                                { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
    22                            };
    23 
    24             AStar astar = new AStar(array);
    25 
    26             Point start = new Point(1, 1);
    27             Point end = new Point(6, 10);
    28             var parent = astar.FindPath(start, end, false);
    29 
    30             Console.WriteLine("Print path:");
    31             while (parent != null)
    32             {
    33                 //Console.WriteLine(parent.X + ", " + parent.Y);
    34                 array[parent.X, parent.Y] = 8;
    35                 parent = parent.ParentPoint;
    36             }
    37 
    38             for (int i = 0; i < 8; i++)
    39             {
    40                 for (int j = 0; j < 12; j++)
    41                 {
    42                     Console.Write(array[i,j] + " ");
    43                 }
    44                 Console.WriteLine();
    45             }
    46         }
    47     }
    48 }
    View Code

    运行结果如下(注意‘8’的位置即是路径):

  • 相关阅读:
    Android tcpdump 抓包
    Android CursorAdapter 查询联系人过滤
    Android 项目打包成apk文件
    解决Centos 6.3 中 gedit中文乱码问题
    在Linux(centos)系统上用手机调试android程序(eclipse)
    系统定时关机命令–shutdown
    使用gdb Server调试嵌入式程序
    Vim 错误排查方法
    通过netstat命令查看进程与端口的对应关系
    dexpler的使用方法
  • 原文地址:https://www.cnblogs.com/AmitX-moten/p/4168328.html
Copyright © 2020-2023  润新知