八数码java_A*算法解决八数码问题 Java语言实现

该博客介绍了如何使用Java实现八数码问题的A*算法。通过创建EightPuzzle类,实现了状态的存储、比较、目标状态判断、求解路径等功能。算法中利用了优先队列按照f(n)值排序,通过上、下、左、右四个方向移动0元素,寻找目标状态。
摘要由CSDN通过智能技术生成

1 importjava.io.BufferedReader;2 importjava.io.FileNotFoundException;3 importjava.io.FileReader;4 importjava.io.IOException;5 importjava.util.ArrayList;6 importjava.util.Arrays;7 importjava.util.Collections;8 importjava.util.Scanner;9

10 @SuppressWarnings("rawtypes")11 public class EightPuzzle implementsComparable{12 private int[] num = new int[9];13 private int depth; //当前的深度即走到当前状态的步骤

14 private int evaluation; //从起始状态到目标的最小估计值

15 private int misposition; //到目标的最小估计

16 private EightPuzzle parent; //当前状态的父状态

17 public int[] getNum() {18 returnnum;19 }20 public void setNum(int[] num) {21 this.num =num;22 }23 public intgetDepth() {24 returndepth;25 }26 public void setDepth(intdepth) {27 this.depth =depth;28 }29 public intgetEvaluation() {30 returnevaluation;31 }32 public void setEvaluation(intevaluation) {33 this.evaluation =evaluation;34 }35 public intgetMisposition() {36 returnmisposition;37 }38 public void setMisposition(intmisposition) {39 this.misposition =misposition;40 }41 publicEightPuzzle getParent() {42 returnparent;43 }44 public voidsetParent(EightPuzzle parent) {45 this.parent =parent;46 }47

48 /**

49 * 判断当前状态是否为目标状态50 *@paramtarget51 *@return

52 */

53 public booleanisTarget(EightPuzzle target){54 returnArrays.equals(getNum(), target.getNum());55 }56

57 /**

58 * 求f(n) = g(n)+h(n);59 * 初始化状态信息60 *@paramtarget61 */

62 public voidinit(EightPuzzle target){63 int temp = 0;64 for(int i=0;i<9;i++){65 if(num[i]!=target.getNum()[i])66 temp++;67 }68 this.setMisposition(temp);69 if(this.getParent()==null){70 this.setDepth(0);71 }else{72 this.depth = this.parent.getDepth()+1;73 }74 this.setEvaluation(this.getDepth()+this.getMisposition());75 }76

77 /**

78 * 求逆序值并判断是否有解79 *@paramtarget80 *@return有解:true 无解:false81 */

82 public booleanisSolvable(EightPuzzle target){83 int reverse = 0;84 for(int i=0;i<9;i++){85 for(int j=0;jnum[i])87 reverse++;88 if(target.getNum()[j]>target.getNum()[i])89 reverse++;90 }91 }92 if(reverse % 2 == 0)93 return true;94 return false;95 }96 @Override97 public intcompareTo(Object o) {98 EightPuzzle c =(EightPuzzle) o;99 return this.evaluation-c.getEvaluation();//默认排序为f(n)由小到大排序

100 }101 /**

102 *@return返回0在八数码中的位置103 */

104 public intgetZeroPosition(){105 int position = -1;106 for(int i=0;i<9;i++){107 if(this.num[i] == 0){108 position =i;109 }110 }111 returnposition;112 }113 /**

114 *115 *@paramopen 状态集合116 *@return判断当前状态是否存在于open表中117 */

