Advertisement
Guest User

Untitled

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