Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit eedf891

Browse files
committed
Create AStarExample.cs
1 parent d559c2e commit eedf891

File tree

1 file changed

+243
-0
lines changed

1 file changed

+243
-0
lines changed

AStarExample.cs

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
6+
public struct NodePosition
7+
{
8+
public int x;
9+
public int y;
10+
11+
public NodePosition(int x, int y)
12+
{
13+
this.x = x;
14+
this.y = y;
15+
}
16+
}
17+
18+
19+
public class Path : List<NodePosition>
20+
{
21+
public override string ToString()
22+
{
23+
StringBuilder sb = new StringBuilder();
24+
for (int i = 0; i < Count; ++i)
25+
{
26+
sb.Append(string.Format("Node {0}: {1}, {2}", i, this[i].x, this[i].y));
27+
28+
if (i < Count - 1)
29+
{
30+
sb.Append(" - ");
31+
}
32+
}
33+
34+
return sb.ToString();
35+
}
36+
}
37+
38+
39+
public class Map
40+
{
41+
const int MAP_WIDTH = 20;
42+
const int MAP_HEIGHT = 20;
43+
44+
static int[] map = new int[MAP_WIDTH * MAP_HEIGHT]
45+
{
46+
// 0001020304050607080910111213141516171819
47+
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 00
48+
1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,1, // 01
49+
1,9,9,1,1,9,9,9,1,9,1,9,1,9,1,9,9,9,1,1, // 02
50+
1,9,9,1,1,9,9,9,1,9,1,9,1,9,1,9,9,9,1,1, // 03
51+
1,9,1,1,1,1,9,9,1,9,1,9,1,1,1,1,9,9,1,1, // 04
52+
1,9,1,1,9,1,1,1,1,9,1,1,1,1,9,1,1,1,1,1, // 05
53+
1,9,9,9,9,1,1,1,1,1,1,9,9,9,9,1,1,1,1,1, // 06
54+
1,9,9,9,9,9,9,9,9,1,1,1,9,9,9,9,9,9,9,1, // 07
55+
1,9,1,1,1,1,1,1,1,1,1,9,1,1,1,1,1,1,1,1, // 08
56+
1,9,1,9,9,9,9,9,9,9,1,1,9,9,9,9,9,9,9,1, // 09
57+
1,9,1,1,1,1,9,1,1,9,1,1,1,1,1,1,1,1,1,1, // 10
58+
1,9,9,9,9,9,1,9,1,9,1,9,9,9,9,9,1,1,1,1, // 11
59+
1,9,1,9,1,9,9,9,1,9,1,9,1,9,1,9,9,9,1,1, // 12
60+
1,9,1,9,1,9,9,9,1,9,1,9,1,9,1,9,9,9,1,1, // 13
61+
1,9,1,1,1,1,9,9,1,9,1,9,1,1,1,1,9,9,1,1, // 14
62+
1,9,1,1,9,1,1,1,1,9,1,1,1,1,9,1,1,1,1,1, // 15
63+
1,9,9,9,9,1,1,1,1,1,1,9,9,9,9,1,1,1,1,1, // 16
64+
1,1,9,9,9,9,9,9,9,1,1,1,9,9,9,1,9,9,9,9, // 17
65+
1,9,1,1,1,1,1,1,1,1,1,9,1,1,1,1,1,1,1,1, // 18
66+
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 19
67+
};
68+
69+
public static int GetMap(int x, int y)
70+
{
71+
if (x < 0 || x >= MAP_WIDTH || y < 0 || y >= MAP_HEIGHT)
72+
{
73+
return 9;
74+
}
75+
76+
return map[(y * MAP_WIDTH) + x];
77+
}
78+
}
79+
80+
public class MapSearchNode
81+
{
82+
public NodePosition position;
83+
AStarPathfinder pathfinder = null;
84+
85+
86+
public MapSearchNode(AStarPathfinder _pathfinder)
87+
{
88+
position = new NodePosition(0, 0);
89+
pathfinder = _pathfinder;
90+
}
91+
92+
public MapSearchNode(NodePosition pos, AStarPathfinder _pathfinder)
93+
{
94+
position = new NodePosition(pos.x, pos.y);
95+
pathfinder = _pathfinder;
96+
}
97+
98+
// Here's the heuristic function that estimates the distance from a Node
99+
// to the Goal.
100+
public float GoalDistanceEstimate(MapSearchNode nodeGoal)
101+
{
102+
double X = (double)position.x - (double)nodeGoal.position.x;
103+
double Y = (double)position.y - (double)nodeGoal.position.y;
104+
return ((float)System.Math.Sqrt((X * X) + (Y * Y)));
105+
}
106+
107+
public bool IsGoal(MapSearchNode nodeGoal)
108+
{
109+
return (position.x == nodeGoal.position.x && position.y == nodeGoal.position.y);
110+
}
111+
112+
public bool ValidNeigbour(int xOffset, int yOffset)
113+
{
114+
// Return true if the node is navigable and within grid bounds
115+
return (Map.GetMap(position.x + xOffset, position.y + yOffset) < 9);
116+
}
117+
118+
void AddNeighbourNode(int xOffset, int yOffset, NodePosition parentPos, AStarPathfinder aStarSearch)
119+
{
120+
if (ValidNeigbour(xOffset, yOffset) &&
121+
!(parentPos.x == position.x + xOffset && parentPos.y == position.y + yOffset))
122+
{
123+
NodePosition neighbourPos = new NodePosition(position.x + xOffset, position.y + yOffset);
124+
MapSearchNode newNode = pathfinder.AllocateMapSearchNode(neighbourPos);
125+
aStarSearch.AddSuccessor(newNode);
126+
}
127+
}
128+
129+
// This generates the successors to the given Node. It uses a helper function called
130+
// AddSuccessor to give the successors to the AStar class. The A* specific initialisation
131+
// is done for each node internally, so here you just set the state information that
132+
// is specific to the application
133+
public bool GetSuccessors(AStarPathfinder aStarSearch, MapSearchNode parentNode)
134+
{
135+
NodePosition parentPos = new NodePosition(0, 0);
136+
137+
if (parentNode != null)
138+
{
139+
parentPos = parentNode.position;
140+
}
141+
142+
// push each possible move except allowing the search to go backwards
143+
AddNeighbourNode(-1, 0, parentPos, aStarSearch);
144+
AddNeighbourNode( 0, -1, parentPos, aStarSearch);
145+
AddNeighbourNode( 1, 0, parentPos, aStarSearch);
146+
AddNeighbourNode( 0, 1, parentPos, aStarSearch);
147+
148+
return true;
149+
}
150+
151+
// given this node, what does it cost to move to successor. In the case
152+
// of our map the answer is the map terrain value at this node since that is
153+
// conceptually where we're moving
154+
public float GetCost(MapSearchNode successor)
155+
{
156+
// Implementation specific
157+
return Map.GetMap(successor.position.x, successor.position.y);
158+
}
159+
160+
public bool IsSameState(MapSearchNode rhs)
161+
{
162+
return (position.x == rhs.position.x &&
163+
position.y == rhs.position.y);
164+
}
165+
}
166+
167+
168+
public class AStarExample
169+
{
170+
static void Main()
171+
{
172+
AStarPathfinder pathfinder = new AStarPathfinder();
173+
Pathfind(new NodePosition(0, 0), new NodePosition(2, 4), pathfinder);
174+
}
175+
176+
static bool Pathfind(NodePosition startPos, NodePosition goalPos, AStarPathfinder pathfinder)
177+
{
178+
// Reset the allocated MapSearchNode pointer
179+
pathfinder.InitiatePathfind();
180+
181+
// Create a start state
182+
MapSearchNode nodeStart = pathfinder.AllocateMapSearchNode(startPos);
183+
184+
// Define the goal state
185+
MapSearchNode nodeEnd = pathfinder.AllocateMapSearchNode(goalPos);
186+
187+
// Set Start and goal states
188+
pathfinder.SetStartAndGoalStates(nodeStart, nodeEnd);
189+
190+
// Set state to Searching and perform the search
191+
AStarPathfinder.SearchState searchState = AStarPathfinder.SearchState.Searching;
192+
uint searchSteps = 0;
193+
194+
do
195+
{
196+
searchState = pathfinder.SearchStep();
197+
searchSteps++;
198+
}
199+
while (searchState == AStarPathfinder.SearchState.Searching);
200+
201+
// Search complete
202+
bool pathfindSucceeded = (searchState == AStarPathfinder.SearchState.Succeeded);
203+
204+
if (pathfindSucceeded)
205+
{
206+
// Success
207+
Path newPath = new Path();
208+
int numSolutionNodes = 0; // Don't count the starting cell in the path length
209+
210+
// Get the start node
211+
MapSearchNode node = pathfinder.GetSolutionStart();
212+
newPath.Add(node.position);
213+
++numSolutionNodes;
214+
215+
// Get all remaining solution nodes
216+
for( ;; )
217+
{
218+
node = pathfinder.GetSolutionNext();
219+
220+
if( node == null )
221+
{
222+
break;
223+
}
224+
225+
++numSolutionNodes;
226+
newPath.Add(node.position);
227+
};
228+
229+
// Once you're done with the solution we can free the nodes up
230+
pathfinder.FreeSolutionNodes();
231+
232+
System.Console.WriteLine("Solution path length: " + numSolutionNodes);
233+
System.Console.WriteLine("Solution: " + newPath.ToString());
234+
}
235+
else if (searchState == AStarPathfinder.SearchState.Failed)
236+
{
237+
// FAILED, no path to goal
238+
System.Console.WriteLine("Pathfind FAILED!");
239+
}
240+
241+
return pathfindSucceeded;
242+
}
243+
}

0 commit comments

Comments
 (0)