118 public int isContains(ArrayListopen){119 for(int i=0;i

127 *128 *@return小于3的不能上移返回false129 */

130 public booleanisMoveUp() {131 int position =getZeroPosition();132 if(position<=2){133 return false;134 }135 return true;136 }137 /**

138 *139 *@return大于6返回false140 */

141 public booleanisMoveDown() {142 int position =getZeroPosition();143 if(position>=6){144 return false;145 }146 return true;147 }148 /**

149 *150 *@return0,3,6返回false151 */

152 public booleanisMoveLeft() {153 int position =getZeroPosition();154 if(position%3 == 0){155 return false;156 }157 return true;158 }159 /**

160 *161 *@return2,5,8不能右移返回false162 */

163 public booleanisMoveRight() {164 int position =getZeroPosition();165 if((position)%3 == 2){166 return false;167 }168 return true;169 }170 /**

171 *172 *@parammove 0:上,1:下,2:左,3:右173 *@return返回移动后的状态174 */

175 public EightPuzzle moveUp(intmove){176 EightPuzzle temp = newEightPuzzle();177 int[] tempnum = (int[])num.clone();178 temp.setNum(tempnum);179 int position = getZeroPosition(); //0的位置

180 int p=0; //与0换位置的位置

181 switch(move){182 case 0:183 p = position-3;184 temp.getNum()[position] =num[p];185 break;186 case 1:187 p = position+3;188 temp.getNum()[position] =num[p];189 break;190 case 2:191 p = position-1;192 temp.getNum()[position] =num[p];193 break;194 case 3:195 p = position+1;196 temp.getNum()[position] =num[p];197 break;198 }199 temp.getNum()[p] = 0;200 returntemp;201 }202 /**

203 * 按照八数码的格式输出204 */

205 public voidprint(){206 for(int i=0;i<9;i++){207 if(i%3 == 2){208 System.out.println(this.num[i]);209 }else{210 System.out.print(this.num[i]+" ");211 }212 }213 }214 /**

215 * 反序列的输出状态216 */

217 public voidprintRoute(){218 EightPuzzle temp = null;219 int count = 0;220 temp = this;221 while(temp!=null){222 temp.print();223 System.out.println("----------分割线----------");224 temp =temp.getParent();225 count++;226 }227 System.out.println("步骤数:"+(count-1));228 }229 /**

230 *231 *@paramopen open表232 *@paramclose close表233 *@paramparent 父状态234 *@paramtarget 目标状态235 */

236 public void operation(ArrayList open,ArrayListclose,EightPuzzle parent,EightPuzzle target){237 if(this.isContains(close) == -1){238 int position = this.isContains(open);239 if(position == -1){240 this.parent =parent;241 this.init(target);242 open.add(this);243 }else{244 if(this.getDepth()

254 @SuppressWarnings("unchecked")255 public static voidmain(String args[]){256 //定义open表

257 ArrayList open = new ArrayList();258 ArrayList close = new ArrayList();259 EightPuzzle start = newEightPuzzle();260 EightPuzzle target = newEightPuzzle();261

262 //BufferedReader br = new BufferedReader(new FileReader("./input.txt") );

263 String lineContent = null;264 int stnum[] = {2,1,6,4,0,8,7,5,3};265 int tanum[] = {1,2,3,8,0,4,7,6,5};266 int order = 0;267 try{268 BufferedReader br;269 br = new BufferedReader(new FileReader("input.txt") );270 while((lineContent=br.readLine())!=null){271 String[] str = lineContent.split(",");272 for(int i = 0 ;i

276 tanum[i] =Integer.parseInt(str[i]);277 }278 order++;279 }280 } catch(NumberFormatException e) {281 System.out.println("请检查输入文件的格式,例如:2,1,6,4,0,8,7,5,3 换行 1,2,3,8,0,4,7,6,5");282 e.printStackTrace();283 } catch(IOException e) {284 System.out.println("当前目录下无input.txt文件。");285 e.printStackTrace();286 }287 start.setNum(stnum);288 target.setNum(tanum);289 long startTime=System.currentTimeMillis(); //获取开始时间

290 if(start.isSolvable(target)){291 //初始化初始状态

292 start.init(target);293 open.add(start);294 while(open.isEmpty() == false){295 Collections.sort(open); //按照evaluation的值排序

296 EightPuzzle best = open.get(0); //从open表中取出最小估值的状态并移除open表

297 open.remove(0);298 close.add(best);299 if(best.isTarget(target)){300 //输出

301 best.printRoute();302 long end=System.currentTimeMillis(); //获取结束时间

303 System.out.println("程序运行时间: "+(end-startTime)+"ms");304 System.exit(0);305 }306 intmove;307 //由best状态进行扩展并加入到open表中308 //0的位置上移之后状态不在close和open中设定best为其父状态,并初始化f(n)估值函数

309 if(best.isMoveUp()){310 move = 0;311 EightPuzzle up =best.moveUp(move);312 up.operation(open, close, best, target);313 }314 //0的位置下移之后状态不在close和open中设定best为其父状态,并初始化f(n)估值函数

315 if(best.isMoveDown()){316 move = 1;317 EightPuzzle up =best.moveUp(move);318 up.operation(open, close, best, target);319 }320 //0的位置左移之后状态不在close和open中设定best为其父状态,并初始化f(n)估值函数

321 if(best.isMoveLeft()){322 move = 2;323 EightPuzzle up =best.moveUp(move);324 up.operation(open, close, best, target);325 }326 //0的位置右移之后状态不在close和open中设定best为其父状态,并初始化f(n)估值函数

327 if(best.isMoveRight()){328 move = 3;329 EightPuzzle up =best.moveUp(move);330 up.operation(open, close, best, target);331 }332

333 }334 }else

335 System.out.println("没有解,请重新输入。");336 }337

338 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值