A*算法

package Astar;

import java.util.*;

public class Astar {
    private int N=3;
    Scanner input=new Scanner(System.in);
    int Map[][]=new int[N][N];
    int target[][]=new int[N][N];
    List<Node> openList=new ArrayList<>();    //A*算法open列表
    List<Node> closeList=new ArrayList<>();   //A*算法closed列表

    HashMap<Integer,int []> targetmap=new HashMap<>();  //估价函数二所用的映射功能
    List<Node> nodeList=new ArrayList<>();  //节点列表用于存储所有扩展节点

    Node Start;
    Node Target;
    Comparator<Node> comparator=new Comparator<Node>() {    //比较函数,根据f(n)的值可以将openlist或closedlist从小到大排列
        @Override
        public int compare(Node o1, Node o2) {
            if(o1.getF()>o2.getF())
                return 1;
            else if(o1.getF()==o2.getF())
                return 0;
            else
                return -1;
        }
    };

    public Astar(){
        if(init()) {
            A_algorithm();
        }else{
            System.out.println("无解");
        }
    }
    boolean init(){         //初始化函数,用于输入初始八数码和目标八数码
        System.out.println("请输入八数码的初始状态:");
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++){
                Map[i][j]=input.nextInt();
            }
        }
        Start=new Node();
        Start.setState(Map);
        System.out.println("请输入八数码的目标状态:");
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++){
                target[i][j]=input.nextInt();
                int index[]={i,j};
                targetmap.put(target[i][j],index);
            }
        }
        Target=new Node();
        Target.setState(target);
        if(isSolve(Target)){
            return true;
        }else{
            return false;
        }
    }
    public boolean isSolve(Node target){     //判断是否有解
        int startNum[]=new int[N*N];
        int endNum[] = new int[N*N];
        int st = 0;
        int et = 0;
        for (int i = N * N - 2; i >= 0; i--) {
            for (int j = i - 1; j >= 0; j--) {
                if (startNum[i] > startNum[j])
                    st++;
                if (endNum[i] > endNum[j])
                    et++;
            }
        }
        if (st % 2 == et % 2)
            return true;
        return false;
    }

    int IndexInList(List<Node> list,Node node){    //判断某一状态是否在列表中
        for (int index = 0; index < list.size(); index++) {
            int i = 0,j=0;
            for (i = 0; i <N; i++) {
                for(j=0;j<N;j++) {
                    if ((list.get(index).getState()[i][j]) != node.getState()[i][j])
                        break;
                }
                if (j < N)
                    break;
            }
            if (i==N&&j==N) {
                return index;
            }
        }
        return -1;
    }

    public boolean isCanMove(int x,int y){    //是否可以移动0
        if(x<0||x>=3||y<0||y>=3){
            return false;
        }
        return true;
    }
    Node getNext(Node now,int direction){   //移动函数,用于获得下一状态
        int dx[]=new int[]{0,0,-1,1};
        int dy[]=new int[]{-1,1,0,0};
        Node next=new Node();
        int temp[][]=new int[N][N];
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++)
                temp[i][j]=now.getState()[i][j];
        }
        int zeroIndex[]=now.getZeroIndex();
        int x0=zeroIndex[0];
        int y0=zeroIndex[1];
        int nextZeroIndex=0;
        int nextx,nexty;
        nextx=x0+dx[direction];
        nexty=y0+dy[direction];
        if(isCanMove(nextx,nexty)){
            temp[x0][y0]=now.getState()[nextx][nexty];
            temp[nextx][nexty]=0;
            List<Node> path=new ArrayList<>();
            path.addAll(now.path);
            next.setState(temp);
            next.setPath(path);
            return next;
        }else{
            return null;
        }
    }

    void A_algorithm(){       //A*算法主体
        Start.path.add(Start);
        openList.add(Start);
        nodeList.add(Start);
        while(!openList.isEmpty()){
            openList.sort(comparator);
            Node best=openList.get(0);
            openList.remove(0);
            closeList.add(best);
            if(best.isTarget(Target)){        //判断是否为目标状态
                System.out.println("-------打印路径------");
                for(int i=0;i<best.path.size();i++){
                    System.out.println("第"+i+"次移动");
                    best.path.get(i).print();
                }
                System.out.println("共扩展了"+nodeList.size()+"个节点");
                return;
            }
            for(int i=0;i<4;i++){
                Node next=getNext(best,i);
                if(next!=null){       //是否可以移动到下一个状态
                    if(IndexInList(closeList,next)==-1){     //如果不在cloesd列表中
                        int index=IndexInList(openList,next);
                        if(index>=0){       //如果在open列表中
                            if(next.getG()<openList.get(index).getG()){    //比较和已在open列表中的深度比较
                                openList.remove(index);     //如果next更小,则将open中已存在的更换为next
                                next.setParent(best);
                                next.setUp2(Target,targetmap);   //设置估价函数,可以更改为其他估价函数
                                next.path.add(next);
                                openList.add(next);
                                nodeList.add(next);
                            }
                        }else{    //如果不在open列表中,则加入到open列表中
                            next.setParent(best);
                            next.setUp2(Target,targetmap);   //设置估价函数,可以更改为其他估价函数
                            next.path.add(next);
                            openList.add(next);
                            nodeList.add(next);
                        }
                    }
                }
            }
        }
    }
}

