来源参考 http://blog.csdn.net/crayondeng/article/details/12342989
假设有人想从A点移动到一墙之隔的B点,如下图,绿色的是起点A,红色是终点B,蓝色方块是中间的墙。
选择路径中经过哪个方格的关键是下面这个等式:
F = G + H
这里:
* G = 从起点A,沿着产生的路径,移动到网格上指定方格的移动耗费。
* H = 从网格上那个方格移动到终点B的预估移动耗费。这经常被称为启发式的
参考java代码:
1 package com.java; 2 3 import java.util.ArrayList; 4 import java.util.Collections; 5 import java.util.Comparator; 6 7 public class TestAStar { 8 9 /** 10 * A*方法总结 11 * 12 * 好,现在你已经看完了整个说明,让我们把每一步的操作写在一起: 13 * 14 * 1,把起始格添加到开启列表。 2,重复如下的工作: a) 寻找开启列表中F值最低的格子。我们称它为当前格。 b) 把它切换到关闭列表。 c) 15 * 对相邻的8格中的每一个? 如果它不可通过或者已经在关闭列表中,略过它。反之如下。 16 * 如果它不在开启列表中,把它添加进去。把当前格作为这一格的父节点。记录这一格的F,G,和H值。 17 * 如果它已经在开启列表中,用G值为参考检查新的路径是否更好 18 * 。更低的G值意味着更好的路径。如果是这样,就把这一格的父节点改成当前格,并且重新计算这一格的G和F值 19 * 。如果你保持你的开启列表按F值排序,改变之后你可能需要重新对开启列表排序。 20 * 21 * d) 停止,当你 把目标格添加进了关闭列表(注解),这时候路径被找到,或者 没有找到目标格,开启列表已经空了。这时候,路径不存在。 22 * 3.保存路径。从目标格开始,沿着每一格的父节点移动直到回到起始格。这就是你的路径 F = G + H 23 */ 24 25 /** 26 * @param args 27 */ 28 public static void main(String[] args) { 29 TestAStar ts = new TestAStar(); 30 ts.initBarrierList(); 31 ts.startAstarroad(new PointHolder(1, 2), new PointHolder(5, 2)); 32 33 } 34 35 int sp = 10; 36 int spA = 14; 37 38 int hang = 5; 39 int lie = 7; 40 41 ArrayList<PointHolder> barrierList = new ArrayList<PointHolder>(); 42 43 public void initBarrierList() { 44 PointHolder ph = new PointHolder(3, 1); 45 barrierList.add(ph); 46 ph = new PointHolder(3, 2); 47 barrierList.add(ph); 48 ph = new PointHolder(3, 3); 49 barrierList.add(ph); 50 } 51 52 ArrayList<PointHolder> openList = new ArrayList<PointHolder>(); 53 ArrayList<PointHolder> closeList = new ArrayList<PointHolder>(); 54 55 public void startAstarroad(PointHolder srcph, PointHolder desph) { 56 57 // 当前点 58 PointHolder curph = null; 59 // 加入open 60 openList.add(srcph); 61 62 while (true) { 63 64 if (openList.isEmpty()) { 65 System.out.println("not find the point"); 66 return; 67 } 68 69 if (closeList.indexOf(desph) > 0) { 70 System.out.println("find"); 71 int ch = closeList.indexOf(desph); 72 closeList.get(ch).printPath(); 73 return; 74 } 75 // 排序 76 Collections.sort(openList, new ComparatorPh(desph)); 77 // 找最小的当前点 78 if (openList.size() > 0) { 79 curph = openList.get(0); 80 } 81 82 // 当前点加入close 83 closeList.add(curph); 84 openList.remove(0); 85 // 打印 86 curph.toStringPoint(); 87 // 找周围点 88 ArrayList<PointHolder> shipphs = getCatShipPh(curph); 89 for (PointHolder shipph : shipphs) { 90 shipph.prePoint = curph; 91 } 92 // 周围点在openlist中,比较最优H 加入open list 93 for (PointHolder shipph : shipphs) { 94 int ch = openList.indexOf(shipph); 95 if (ch >= 0) { 96 int shipph_H = shipph.getH(desph); 97 int openph_H = openList.get(ch).getH(desph); 98 if (shipph_H < openph_H) { 99 openList.get(ch).prePoint = shipph.prePoint; 100 } 101 } else { 102 openList.add(shipph); 103 } 104 } 105 106 } 107 108 } 109 110 // 得到可到达的点的集合 111 ArrayList<PointHolder> getCatShipPh(PointHolder ph) { 112 ArrayList<PointHolder> mList = new ArrayList<TestAStar.PointHolder>(); 113 int x = ph.x; 114 int y = ph.y; 115 boolean uEnable = false;// 上是否可用 116 boolean dEnable = false; 117 boolean lEnable = false; 118 boolean rEnable = false; 119 // 上 120 PointHolder ph1 = new PointHolder(x, y - 1); 121 if (validatePointHolder(ph1)) { 122 uEnable = true; 123 if (!closeList.contains(ph1)) 124 mList.add(ph1); 125 } 126 // 下 127 ph1 = new PointHolder(x, y + 1); 128 if (validatePointHolder(ph1)) { 129 dEnable = true; 130 if (!closeList.contains(ph1)) 131 mList.add(ph1); 132 } 133 // 左 134 ph1 = new PointHolder(x - 1, y); 135 if (validatePointHolder(ph1)) { 136 lEnable = true; 137 if (!closeList.contains(ph1)) 138 mList.add(ph1); 139 } 140 // 右 141 ph1 = new PointHolder(x + 1, y); 142 if (validatePointHolder(ph1)) { 143 rEnable = true; 144 if (!closeList.contains(ph1)) 145 mList.add(ph1); 146 } 147 // 左上 148 ph1 = new PointHolder(x - 1, y - 1); 149 if (validatePointHolder(ph1) && uEnable && lEnable) { 150 if (!closeList.contains(ph1)) 151 mList.add(ph1); 152 } 153 // 右上 154 ph1 = new PointHolder(x + 1, y - 1); 155 if (validatePointHolder(ph1) && uEnable && rEnable) { 156 if (!closeList.contains(ph1)) 157 mList.add(ph1); 158 } 159 // 左下 160 ph1 = new PointHolder(x - 1, y + 1); 161 if (validatePointHolder(ph1) && lEnable && dEnable) { 162 if (!closeList.contains(ph1)) 163 mList.add(ph1); 164 } 165 // 右下 166 ph1 = new PointHolder(x + 1, y + 1); 167 if (validatePointHolder(ph1) && rEnable && dEnable) { 168 if (!closeList.contains(ph1)) 169 mList.add(ph1); 170 } 171 return mList; 172 } 173 174 /*** 175 * 校验 是否符合 176 * 177 * @param ph 178 * @return 179 */ 180 boolean validatePointHolder(PointHolder ph) { 181 if (ph == null) 182 return false; 183 // 是否范围内 184 if (ph.x < 0 || ph.x >= 7 || ph.y < 0 || ph.y >= 5) 185 return false; 186 // 是否不可用 187 if (barrierList.contains(ph)) 188 return false; 189 return true; 190 } 191 192 public static class PointHolder { 193 194 public PointHolder(int x, int y) { 195 this.x = x; 196 this.y = y; 197 } 198 199 public int x; 200 public int y; 201 // 前一个节点 202 PointHolder prePoint; 203 public int H; 204 205 public int getH(PointHolder desPh) { 206 207 return Math.abs(desPh.x - x) + Math.abs(desPh.y - y); 208 } 209 210 public int getG() { 211 PointHolder ph = this; 212 int g = 0; 213 while (ph != null) { 214 g++; 215 ph = ph.prePoint; 216 } 217 return g; 218 } 219 220 @Override 221 public boolean equals(Object obj) { 222 PointHolder ph = (PointHolder) obj; 223 if (ph.x == x && ph.y == y) { 224 return true; 225 } else { 226 return false; 227 } 228 } 229 230 public void toStringPoint() { 231 System.out.println("P(" + x + "," + y + ")"); 232 } 233 234 public void printPath() { 235 ArrayList<PointHolder> mList = new ArrayList<TestAStar.PointHolder>(); 236 PointHolder ph = this; 237 while (ph != null) { 238 mList.add(ph); 239 ph = ph.prePoint; 240 } 241 242 for (int i = 0; i < mList.size(); i++) { 243 mList.get(i).toStringPoint(); 244 } 245 246 } 247 } 248 249 public class ComparatorPh implements Comparator<PointHolder> { 250 PointHolder desPh; 251 252 public ComparatorPh(PointHolder desPh) { 253 this.desPh = desPh; 254 } 255 256 @Override 257 public int compare(PointHolder o1, PointHolder o2) { 258 int f1 = o1.getG() + o1.getH(desPh); 259 int f2 = o2.getG() + o1.getH(desPh); 260 return f1 - f2; 261 } 262 263 } 264 265 }