Naive C# AStar


SUBMITTED BY: Guest

DATE: Nov. 11, 2013, 8:59 p.m.

FORMAT: Text only

SIZE: 8.6 kB

HITS: 968

  1. using System;
  2. using System.Collections.Generic;
  3. namespace MonoTest
  4. {
  5. public class AStar
  6. {
  7. public static int resultLength=0;
  8. class Node
  9. {
  10. public Node(int x, int y)
  11. {
  12. posX = x;
  13. posY = y;
  14. neighbors = new List<Node>();
  15. }
  16. public List<Node> neighbors;
  17. public int posX;
  18. public int posY;
  19. public float g = float.PositiveInfinity;
  20. public float f = float.PositiveInfinity;
  21. public Node previous = null;
  22. }
  23. public static void Main()
  24. {
  25. for(int i=0; i<1000; ++i)
  26. {
  27. performAStar();
  28. }
  29. }
  30. public static void performAStar()
  31. {
  32. string map = "S XXX X\n"
  33. +"XX XXXXXXXXXXXXX X\n"
  34. +" XX X\n"
  35. +"X XXX XXXXXX\n"
  36. +" XXXX XXXXXXXX\n"
  37. +"XXXXXXX X X\n"
  38. +"XX X XXXXX X\n"
  39. +" XX XX X\n"
  40. +"XXXXXXXXXXX X\n"
  41. +"XX XXXXXXXXX X\n"
  42. +" XXXXXX X\n"
  43. +"X XXX XXXXXX\n"
  44. +" XXXX XXXXXXXX\n"
  45. +"XXXXXXX X X\n"
  46. +"XX X XXXXX X\n"
  47. +" XX XX X\n"
  48. +"XXXXX XXXXX X\n"
  49. +"XX XXXX XXXX X\n"
  50. +" XXXXXX X\n"
  51. +"X XXX XXXXXX\n"
  52. +" XXXX XXXXXXXX\n"
  53. +"XXXXX XX X X\n"
  54. +"XX X XXXXX X\n"
  55. +" XX XX X\n"
  56. +"XXXXX XXXXXXXXXXXX X\n"
  57. +" G XX X\n"
  58. +"XXXXXXXXXXXXXXXXXXXXXXX";
  59. string[] lines = map.Split ('\n');
  60. Node start = null;
  61. Node goal = null;
  62. int width = lines [0].Length;
  63. int height = lines.Length;
  64. Node[,] nodes = new Node[width,height];
  65. //initialize the node grid with zeros
  66. for (int x = 0; x < width; x++)
  67. for (int y = 0; y < height; y++)
  68. nodes [x,y] = null;
  69. //create the accessible nodes on the grid
  70. for (int y = 0; y < height; y++)
  71. {
  72. string line = lines [y];
  73. for (int x = 0; x < width; x++)
  74. {
  75. char c = line [x];
  76. //accessible node?
  77. if (c != 'X')
  78. {
  79. Node node = new Node (x, y);
  80. if (c == 'S')
  81. start = node;
  82. if (c == 'G')
  83. goal = node;
  84. nodes [x,y] = node;
  85. }
  86. }
  87. }
  88. //connect the nodes
  89. for (int x = 0; x < width; x++)
  90. {
  91. for (int y = 0; y < height; y++)
  92. {
  93. if(nodes [x,y] == null)
  94. continue;
  95. //up
  96. if (y > 0 && nodes [x,y - 1] != null)
  97. nodes [x,y].neighbors.Add (nodes [x,y - 1]);
  98. //up right
  99. if (y > 0 && x < width - 1 && nodes [x + 1,y - 1] != null)
  100. nodes [x,y].neighbors.Add (nodes [x + 1,y - 1]);
  101. //right
  102. if (x < width - 1 && nodes [x + 1,y] != null)
  103. nodes [x,y].neighbors.Add (nodes [x + 1,y]);
  104. //right down
  105. if (x < width - 1 && y < height && nodes [x + 1,y + 1] != null)
  106. nodes [x,y].neighbors.Add (nodes [x + 1,y + 1]);
  107. //down
  108. if (y < height && nodes [x,y + 1] != null)
  109. nodes [x,y].neighbors.Add (nodes [x,y + 1]);
  110. //down left
  111. if (y < height && x > 0 && nodes [x - 1,y + 1] != null)
  112. nodes [x,y].neighbors.Add (nodes [x - 1,y + 1]);
  113. //left
  114. if (x > 0 && nodes [x - 1,y] != null)
  115. nodes [x,y].neighbors.Add (nodes [x - 1,y]);
  116. //left up
  117. if (x > 0 && y > 0 && nodes [x - 1,y - 1] != null)
  118. nodes [x,y].neighbors.Add (nodes [x - 1,y - 1]);
  119. }
  120. }
  121. //perform the actal pathfinding
  122. if (!aStar(start, goal))
  123. {
  124. Console.Error.WriteLine("Unable to find a path.");
  125. }
  126. //reconstruct the path
  127. List<Node> path = new List<Node> ();
  128. Node waypoint = goal;
  129. path.Add (goal);
  130. while (waypoint.previous != null)
  131. {
  132. path.Add (waypoint.previous);
  133. waypoint = waypoint.previous;
  134. }
  135. string result = "";
  136. for (int i = path.Count - 1; i >= 0; i--)
  137. {
  138. Node p = path[i];
  139. result += "("+p.posX.ToString()+","+p.posY.ToString()+")";
  140. }
  141. //make sure the compiler can't optimize away any important computations by saving the result:
  142. resultLength = result.Length;
  143. //Console.WriteLine(result);
  144. }
  145. private static bool aStar(Node start, Node goal)
  146. {
  147. List<Node> closedSet = new List<Node> ();
  148. List<Node> openSet = new List<Node> ();
  149. openSet.Add (start);
  150. start.g = 0.0f;
  151. start.f = h (start, goal);
  152. while (openSet.Count > 0)
  153. {
  154. Node current = findBest(openSet);
  155. if(current == goal)
  156. return true;
  157. openSet.Remove(current);
  158. closedSet.Add(current);
  159. foreach(Node neighbor in current.neighbors)
  160. {
  161. if(closedSet.Contains(neighbor))
  162. continue;
  163. float newG = current.g + h(current, neighbor);
  164. if(newG < neighbor.g)
  165. {
  166. neighbor.g = newG;
  167. neighbor.f = newG + h(neighbor, goal);
  168. neighbor.previous = current;
  169. }
  170. if(!openSet.Contains(neighbor))
  171. {
  172. openSet.Add(neighbor);
  173. }
  174. }
  175. }
  176. return false;
  177. }
  178. private static float h(Node current, Node goal)
  179. {
  180. double dx = current.posX - goal.posX;
  181. double dy = current.posY - goal.posY;
  182. return (float)Math.Sqrt(dx*dx + dy*dy);
  183. }
  184. private static Node findBest(List<Node> list)
  185. {
  186. Node best = null;
  187. float bestF = float.PositiveInfinity;
  188. foreach (Node node in list)
  189. {
  190. if(node.f < bestF)
  191. {
  192. best = node;
  193. bestF = node.f;
  194. }
  195. }
  196. return best;
  197. }
  198. }
  199. }

comments powered by Disqus