Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1a6b932

Browse files
committed
--update : add A* algo
1 parent 6f31fb4 commit 1a6b932

File tree

1 file changed

+215
-0
lines changed

1 file changed

+215
-0
lines changed

‎src/PathFinder/AStart/index.js‎

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
/**
2+
* h is calculate by Euclidean Distance.
3+
* Complexity can be imporved by using Min-heap.
4+
* Worse case time complexity is O(E), where E is the number of edges in the graph.
5+
* Read more: [http://theory.stanford.edu/~amitp/GameProgramming/AStarComparison.html]
6+
*/
7+
function AStar(s, e, row, col, inputGrid) {
8+
const Row = row;
9+
const Col = col;
10+
const start = s;
11+
const end = e;
12+
13+
function cell() {
14+
this.cellValue = null;
15+
this.parent_i = -1;
16+
this.parent_j = -1;
17+
this.h = Number.MAX_SAFE_INTEGER;
18+
this.g = Number.MAX_SAFE_INTEGER;
19+
this.f = Number.MAX_SAFE_INTEGER;
20+
}
21+
22+
function pair(i, j, f) {
23+
this.i = i;
24+
this.j = j;
25+
this.f = f;
26+
}
27+
28+
const grid = [];
29+
30+
for (let i = 0; i < Row; i += 1) {
31+
grid[i] = [];
32+
for (let j = 0; j < Col; j += 1) {
33+
grid[i][j] = new cell();
34+
grid[i][j].cellValue = inputGrid[i][j];
35+
}
36+
}
37+
38+
39+
const isValid = (i, j) => i >= 0 && j >= 0 && i < Row && j < Col;
40+
41+
const isDestination = (i, j) => end.i === i && end.j === j;
42+
43+
const isBlocked = (i, j) => grid[i][j].cellValue === 0;
44+
45+
const euclideanDistance = (i, j) => Math.abs(i - end.i) * Math.abs(i - end.i)
46+
+ Math.abs(j - end.j) * Math.abs(j - end.j);
47+
48+
const trace = () => {
49+
const endRow = end.i;
50+
const endCol = end.j;
51+
const startRow = start.i;
52+
const startCol = start.j;
53+
54+
let i = endRow;
55+
let j = endCol;
56+
const path = [];
57+
58+
while (!(i === startRow && j === startCol)) {
59+
path.push([i, j]);
60+
61+
const nextI = grid[i][j].parent_i;
62+
const nextJ = grid[i][j].parent_j;
63+
i = nextI;
64+
j = nextJ;
65+
}
66+
path.push([i, j]);
67+
68+
for (let i = 0; i < path.length; i += 1) {
69+
console.log(path[i]);
70+
}
71+
};
72+
73+
const neighbourExplorer = (i, j, parentI, parentJ, openList, openListMap,
74+
closedListMap, distanceFromParent) => {
75+
if (!isValid(i, j)) {
76+
return false;
77+
}
78+
79+
if (isBlocked(i, j)) {
80+
return false;
81+
}
82+
83+
if (isDestination(i, j)) {
84+
grid[i][j].parent_i = parentI;
85+
grid[i][j].parent_j = parentJ;
86+
trace();
87+
return true;
88+
}
89+
90+
91+
const g = grid[parentI][parentJ].g + distanceFromParent;
92+
const h = euclideanDistance(i, j);
93+
const f = g + h;
94+
95+
if ((openListMap[[i, j]] && openListMap[[i, j]] > f)
96+
|| (closedListMap[[i, j]] && closedListMap[[i, j]] > f)
97+
|| (!closedListMap[[i, j]] && !openListMap[[i, j]])) {
98+
openListMap[[i, j]] = f;
99+
grid[i][j].parent_i = parentI;
100+
grid[i][j].parent_j = parentJ;
101+
grid[i][j].g = g;
102+
grid[i][j].h = h;
103+
grid[i][j].f = g + h;
104+
105+
const item = new pair(i, j, f);
106+
// can be improved by using Min-Heap DataStructure
107+
if (!openList.length) {
108+
openList.push(item);
109+
}
110+
let k = 0;
111+
let temp = item;
112+
for (; k < openList.length; k += 1) {
113+
if (openList[k].f > item.f) {
114+
[temp, openList[k]] = [openList[k], temp];
115+
}
116+
}
117+
openList[k] = temp;
118+
}
119+
return false;
120+
};
121+
122+
const search = () => {
123+
if (!isValid(start.i, start.j) || !isValid(end.i, end.j)) {
124+
return false;
125+
}
126+
127+
let i = start.i;
128+
let j = start.j;
129+
const openList = [];
130+
const openListMap = new Map();
131+
const closedListMap = new Map();
132+
let foundDest = false;
133+
134+
// Initialize start point
135+
grid[i][j].h = 0;
136+
grid[i][j].g = 0;
137+
grid[i][j].f = 0;
138+
139+
openList.push(new pair(i, j, 0.0));
140+
141+
openListMap[[i, j]] = 0;
142+
143+
while (openList.length > 0) {
144+
const currentCell = openList.shift();
145+
i = currentCell.i;
146+
j = currentCell.j;
147+
const currentF = currentCell.f;
148+
closedListMap[[i, j]] = currentF;
149+
const parentI = i;
150+
const parentJ = j;
151+
152+
foundDest = neighbourExplorer(i - 1, j, parentI, parentJ, openList, openListMap, closedListMap, 1); // for North
153+
if (foundDest) { break; }
154+
foundDest = neighbourExplorer(i, j - 1, parentI, parentJ, openList, openListMap, closedListMap, 1); // for West
155+
if (foundDest) { break; }
156+
foundDest = neighbourExplorer(i + 1, j, parentI, parentJ, openList, openListMap, closedListMap, 1); // for South
157+
if (foundDest) { break; }
158+
foundDest = neighbourExplorer(i, j + 1, parentI, parentJ, openList, openListMap, closedListMap, 1); // for East
159+
if (foundDest) { break; }
160+
foundDest = neighbourExplorer(i - 1, j - 1, parentI, parentJ, openList, openListMap, closedListMap, 1); // for N.W
161+
if (foundDest) { break; }
162+
foundDest = neighbourExplorer(i - 1, j + 1, parentI, parentJ, openList, openListMap, closedListMap, 1);// for S.W
163+
if (foundDest) { break; }
164+
foundDest = neighbourExplorer(i + 1, j + 1, parentI, parentJ, openList, openListMap, closedListMap, 1);// for S.E
165+
if (foundDest) { break; }
166+
foundDest = neighbourExplorer(i + 1, j - 1, parentI, parentJ, openList, openListMap, closedListMap, 1);// for N.E
167+
if (foundDest) { break; }
168+
}
169+
170+
171+
if (!foundDest) {
172+
return false;
173+
}
174+
return true;
175+
};
176+
search();
177+
}
178+
179+
180+
// const inputGrid = [
181+
// [1, 0, 1, 1, 1, 1, 0, 1, 1, 1],
182+
// [1, 1, 1, 0, 1, 1, 1, 0, 1, 1],
183+
// [1, 1, 1, 0, 1, 1, 0, 1, 0, 1],
184+
// [0, 0, 1, 0, 1, 0, 0, 0, 0, 1],
185+
// [1, 1, 1, 0, 1, 1, 1, 0, 1, 0],
186+
// [1, 0, 1, 1, 1, 1, 0, 1, 0, 0],
187+
// [1, 0, 0, 0, 0, 1, 0, 0, 0, 1],
188+
// [1, 0, 1, 1, 1, 1, 0, 1, 1, 1],
189+
// [1, 1, 1, 0, 0, 0, 1, 0, 0, 1],
190+
// ];
191+
192+
const inputGrid = [
193+
[1, 0, 0, 0, 0, 0],
194+
[1, 1, 1, 1, 1, 1],
195+
[1, 0, 0, 0, 0, 0],
196+
[1, 1, 1, 1, 1, 1],
197+
];
198+
199+
const ROW = inputGrid.length;
200+
const COL = inputGrid[0].length;
201+
const start = {
202+
i: 0,
203+
j: 0,
204+
};
205+
const end = {
206+
i: 3,
207+
j: 5,
208+
};
209+
210+
AStar(start, end, ROW, COL, inputGrid);
211+
212+
213+
module.exports = {
214+
AStar,
215+
};

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /