A*算法解决迷宫问题

迷宫问题:
一张地图上有若干障碍物,表示不能通过。给定起点和终点,要求找到一条从起点到终点的路径。

抽象:
把地图抽象为n*m的布尔矩阵。true表示可以通过,false表示不能通过。

算法思路:

  1. 维护两个列表,open和close。
  2. 从起点开始,先将起点加入open列表。算出其上下左右的位置离终点的距离,并让这些点都指向起点,放入open列表里。将起点放入close列表。
  3. 选择open列表中距离最短的点,对于其上下左右的位置,如果其既不在open列表中又不在close列表中,则计算其距离,并让这些点都指向选中的点,放入open列表中。刚才选中的点放入close列表中。
  4. 重复步骤3,直到终点被放入close列表中。
  5. 从终点开始,查找其指向的点,这样一路追溯到起点,则为一条可行路径。

距离的计算:公式 F = G + H

  1. F代表预测的通过这个点的路径总长度
  2. G代表从起点到这个点已经走过的长度。用该点指向的点的G加上1
  3. H为预测的从该点到终点所需距离。其中一种方法:用两个点之间纵坐标差值的绝对值和横坐标差值的绝对值相加而得(曼哈顿方法)
package a_star;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;


public class SimplePuzzle {

    class Position {
        int x;
        int y;
        Position lastPosition;
        int pastDistance = 0;
        int predictDistance;

        Position(int x, int y, Position lastPosition) {
            this.x = x;
            this.y = y;
            this.lastPosition = lastPosition;
            if(lastPosition != null)
                pastDistance = lastPosition.pastDistance + 1;
            predictDistance = Math.abs(endx - x) + Math.abs(endy - y);
        }
        int distance(){
            return pastDistance + predictDistance;
        }
    }

    boolean[][] map;
    boolean[][] used;
    int startx, starty;
    int endx, endy;

    List<Position> open;
    Position openGhost;
    boolean endReached = false;

    public static void main(String[] args) throws IOException {
        new SimplePuzzle().find("/Users/yanning/Development/JAVA_SE_WORKSPACE/Algorithm/map.txt");
    }

    public void find(String file) throws IOException {
        initiate(file);
        Position start = new Position(startx, starty, null);
        Position end = null;
        open.add(start);

        while(true) {
            Position chosed = open.remove(0);
            if(chosed.lastPosition!=null)
                System.out.println("choosed: ["+chosed.lastPosition.x+","+chosed.lastPosition.y+"]<-(" + chosed.x+","+chosed.y+")");
            if(chosed.x == endx && chosed.y == endy) {
                end = chosed;
                break;
            }

            if(valid(chosed.x-1, chosed.y)) {
                addToOpenList(new Position(chosed.x-1, chosed.y, chosed));
            }

            if(valid(chosed.x+1, chosed.y)) {
                addToOpenList(new Position(chosed.x+1, chosed.y, chosed));
            }
            if(valid(chosed.x, chosed.y-1)) {
                addToOpenList(new Position(chosed.x, chosed.y-1, chosed));
            }
            if(valid(chosed.x, chosed.y+1)) {
                addToOpenList(new Position(chosed.x, chosed.y+1, chosed));
            }
            Iterator<Position> itr = open.iterator();
            System.out.print("openList: ");
            while(itr.hasNext()) {
                Position tmp = itr.next();
                System.out.print("("+tmp.x+", "+tmp.y+")*"+tmp.distance()+" -> ");
            }
            System.out.println("\n------------------");
        }

        Position tmp = end;
        System.out.println("path: ");
        while(tmp != null) {
            System.out.print("("+tmp.x+", "+tmp.y+") <- ");
            tmp = tmp.lastPosition;
        }
    }

    void initiate(String file) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(file));
        String[] tmp;

        int n = Integer.parseInt(br.readLine());
        int m = Integer.parseInt(br.readLine());
        map = new boolean[n][m];
        used = new boolean[n][m];

        for(int i = 0; i < n; i++) {
            tmp = br.readLine().split(",");
            if(tmp.length != m){
                System.err.println("Bad input file");
                System.exit(-1);
            }
            for(int j = 0; j < m; j++) {
                map[i][j] = (tmp[j].equals("0")) ? false : true;
                used[i][j] = false;
            }
        }       

        tmp = br.readLine().split(",");
        startx = Integer.parseInt(tmp[0]);
        starty = Integer.parseInt(tmp[1]);
        tmp = br.readLine().split(",");
        endx = Integer.parseInt(tmp[0]);
        endy = Integer.parseInt(tmp[1]);

        open = new LinkedList<Position>();

    }

    void addToOpenList(Position p) {
        used[p.x][p.y] = true;

        Iterator<Position> itr = open.iterator();
        int index = -1;
        while(itr.hasNext()) {
            Position tmp = itr.next();
            index++;
            if(p.distance() <= tmp.distance()) {
                open.add(index, p);
                return;
            }
        }
        open.add(p);
    }

    boolean valid(int x, int y) {
        if(x < 0 || x >= map.length || y < 0 || y >= map[0].length)
            return false;
        if(map[x][y] || used[x][y])
            return false;
        return true;
    }
}

输入:map.txt

5
5
0,0,0,0,0
0,0,1,0,0
0,0,1,0,0
0,0,1,0,0
0,0,0,0,0
2,0
1,4

输出:

openList: (2, 1)*5 -> (1, 0)*5 -> (3, 0)*7 -> ------------------
choosed: [2,0]<-(2,1)
openList: (1, 1)*5 -> (1, 0)*5 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [2,1]<-(1,1)
openList: (1, 0)*5 -> (0, 1)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [2,0]<-(1,0)
openList: (0, 0)*7 -> (0, 1)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [1,0]<-(0,0)
openList: (0, 1)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [1,1]<-(0,1)
openList: (0, 2)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [0,1]<-(0,2)
openList: (0, 3)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [0,2]<-(0,3)
openList: (0, 4)*7 -> (1, 3)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [0,3]<-(0,4)
openList: (1, 4)*7 -> (1, 3)*7 -> (3, 1)*7 -> (3, 0)*7 -> ------------------
choosed: [0,4]<-(1,4)
path: 
(1, 4) <- (0, 4) <- (0, 3) <- (0, 2) <- (0, 1) <- (1, 1) <- (2, 1) <- (2, 0) <- 
    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/little_mind/article/details/45920961
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