class Node {       //用于定义状态的类
    private int N=3;
    int state[][]=new int[3][3];
    private int f;    //估计函数
    private int g;    //当前深度
    private int h;     //目标的估计
    private Node parent;  //存储当前结点的上一个状态
    List<Node> path=new ArrayList<>();   //存储路径
    public Node(){

    }

    public void setUp(Node target) {   //估价函数一
        int num=0;
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++)
                if(state[i][j]!=target.getState()[i][j]){
                    num++;
                }
        }
        this.h = num;
        if(this.parent==null){
            this.g=0;
        }else{
            this.g=this.parent.getG()+1;
        }
        this.f=this.g+this.h;
    }
    public void setUp2(Node target,Map<Integer,int[]> map){   //估价函数二
        int num = 0;
        for (int row = 0; row < N; row++) {
            for (int cow = 0; cow < N; cow++) {
                if (cow != 0 && state[row][cow] != target.getState()[row][cow]){
                    num += Math.abs(row - map.get(state[row][cow])[0]) + Math.abs(cow - map.get(state[row][cow])[1]);
                }
            }
        }
        this.h = num;
        if(this.parent==null){
            this.g=0;
        }else{
            this.g=this.parent.getG()+1;
        }
        this.f=this.g+this.h;
    }

    public int[][] getState() {
        return state;
    }

    public void setState(int[][] state) {
        this.state = state;
    }

    public int getF() {
        return f;
    }

    public void setF(int f) {
        this.f = f;
    }

    public int getG() {
        return g;
    }

    public void setG(int g) {
        this.g = g;
    }

    public Node getParent() {
        return parent;
    }

    public void setParent(Node parent) {
        this.parent = parent;
    }

    public List<Node> getPath() {
        return path;
    }

    public void setPath(List<Node> path) {
        this.path = path;
    }

    public boolean isTarget(Node target){
        int i = 0,j=0;
        for (i = 0; i <N; i++) {
            for(j=0;j<N;j++) {
                if (state[i][j]!= target.getState()[i][j])
                    return false;
            }
        }
        return true;
    }

    public int[] getZeroIndex(){     //获得0的位置
        int x0 = 0, y0 = 0;
        for (x0 = 0; x0 < N; x0++) {
            boolean flag = false;
            for (y0 = 0; y0 < N; y0++) {
                if (state[x0][y0] == 0) {
                    flag = true;
                    break;
                }
            }
            if (flag)
                break;
        }
        return new int[]{x0, y0};
    }


    public void print(){    //打印函数
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                System.out.print(state[i][j]+" ");
            }
            System.out.println();
        }
    }
}

package Astar;

public class test {
        public static void main(String[] args) {
            Astar astar=new Astar();
        }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值