A*尋路算法 學習

public class AStarFrame_V2 extends JFrame {
    RectCell[][] cells;
    int[][] values;
    private JPanel contentPane ;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    AStarFrame_V2 frame = new AStarFrame_V2();
                    frame.setVisible(true);
                    new Thread(new MyRunnable(frame)).start();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    static class MyRunnable implements Runnable {
        AStarFrame_V2 frame;
        MyRunnable(AStarFrame_V2 frame) {
            this.frame = frame;
        }
        @Override
        public void run() {
            frame.start();
        }

    }
     class MyPanel extends JPanel {
        public void paint(Graphics g) {
            super.paint(g);
            Graphics2D g2d = (Graphics2D)g;
            for (RectCell[] row : cells) {
                for (RectCell column : row) {
                    Color color = Color.black;
                    if (column.isFill()) {
                        g2d.setColor(color);
                        g2d.fill(column.getRect());
                    }
                    else if(column.isJump()){
                        color = Color.green;
                        g2d.setColor(color);
                        g2d.fill(column.getRect());
                    }else if(column.type == 3) {
                        color = Color.pink;
                        g2d.setColor(color);
                        g2d.fill(column.getRect());
                    }
                    else if(column.type == 4) {
                        color = Color.red;
                        g2d.setColor(color);
                        g2d.fill(column.getRect());
                    }
                    else { 
                        g2d.setColor(color);
                        g2d.draw(column.getRect()); 
                    }
                }
            }
            g2d.setColor(Color.BLUE);
            g2d.fill(A.getRect());
            g2d.setColor(Color.red);
            g2d.fill(B.getRect());
    }
    public void paint(Graphics2D  g2d,Shape s) {
        g2d.drawRect(10, 10, 10, 10);
    }
    }
    /**
     * Create the frame.
     */
    public AStarFrame_V2() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 1024, 1024);
        contentPane = new MyPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        getContentPane().setLayout(null);
        contentPane.setLayout(null);
        init();
    }
    public static final int BASIC = 6;
    public static final int BASIC_X = BASIC;
    public static final int BASIC_Y = BASIC;
    public static final RectCell A = new RectCell(new Rectangle((1)*BASIC, (1)*BASIC, BASIC, BASIC), (byte)0, 0, 0);
