Advertisement
Guest User

Untitled

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