Advertisement
Guest User

a*

a guest
Sep 28th, 2016
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.71 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. // A* needs only a WeightedGraph and a Vector3 type L, and does *not*
  6. // have to be a grid. However, in the example code I am using a grid.
  7. public interface WeightedGraph<L>
  8. {
  9.     double Cost(Vector3 a, Vector3 b);
  10.     IEnumerable<Vector3> Neighbors(Vector3 id);
  11. }
  12.  
  13.  
  14.  
  15.  
  16.  
  17. public class SquareGrid : WeightedGraph<Vector3>
  18. {
  19.     // Implementation notes: I made the fields public for convenience,
  20.     // but in a real project you'll probably want to follow standard
  21.     // style and make them private.
  22.  
  23.     public static readonly Vector3[] DIRS = new[]
  24.         {
  25.             new Vector3(1,0, 0),
  26.             new Vector3(1,0, 1),
  27.             new Vector3(1,0, -1),
  28.             new Vector3(-1,0, 1),
  29.             new Vector3(-1,0, -1),
  30.             new Vector3(0,0, -1),
  31.             new Vector3(-1,0, 0),
  32.             new Vector3(0,0, 1)
  33.         };
  34.  
  35.     public int width, height;
  36.     public HashSet<Vector3> walls = new HashSet<Vector3>();
  37.     public HashSet<Vector3> forests = new HashSet<Vector3>();
  38.  
  39.     public SquareGrid(int width, int height)
  40.     {
  41.         this.width = width;
  42.         this.height = height;
  43.     }
  44.  
  45.     public bool InBounds(Vector3 id)
  46.     {
  47.         return 0 <= id.x && id.x < width
  48.             && 0 <= id.z && id.z < height;
  49.     }
  50.  
  51.     public bool Passable(Vector3 id)
  52.     {
  53.         return !walls.Contains(id);
  54.     }
  55.  
  56.     public double Cost(Vector3 a, Vector3 b)
  57.     {
  58.         return forests.Contains(b) ? 5 : 1;
  59.     }
  60.  
  61.     public IEnumerable<Vector3> Neighbors(Vector3 id)
  62.     {
  63.         foreach (var dir in DIRS)
  64.         {
  65.             Vector3 next = new Vector3(id.x + dir.x, 0, id.z + dir.z);
  66.             if (InBounds(next) && Passable(next))
  67.             {
  68.                 yield return next;
  69.             }
  70.         }
  71.     }
  72. }
  73.  
  74.  
  75. public class PriorityQueue<T>
  76. {
  77.     // I'm using an unsorted array for this example, but ideally this
  78.     // would be a binary heap. Find a binary heap class:
  79.     // * https://bitbucket.org/BlueRaja/high-speed-priority-queue-for-c/wiki/Home
  80.     // * http://visualstudiomagazine.com/articles/2012/11/01/priority-queues-with-c.aspx
  81.     // * http://xfleury.github.io/graphsearch.html
  82.     // * http://stackoverflow.com/questions/102398/priority-queue-in-net
  83.     private List<NodeElement> elements = new List<NodeElement>();
  84.  
  85.     public int Count
  86.     {
  87.         get { return elements.Count; }
  88.     }
  89.  
  90.     public void Enqueue(Vector3 item, double priority)
  91.     {
  92.         NodeElement temp = new NodeElement();
  93.         elements.Add(new NodeElement(item, priority));
  94.     }
  95.     public class NodeElement
  96.     {
  97.         public Vector3 item1;
  98.         public double item2;
  99.         public NodeElement(Vector3 _node, double _double)
  100.         {
  101.             item1 = _node;
  102.             item2 = _double;
  103.         }
  104.         public NodeElement()
  105.         {
  106.             item1 = Vector3.zero;
  107.             item2 = 0;
  108.         }
  109.     }
  110.     public Vector3 Dequeue()
  111.     {
  112.         int bestIndex = 0;
  113.  
  114.         for (int i = 0; i < elements.Count; i++)
  115.         {
  116.             if (elements[i].item2 < elements[bestIndex].item2)
  117.             {
  118.                 bestIndex = i;
  119.             }
  120.         }
  121.         Vector3 bestItem = elements[bestIndex].item1;
  122.         elements.RemoveAt(bestIndex);
  123.         return bestItem;
  124.     }
  125.  
  126. }
  127.  
  128.  
  129. /* NOTE about types: in the main article, in the Python code I just
  130.  * use numbers for costs, heuristics, and priorities. In the C++ code
  131.  * I use a typedef for this, because you might want int or double or
  132.  * another type. In this C# code I use double for costs, heuristics,
  133.  * and priorities. You can use an int if you know your values are
  134.  * always integers, and you can use a smaller size number if you know
  135.  * the values are always small. */
  136.  
  137. public class AStarSearch
  138. {
  139.     public Dictionary<Vector3, Vector3> cameFrom
  140.         = new Dictionary<Vector3, Vector3>();
  141.     public Dictionary<Vector3, double> costSoFar
  142.         = new Dictionary<Vector3, double>();
  143.  
  144.     // Note: a generic version of A* would abstract over Vector3 and
  145.     // also Heuristic
  146.     static public double Heuristic(Vector3 a, Vector3 b)
  147.     {
  148.         return Math.Abs(a.x - b.x) + Math.Abs(a.y - b.y);
  149.     }
  150.     Vector3 _start, _goal;
  151.     public AStarSearch(SquareGrid graph, Vector3 start, Vector3 goal)
  152.     {
  153.         var frontier = new PriorityQueue<Vector3>();
  154.         frontier.Enqueue(start, 0);
  155.         _start = start;
  156.         _goal = goal;
  157.         cameFrom[start] = start;
  158.         costSoFar[start] = 0;
  159.  
  160.         while (frontier.Count > 0)
  161.         {
  162.             Vector3 current = frontier.Dequeue();
  163.  
  164.             if (current.Equals(goal))
  165.             {
  166.                 break;
  167.             }
  168.  
  169.             foreach (var next in graph.Neighbors(current))
  170.             {
  171.                 double newCost = costSoFar[current]
  172.                     + graph.Cost(current, next);
  173.                 if (!costSoFar.ContainsKey(next)
  174.                     || newCost < costSoFar[next])
  175.                 {
  176.                     costSoFar[next] = newCost;
  177.                     double priority = newCost + Heuristic(next, goal);
  178.                     frontier.Enqueue(next, priority);
  179.                     cameFrom[next] = current;
  180.                 }
  181.             }
  182.         }
  183.     }
  184.  
  185.     public List<Vector3> FindShortestPath()
  186.     {
  187.         Vector3 next = _goal;
  188.         List<Vector3> path = new List<Vector3>();
  189.         path.Add(next);
  190.         for (int i = 0; i < cameFrom.Count; ++i)
  191.         {
  192.             next = cameFrom[next];
  193.             path.Add(next);
  194.             if (next == _start)
  195.             {
  196.                 path.Reverse();
  197.                 break;
  198.             }
  199.         }
  200.         return path;
  201.     }
  202. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement