A*算法JS版本(转存的资料)
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html>
4 <head>
5 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
6 <title>my rpg game - dh20156风之石</title>
7 <style type="text/css">
8 table {
9 border-left:#CCC 1px solid;
10 border-top:#CCC 1px solid;
11 border-collapse:collapse;
12 }
13 td {
14 border-right:#CCC 1px solid;
15 border-bottom:#CCC 1px solid;
16 height:10px;
17 width:10px;
18 font-size:0px;
19 color:highlight;
20 }
21 </style>
22 </head>
23 <body>
24 <script type="text/javascript">
25 var map = function(){
26 var owner = this;
27 //起点
28 this.startNode = [];
29 //map table
30 this.table = null;
31 //清除颜色
32 this.clearColor = function(){
33 var xl = this.length;
34 if(xl<1){
35 return;
36 }
37 var yl = this[0].length;
38 if(yl<1){
39 return;
40 }
41 var maptable = this.table;
42 maptable.style.display = 'none';
43 for(var i=0;i<xl;i++){
44 for(var n=0;n<yl;n++){
45 maptable.rows[i].cells[n].style.background='';
46 if(this[i][n]!=0){
47 maptable.rows[i].cells[n].style.background='background';
48 }
49 }
50 }
51 maptable.style.display = 'block';
52 }
53 //寻路
54 this.run = function(obj){
55 var x0=0,y0=0,x1=0,y1=0;
56 var _sn = this.startNode;
57 var _en = this.endNode;
58 if(_sn.length<1){
59 obj.style.background = 'red';
60 x0 = obj.parentNode.rowIndex;
61 y0 = obj.cellIndex;
62 this.startNode = [x0,y0];
63 }else{
64 this.clearColor();
65 obj.style.background = 'red';
66 x0 = _sn[0];
67 y0 = _sn[1];
68 x1 = obj.parentNode.rowIndex;
69 y1 = obj.cellIndex;
70 var path = this.getPath(x0,y0,x1,y1);
71 this.showPath(path);
72 this.startNode = [x1,y1];
73 }
74 }
75 //点击事件
76 this.click = function(event){
77 event = event||window.event;
78 var obj = event.srcElement||event.target;
79 if(obj.tagName!='TD'){
80 return;
81 }
82 owner.run(obj);
83 }
84 //创建视图
85 this.setView = function(){
86 var xl = this.length;
87 if(xl<1){
88 return;
89 }
90 var yl = this[0].length;
91 if(yl<1){
92 return;
93 }
94 var trstr = '<tr>'+new Array(yl+1).join('<td></td>')+'</tr>';
95 var tbstr = '<table id="amap">'+new Array(xl+1).join(trstr)+'</table>';
96 document.write(tbstr);
97 var maptable = this.table = document.getElementById("amap");
98 for(var i=0;i<xl;i++){
99 for(var n=0;n<yl;n++){
100 if(this[i][n]!=0){
101 maptable.rows[i].cells[n].style.background='background';
102 }
103 }
104 }
105 if(window.attachEvent){
106 this.table.attachEvent('onclick',this.click);
107 }else{
108 this.table.addEventListener('click',this.click,false);
109 }
110 }
111 //显示路径
112 this.showPath = function(path){
113 if(path!=undefined && path.length>0){
114 var maptable = this.table;
115 var pos = null;
116 var move = function(){
117 if(path.length>0){
118 pos = path.shift();
119 maptable.rows[pos[0]].cells[pos[1]].style.background='red';
120 window.setTimeout(arguments.callee,30);
121 }
122 }
123 move();
124 }else{
125 document.title = 'Did not find the path!';
126 }
127 }
128 }
129
130 var Astar = function(map){
131 //dh20156;
132 this.map = map;
133 //已探索列表
134 this.chkList = [];
135 //开放对象列表
136 this.openList = [];
137 //取G值
138 this.getG = function(x0,y0,x1,y1){
139 if(Math.abs(x0-x1)==1 && Math.abs(y0-y1)==1){
140 return 14;
141 }else{
142 return 10;
143 }
144 }
145 //取H值Diagonal Shortcut
146 this.getH = function(x0,y0,x1,y1){
147 var xDistance = Math.abs(x0-x1);
148 var yDistance = Math.abs(y0-y1);
149 if(xDistance > yDistance){
150 return (14*yDistance + 10*(xDistance-yDistance));
151 }else{
152 return (14*xDistance + 10*(yDistance-xDistance));
153 }
154 }
155 //节点对象
156 this.point = function(_f,_g,_h,_x,_y,_p){
157 this.f = _f;
158 this.g = _g;
159 this.h = _h;
160 this.x = _x;
161 this.y = _y;
162 this.p = _p;
163 }
164 //获取检测子节点对象
165 this.setPoints = function(_node,x1,y1){
166 var map = this.map;
167 var x = _node.x;
168 var y = _node.y;
169 var g = _node.g;
170 var t = x-1;
171 var b = x+1;
172 var l = y-1;
173 var r = y+1;
174 var maxX = map.length;
175 var maxY = map[0].length;
176 if(t>=0 && l>=0 && map[t][l]==0 && map[t][y]==0 && map[x][l]==0) this.chkPoint(_node,x,y,g,t,l,x1,y1);//1
177 if(t>=0 && map[t][y]==0) this.chkPoint(_node,x,y,g,x-1,y,x1,y1);//2
178 if(t>=0 && r<maxY && map[t][r]==0 && map[t][y]==0 && map[x][r]==0) this.chkPoint(_node,x,y,g,t,r,x1,y1);//3
179 if(l>=0 && map[x][l]==0) this.chkPoint(_node,x,y,g,x,y-1,x1,y1);//4
180 if(r<maxY && map[x][r]==0) this.chkPoint(_node,x,y,g,x,y+1,x1,y1);//6
181 if(b<maxX && l>=0 && map[b][l]==0 && map[x][l]==0 && map[b][y]==0) this.chkPoint(_node,x,y,g,b,l,x1,y1);//7
182 if(b<maxX && map[b][y]==0) this.chkPoint(_node,x,y,g,x+1,y,x1,y1);//8
183 if(b<maxX && r<maxY && map[b][r]==0 && map[b][y]==0 && map[x][r]==0) this.chkPoint(_node,x,y,g,b,r,x1,y1);//9
184 }
185 //检测子节点对象
186 this.chkPoint = function(_fnode,_x0,_y0,_g,_x1,_y1,_x2,_y2){
187 var open = this.openList;
188 var chk = this.chkList;
189 var _id = new String(_x1+'_'+_y1);
190 var _point = null;
191 if(undefined == (_point = chk[_id])){
192 _point = new this.point(0,0,0,_x1,_y1,_fnode);
193 open[open.length] = _point;
194 chk[_id] = _point;
195 _point.g = _g + this.getG(_x0,_y0,_x1,_y1); //起点到当前点实际值
196 _point.h = this.getH(_x1,_y1,_x2,_y2); //终点到当前点的估价
197 _point.f = _point.g + _point.h;
198 }else{
199 var _CNG = _g + this.getG(_x0,_y0,_x1,_y1);
200 if(_point.g>_CNG){//保留小G,替换parentNode
201 _point.g = _CNG;
202 _point.f = _point.g + _point.h;
203 _point.p = _fnode;
204 }
205 }
206 }
207 //探索路径
208 this.getPath = function(x0,y0,x1,y1){
209 var st = new Date();
210 var tp = [];
211 var open = this.openList;
212 var map = this.map;
213 if(map[x0][y0]!=0 || map[x1][y1]!=0){
214 return tp;
215 }
216 var _sh = this.getH(x0,y0,x1,y1);
217 open[0] = new this.point(_sh,0,_sh,x0,y0,null);
218 var oll=0,nowNode=null;
219 while(0<(oll=open.length)){
220 var maxNode,minIndex,minf=10000000000;
221 for(var i=0;i<oll;i++){
222 maxNode = open[i];
223 if(minf>maxNode.f){
224 minf = maxNode.f;
225 minIndex = i;
226 }
227 }
228 nowNode = open[minIndex];
229 open[minIndex] = open[oll-1];
230 open.length--;
231 if(nowNode.x==x1 && nowNode.y==y1){
232 while(nowNode.p!=null){
233 tp.push([nowNode.x,nowNode.y]);
234 nowNode = nowNode.p;
235 }
236 tp.push([x0,y0]);
237 break;
238 }
239 this.setPoints(nowNode,x1,y1);
240 }
241 open = this.openList = this.chkList = map = [];
242 document.title = new Date()-st+' ms, '+tp.length+'steps.';
243 return tp.slice(0).reverse();
244 }
245 }
246
247 var maps = [ // handest
248 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
249 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
250 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
251 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
252 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
253 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
254 [0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
255 [0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
256 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
257 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
258 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
259 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
260 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
261 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
262 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
263 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
264 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
265 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
266 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
267 [0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
268 [0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
269 [0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
270 [0,0,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
271 [0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
272 [0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
273 [0,0,1,1,1,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
274 [0,0,0,0,1,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
275 [0,0,0,0,1,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
276 [0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
277 [0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0],
278 [0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,1,0,1,0,0,1,0,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
279 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
280 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0],
281 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0],
282 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0],
283 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,1,1,0,0,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0],
284 [0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0],
285 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0],
286 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
287 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
288 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
289 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0],
290 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
291 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
292 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
293 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
294 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0],
295 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0],
296 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0],
297 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
298 ];
299
300 map.call(maps);
301 maps.setView();
302 Astar.call(maps,maps);
303
304 </script>
305 <h1>Javascript版A*(a star)算法!</h1>
306 <h3>在白色表格中点击,第一次设置起点,第二次设置终点,将自动找到路径!</h3>
307 </body>
308 </html>
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html>
4 <head>
5 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
6 <title>my rpg game - dh20156风之石</title>
7 <style type="text/css">
8 table {
9 border-left:#CCC 1px solid;
10 border-top:#CCC 1px solid;
11 border-collapse:collapse;
12 }
13 td {
14 border-right:#CCC 1px solid;
15 border-bottom:#CCC 1px solid;
16 height:10px;
17 width:10px;
18 font-size:0px;
19 color:highlight;
20 }
21 </style>
22 </head>
23 <body>
24 <script type="text/javascript">
25 var map = function(){
26 var owner = this;
27 //起点
28 this.startNode = [];
29 //map table
30 this.table = null;
31 //清除颜色
32 this.clearColor = function(){
33 var xl = this.length;
34 if(xl<1){
35 return;
36 }
37 var yl = this[0].length;
38 if(yl<1){
39 return;
40 }
41 var maptable = this.table;
42 maptable.style.display = 'none';
43 for(var i=0;i<xl;i++){
44 for(var n=0;n<yl;n++){
45 maptable.rows[i].cells[n].style.background='';
46 if(this[i][n]!=0){
47 maptable.rows[i].cells[n].style.background='background';
48 }
49 }
50 }
51 maptable.style.display = 'block';
52 }
53 //寻路
54 this.run = function(obj){
55 var x0=0,y0=0,x1=0,y1=0;
56 var _sn = this.startNode;
57 var _en = this.endNode;
58 if(_sn.length<1){
59 obj.style.background = 'red';
60 x0 = obj.parentNode.rowIndex;
61 y0 = obj.cellIndex;
62 this.startNode = [x0,y0];
63 }else{
64 this.clearColor();
65 obj.style.background = 'red';
66 x0 = _sn[0];
67 y0 = _sn[1];
68 x1 = obj.parentNode.rowIndex;
69 y1 = obj.cellIndex;
70 var path = this.getPath(x0,y0,x1,y1);
71 this.showPath(path);
72 this.startNode = [x1,y1];
73 }
74 }
75 //点击事件
76 this.click = function(event){
77 event = event||window.event;
78 var obj = event.srcElement||event.target;
79 if(obj.tagName!='TD'){
80 return;
81 }
82 owner.run(obj);
83 }
84 //创建视图
85 this.setView = function(){
86 var xl = this.length;
87 if(xl<1){
88 return;
89 }
90 var yl = this[0].length;
91 if(yl<1){
92 return;
93 }
94 var trstr = '<tr>'+new Array(yl+1).join('<td></td>')+'</tr>';
95 var tbstr = '<table id="amap">'+new Array(xl+1).join(trstr)+'</table>';
96 document.write(tbstr);
97 var maptable = this.table = document.getElementById("amap");
98 for(var i=0;i<xl;i++){
99 for(var n=0;n<yl;n++){
100 if(this[i][n]!=0){
101 maptable.rows[i].cells[n].style.background='background';
102 }
103 }
104 }
105 if(window.attachEvent){
106 this.table.attachEvent('onclick',this.click);
107 }else{
108 this.table.addEventListener('click',this.click,false);
109 }
110 }
111 //显示路径
112 this.showPath = function(path){
113 if(path!=undefined && path.length>0){
114 var maptable = this.table;
115 var pos = null;
116 var move = function(){
117 if(path.length>0){
118 pos = path.shift();
119 maptable.rows[pos[0]].cells[pos[1]].style.background='red';
120 window.setTimeout(arguments.callee,30);
121 }
122 }
123 move();
124 }else{
125 document.title = 'Did not find the path!';
126 }
127 }
128 }
129
130 var Astar = function(map){
131 //dh20156;
132 this.map = map;
133 //已探索列表
134 this.chkList = [];
135 //开放对象列表
136 this.openList = [];
137 //取G值
138 this.getG = function(x0,y0,x1,y1){
139 if(Math.abs(x0-x1)==1 && Math.abs(y0-y1)==1){
140 return 14;
141 }else{
142 return 10;
143 }
144 }
145 //取H值Diagonal Shortcut
146 this.getH = function(x0,y0,x1,y1){
147 var xDistance = Math.abs(x0-x1);
148 var yDistance = Math.abs(y0-y1);
149 if(xDistance > yDistance){
150 return (14*yDistance + 10*(xDistance-yDistance));
151 }else{
152 return (14*xDistance + 10*(yDistance-xDistance));
153 }
154 }
155 //节点对象
156 this.point = function(_f,_g,_h,_x,_y,_p){
157 this.f = _f;
158 this.g = _g;
159 this.h = _h;
160 this.x = _x;
161 this.y = _y;
162 this.p = _p;
163 }
164 //获取检测子节点对象
165 this.setPoints = function(_node,x1,y1){
166 var map = this.map;
167 var x = _node.x;
168 var y = _node.y;
169 var g = _node.g;
170 var t = x-1;
171 var b = x+1;
172 var l = y-1;
173 var r = y+1;
174 var maxX = map.length;
175 var maxY = map[0].length;
176 if(t>=0 && l>=0 && map[t][l]==0 && map[t][y]==0 && map[x][l]==0) this.chkPoint(_node,x,y,g,t,l,x1,y1);//1
177 if(t>=0 && map[t][y]==0) this.chkPoint(_node,x,y,g,x-1,y,x1,y1);//2
178 if(t>=0 && r<maxY && map[t][r]==0 && map[t][y]==0 && map[x][r]==0) this.chkPoint(_node,x,y,g,t,r,x1,y1);//3
179 if(l>=0 && map[x][l]==0) this.chkPoint(_node,x,y,g,x,y-1,x1,y1);//4
180 if(r<maxY && map[x][r]==0) this.chkPoint(_node,x,y,g,x,y+1,x1,y1);//6
181 if(b<maxX && l>=0 && map[b][l]==0 && map[x][l]==0 && map[b][y]==0) this.chkPoint(_node,x,y,g,b,l,x1,y1);//7
182 if(b<maxX && map[b][y]==0) this.chkPoint(_node,x,y,g,x+1,y,x1,y1);//8
183 if(b<maxX && r<maxY && map[b][r]==0 && map[b][y]==0 && map[x][r]==0) this.chkPoint(_node,x,y,g,b,r,x1,y1);//9
184 }
185 //检测子节点对象
186 this.chkPoint = function(_fnode,_x0,_y0,_g,_x1,_y1,_x2,_y2){
187 var open = this.openList;
188 var chk = this.chkList;
189 var _id = new String(_x1+'_'+_y1);
190 var _point = null;
191 if(undefined == (_point = chk[_id])){
192 _point = new this.point(0,0,0,_x1,_y1,_fnode);
193 open[open.length] = _point;
194 chk[_id] = _point;
195 _point.g = _g + this.getG(_x0,_y0,_x1,_y1); //起点到当前点实际值
196 _point.h = this.getH(_x1,_y1,_x2,_y2); //终点到当前点的估价
197 _point.f = _point.g + _point.h;
198 }else{
199 var _CNG = _g + this.getG(_x0,_y0,_x1,_y1);
200 if(_point.g>_CNG){//保留小G,替换parentNode
201 _point.g = _CNG;
202 _point.f = _point.g + _point.h;
203 _point.p = _fnode;
204 }
205 }
206 }
207 //探索路径
208 this.getPath = function(x0,y0,x1,y1){
209 var st = new Date();
210 var tp = [];
211 var open = this.openList;
212 var map = this.map;
213 if(map[x0][y0]!=0 || map[x1][y1]!=0){
214 return tp;
215 }
216 var _sh = this.getH(x0,y0,x1,y1);
217 open[0] = new this.point(_sh,0,_sh,x0,y0,null);
218 var oll=0,nowNode=null;
219 while(0<(oll=open.length)){
220 var maxNode,minIndex,minf=10000000000;
221 for(var i=0;i<oll;i++){
222 maxNode = open[i];
223 if(minf>maxNode.f){
224 minf = maxNode.f;
225 minIndex = i;
226 }
227 }
228 nowNode = open[minIndex];
229 open[minIndex] = open[oll-1];
230 open.length--;
231 if(nowNode.x==x1 && nowNode.y==y1){
232 while(nowNode.p!=null){
233 tp.push([nowNode.x,nowNode.y]);
234 nowNode = nowNode.p;
235 }
236 tp.push([x0,y0]);
237 break;
238 }
239 this.setPoints(nowNode,x1,y1);
240 }
241 open = this.openList = this.chkList = map = [];
242 document.title = new Date()-st+' ms, '+tp.length+'steps.';
243 return tp.slice(0).reverse();
244 }
245 }
246
247 var maps = [ // handest
248 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
249 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
250 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
251 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
252 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
253 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
254 [0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
255 [0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
256 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
257 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
258 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
259 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
260 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
261 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
262 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
263 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
264 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
265 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
266 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
267 [0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
268 [0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
269 [0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
270 [0,0,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
271 [0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
272 [0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
273 [0,0,1,1,1,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
274 [0,0,0,0,1,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
275 [0,0,0,0,1,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
276 [0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
277 [0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0],
278 [0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,1,0,1,0,0,1,0,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
279 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
280 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0],
281 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0],
282 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0],
283 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,1,1,0,0,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0],
284 [0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0],
285 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0],
286 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
287 [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
288 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
289 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0],
290 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
291 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
292 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
293 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
294 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0],
295 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0],
296 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0],
297 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
298 ];
299
300 map.call(maps);
301 maps.setView();
302 Astar.call(maps,maps);
303
304 </script>
305 <h1>Javascript版A*(a star)算法!</h1>
306 <h3>在白色表格中点击,第一次设置起点,第二次设置终点,将自动找到路径!</h3>
307 </body>
308 </html>