Advertisement
Guest User

a*

a guest
Sep 28th, 2016
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.40 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.  
  84.     private List<Node> elements = new List<Node>();
  85.  
  86.     public int Count
  87.     {
  88.         get { return elements.Count; }
  89.     }
  90.  
  91.     public void Enqueue(Vector3 item, double priority)
  92.     {
  93.         Node temp = ScriptableObject.CreateInstance<Node>();
  94.         temp.cords = item;
  95.         temp.cost = priority;
  96.         elements.Add(temp);
  97.     }
  98.  
  99.     public Vector3 Dequeue()
  100.     {
  101.         int bestIndex = 0;
  102.  
  103.         for (int i = 0; i < elements.Count; i++)
  104.         {
  105.             if (elements[i].cost < elements[bestIndex].cost)
  106.             {
  107.                 bestIndex = i;
  108.             }
  109.         }
  110.  
  111.         Vector3 bestItem = elements[bestIndex].cords;
  112.         elements.RemoveAt(bestIndex);
  113.         return bestItem;
  114.     }
  115. }
  116.  
  117.  
  118. /* NOTE about types: in the main article, in the Python code I just
  119.  * use numbers for costs, heuristics, and priorities. In the C++ code
  120.  * I use a typedef for this, because you might want int or double or
  121.  * another type. In this C# code I use double for costs, heuristics,
  122.  * and priorities. You can use an int if you know your values are
  123.  * always integers, and you can use a smaller size number if you know
  124.  * the values are always small. */
  125.  
  126. public class AStarSearch
  127. {
  128.     public Dictionary<Vector3, Vector3> cameFrom
  129.         = new Dictionary<Vector3, Vector3>();
  130.     public Dictionary<Vector3, double> costSoFar
  131.         = new Dictionary<Vector3, double>();
  132.  
  133.     // Note: a generic version of A* would abstract over Vector3 and
  134.     // also Heuristic
  135.     static public double Heuristic(Vector3 a, Vector3 b)
  136.     {
  137.         return Math.Abs(a.x - b.x) + Math.Abs(a.y - b.y);
  138.     }
  139.     Vector3 _start, _goal;
  140.     public AStarSearch(SquareGrid graph, Vector3 start, Vector3 goal)
  141.     {
  142.         var frontier = new PriorityQueue<Vector3>();
  143.         frontier.Enqueue(start, 0);
  144.         _start = start;
  145.         _goal = goal;
  146.         cameFrom[start] = start;
  147.         costSoFar[start] = 0;
  148.  
  149.         while (frontier.Count > 0)
  150.         {
  151.             var current = frontier.Dequeue();
  152.  
  153.             if (current.Equals(goal))
  154.             {
  155.                 break;
  156.             }
  157.  
  158.             foreach (var next in graph.Neighbors(current))
  159.             {
  160.                 double newCost = costSoFar[current]
  161.                     + graph.Cost(current, next);
  162.                 if (!costSoFar.ContainsKey(next)
  163.                     || newCost < costSoFar[next])
  164.                 {
  165.                     costSoFar[next] = newCost;
  166.                     double priority = newCost + Heuristic(next, goal);
  167.                     frontier.Enqueue(next, priority);
  168.                     cameFrom[next] = current;
  169.                 }
  170.             }
  171.         }
  172.     }
  173.  
  174.     public List<Vector3> FindShortestPath()
  175.     {
  176.         Vector3 next = _goal;
  177.         List<Vector3> path = new List<Vector3>();
  178.         path.Add(next);
  179.         for (int i = 0; i < cameFrom.Count; ++i)
  180.         {
  181.             next = cameFrom[next];
  182.             path.Add(next);
  183.             if (next == _start)
  184.             {
  185.                 path.Reverse();
  186.                 break;
  187.             }
  188.         }
  189.         return path;
  190.     }
  191. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement