doctard

Untitled

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