//  public static final RectCell B = new RectCell(new Rectangle((18)*BASIC, (30)*BASIC, BASIC, BASIC), (byte)0, 29,17);
    public static final RectCell B = new RectCell(new Rectangle((65)*BASIC, (101)*BASIC, BASIC, BASIC), (byte)0, 100,64);
    public static final Node NB = new Node(null, B);
    private void init() {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("./res/worldnpc/sc/chengshi.txt")));
            String[] statistics = br.readLine().split("\\|");
            int max_rows = Integer.parseInt(statistics[4]);
            int max_columns = Integer.parseInt(statistics[5]);
            cells = new RectCell[max_rows][max_columns];
            values= new int[max_rows][max_columns];
            String line = null;
            int y=0;
            while((line = br.readLine()) != null) {
                String[] datas = line.split("\\|");
                for (int x=0;x<datas.length;x++) {
                    cells[y][x] = new RectCell(new Rectangle((x+1)*BASIC, (y+1)*BASIC, BASIC, BASIC), Byte.parseByte(datas[x]), y, x);
                    values[y][x] = Integer.MAX_VALUE;
                }
                y++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    void start() {
        long currtime = System.currentTimeMillis();
        Node nodeA = new Node(null, A);
        Map<RectCell,Node> closed = new HashMap<>();
        Map<RectCell,Node> opened = new HashMap<>();
        Node node = go(nodeA, closed, opened);
        Node parent = node;
        do {
            parent.cell.type = 4;
            parent = parent.parent;
        }while(parent != null);
        repaint();
        JOptionPane.showMessageDialog(this, "耗時毫秒數:" +( System.currentTimeMillis() - currtime)+",G:"+node.G+",H:"+node.H+","+node.F);
    }



    Node next;

    Node go(Node from,Map<RectCell,Node> closed,Map<RectCell,Node> opened) {
        closed.put(from.cell, from);
        opened.remove(from.cell);
        if (from.cell.x == B.x && from.cell.y == B.y) return from;

        next = putOpened(closed,opened,from,1,0);
        Node to = putOpened(closed,opened,from,0,1);
        if (next == null || (to != null && to.F < next.F)) next = to;
        to = putOpened(closed,opened,from,-1,0);
        if (next == null || (to != null && to.F < next.F)) next = to;
        to = putOpened(closed,opened,from,0,-1);
        if (next == null || (to != null && to.F < next.F)) next = to;
        to = putOpened(closed,opened,from,1,1);
        if (next == null || (to != null && to.F < next.F)) next = to;
        to = putOpened(closed,opened,from,1,-1);
        if (next == null || (to != null && to.F < next.F)) next = to;
        to = putOpened(closed,opened,from,-1,1);
        if (next == null || (to != null && to.F < next.F)) next = to;
        to = putOpened(closed,opened,from,-1,-1);
        if (next == null || (to != null && to.F < next.F)) next = to;
        next = getMinOpendNode(next,opened);
        next.cell.type = 3;
        System.err.println("next go:"+next.toString());
//      repaint();
//      try {
//          Thread.sleep(100);
//      } catch (InterruptedException e) {
//          e.printStackTrace();
//      }
        return go(next, closed, opened);

    }

    private Node getMinOpendNode(Node next,Map<RectCell, Node> opened) {
        for (Node node : opened.values()) {
            if (next == null || node.F < next.F) next = node;
        }
        return next;
    }
    private Node putOpened(Map<RectCell,Node> closed,Map<RectCell, Node> opened, Node from,int r_upd,int c_upd) {
        //
        int x = from.cell.x + c_upd;
        int y = from.cell.y + r_upd;
        if (y<0 || x<0 || y>=cells.length || x>= cells[0].length) {
            return null;
        }
        RectCell cell = cells[y][x];
        if (cell.isFill() || closed.containsKey(cell)) return null;
        Node to = new Node(from, cell);

        int h = from.calculateG(to);
        int d = values[to.cell.y][to.cell.x];
        if (h >= d) return null;
        values[to.cell.y][to.cell.x] = h;
        to.calculateF(NB);      
        opened.put(cell, to);
        return to;

    }
    static class Node {
        Node parent;
        int G;//從起點,沿着產生的路徑
        int H;//從網格上那個方向移動到終點的估計移動消費,曼哈頓方法:從當前格到目的格之間水平和垂直的方格的數量總和,忽略對角線方向。然後把結果乘以10。|x1-x2|+|y1-y2|(忽略障礙物)
        int F;//G+H
        RectCell cell;
        public Node(Node parent,RectCell cell) {
            this.parent = parent;
            this.cell = cell;
        }
        public void calc(int g, int h) {
            this.G = g;
            this.H = h;
            this.F = g+h;       
        }
        public String toString() {
            return "Node{"+cell.toString() + "  GHF["+G+","+H+","+F+"]}";
        }

        /*
         * 計算當前節點的F值
         */
        public void calculateF(Node target) {
            if (parent != null)
                this.G = parent.G + predict(parent);
            this.F = this.G + this.predict(target);
        }

        /*
         * 計算當前節點的G值
         */
        public int calculateG(Node target) {
            return this.G + predict(target);
        }

        /*
         * 計算當前節點到目標節點的啓發因子代價(H)
         */
        private int predict(Node target) {
            int dx = Math.abs(this.cell.x - target.cell.x);
            int dy = Math.abs(this.cell.y - target.cell.y);
            int a = Math.abs(dx - dy);
            int b = Math.min(dx, dy);
            return a * a + b * b;
        }
    }


}
public class RectCell {
    Rectangle rect;
    byte type;//0:空,1:阻擋,2:可跳躍
    int y;
    int x;
    public RectCell(Rectangle rectangle,byte type,int y,int x) {
        this.rect = rectangle;
        this.type = type;
        this.y = y;
        this.x = x;
    }

    public boolean isFill() {
        return type == 1;
    }

    public boolean isJump() {
        return type == 2;
    }

    public boolean isNull() {
        return type == 0;
    }
    public Rectangle getRect() {
        return rect;
    }
    public byte getType() {
        return type;
    }

    @Override
        public String toString() {
            return "Cell["+type+",("+x+","+y+")("+rect.width+","+rect.height+")]";
        }

}

Node int predict(Node target) 影響整個尋路效果

發佈了30 篇原創文章 · 獲贊 4 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章