目标:{1,2,3}
{8,0,4}
{7,6,5}
当前:{1,0,3}
{7,2,4}
{6,8,5}
代码:
package com.test;
import java.util.*;
class Matrix implements Comparable<Matrix>{
public int[][] matrix = new int[3][3];
public int value = 0;
public Matrix(){}
public Matrix(int m[][], int v){
matrix = m;
value = v;
}
public int[][] getMatrix() {
return matrix;
}
public void setMatrix(int[][] matrix) {
this.matrix = matrix;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public int compareTo(Matrix m) {
if(this.value > m.value)
return 1;
else if(this.value < m.value)
return -1;
else
return 0;
}
}
//A算法实现八数码问题
class eightDigit{
private int targetMatrix[][]={{1,2,3},
{8,0,4},
{7,6,5}};
public eightDigit(){
}
//获得当前数字在目标数组中的位置
public int[] primitivePos(int nowPos){
int pos[] = new int[2];
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
if(nowPos == targetMatrix[i][j]){
pos[0] = i;
pos[1] = j;
}
}
}
return pos;
}
//根据0所在位置判断它可以移动的方向
public int direction(int zeroPos[]){
int dir = 0;
if(zeroPos[0] == 1 && zeroPos[1] == 1){
dir = 4;
}else if((zeroPos[0]+zeroPos[1])%2 != 0){
dir = 3;
}else{
dir =2;
}
return dir;
}
//获得路径
public void getWay(int oldMatrix[][]){
int oldDepth = 0;
List<int[][]> list = new ArrayList<int[][]>();
list.add(oldMatrix);
while(true){
List<Matrix> set = new ArrayList<Matrix>();
//获得当前0所在的位置,以便判断移动的方向
int[] zeroPos = new int[2];
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
if(0 == oldMatrix[i][j]){
zeroPos[0] = i;
zeroPos[1] = j;
}
}
}
int t = direction(zeroPos);
if(oldDepth != 0){
t = t-1;
}
//判断0可以移动的方向
oldDepth = oldDepth+1;
boolean t1=false,t2=false,t3=false,t4=false;
do{
int[][] newMatrix = new int[3][3];
for(int i =0; i<3; i++){
newMatrix[i][0] = oldMatrix[i][0];
newMatrix[i][1] = oldMatrix[i][1];
newMatrix[i][2] = oldMatrix[i][2];
}
int temp = newMatrix[zeroPos[0]][zeroPos[1]];
//向下移动
if(zeroPos[0]+1 <= 2 && t1==false){
newMatrix[zeroPos[0]][zeroPos[1]] = newMatrix[zeroPos[0]+1][zeroPos[1]];
newMatrix[zeroPos[0]+1][zeroPos[1]] = temp;
if(compare(newMatrix, list) == false){
int eF = evaluateFunc(newMatrix,oldDepth);
set.add(new Matrix(newMatrix,eF));
t--;
}
t1=true;
}
//向上移动
else if(zeroPos[0]-1 >= 0 && t2==false){
newMatrix[zeroPos[0]][zeroPos[1]] = newMatrix[zeroPos[0]-1][zeroPos[1]];
newMatrix[zeroPos[0]-1][zeroPos[1]] = temp;
if(compare(newMatrix, list) == false){
int eF = evaluateFunc(newMatrix,oldDepth);
set.add(new Matrix(newMatrix,eF));
t--;
}
t2=true;
}
//向左移动
else if(zeroPos[1]-1 >= 0 && t3==false){
newMatrix[zeroPos[0]][zeroPos[1]] = newMatrix[zeroPos[0]][zeroPos[1]-1];
newMatrix[zeroPos[0]][zeroPos[1]-1] = temp;
if(compare(newMatrix, list) == false){
int eF = evaluateFunc(newMatrix,oldDepth);
set.add(new Matrix(newMatrix,eF));
t--;
}
t3=true;
}
//向右移动
else if(zeroPos[1]+1 <=2 && t4== false){
newMatrix[zeroPos[0]][zeroPos[1]] = newMatrix[zeroPos[0]][zeroPos[1]+1];
newMatrix[zeroPos[0]][zeroPos[1]+1] = temp;
if(compare(newMatrix, list) == false){
int eF = evaluateFunc(newMatrix,oldDepth);
set.add(new Matrix(newMatrix,eF));
t--;
}
t4=true;
}
}while(t>0);
oldMatrix = getCheap(set).getMatrix();
list.add(oldMatrix);
//当前的八数码满足目标八数码时,退出循环
boolean flag=true;
for(int x=0;x<3;x++){
for(int y=0; y<3;y++){
if(oldMatrix[x][y] != targetMatrix[x][y])
flag=false;
}
}
if(flag==true)
break;
}
Iterator<int[][]> iter = list.iterator();
int step=1;
while(iter.hasNext()){
System.out.println("步骤:"+step++);
printPic(iter.next());
}
}
//判断两个二维数组是否相同
public boolean isSame(int[][] n, int[][] o){
for(int x=0;x<3;x++){
for(int y=0; y<3;y++){
if(o[x][y] != n[x][y])
return false;
}
}
return true;
}
//查看当前步骤是否是上一步所走过的
public boolean compare(int newMatrix[][], List<int[][]> list){
for(int i=0; i<list.size(); i++){
if(isSame(newMatrix, list.get(i))){
return true;
}
}
return false;
}
//从所以能移动的路径列表出找到评估值最小的那一个
public Matrix getCheap(List<Matrix> list){
Matrix target = new Matrix();
target.setValue(100);
Iterator<Matrix> iter = list.iterator();
while(iter.hasNext()){
Matrix temp = iter.next();
if(target.value > temp.value){
target = temp;
}
}
return target;
}
//评估函数
public int evaluateFunc(int matrix[][], int depth){
int step = 0;//错位数个数
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
//将当前位置的数字与原来矩阵中次位置的数字进行比较,不同则错位数加一
if(matrix[i][j] != targetMatrix[i][j] && matrix[i][j] != 0){
int pos[] = primitivePos(matrix[i][j]);
step += Math.abs(pos[0]-i)+Math.abs(pos[1]-j);
}
}
}
return depth+step;
}
//打印数组信息
public void printPic(int matrix[][]){
for(int i=0; i<3; i++){
System.out.println(" "+matrix[i][0]+" "+matrix[i][1]+" "+matrix[i][2]);
}
System.out.println("-----------");
}
}
public class Test {
public static void main(String[] args) {
int matrix[][] = {{1,0,3},
{7,2,4},
{6,8,5}};
eightDigit ed = new eightDigit();
ed.getWay(matrix);
}
}
最后得出了想要的结果,但是过程代码量多的令人发指,自己也没有对代码进行二次优化,直接把原始想法打出来了,关键就是评估函数的生成了,根据每一步的评估值来决定是否选择这一步。