简体   繁体   中英

I need help implementing A* algorithm on a JPanel in Java

I'm learning java and for the last couple of days i haven't been able to make any progress.I have searched all over Google and this site,but i can't seem to find exactly the solution i need.A similar problem or something. I'm trying to implement the A* algorithm on a simple JPanel which has a grid layout,with no success.Currently i have a run time error,the program compiles just fine.I know the solution might be something really simple,so please bear with me if i haven't figured that out.Sometimes we just need an extra set of eyes to see what we can't.Thank you so much for your your time and your help.

Anyway,here's what I've tried so far,there are only two classes and the Grid class has the UI features and a start button which is meant to instantiate the Maze class that runs the A* algorithm:

My Grid class,which has the main method

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Grid extends JPanel {

    private boolean start;
    private boolean end;
    public int x;
    public int y;
    public JPanel parent;
    private double localCost; // cost of getting from this square to goal i.e 'H'
    private double parentCost; // cost of getting from parent square to this node i.e 'G'
    private double passThroughCost;// cost of getting from the start to the goal i.e 'F'
// through this square
    private static final long serialVersionUID = 1L;
    private Set<JPanel> adjacencies = new HashSet<JPanel>();
    public JPanel mainPanel, southPanel;
    public final JFrame mainFrame = new JFrame();
    public static int a = 7;
    public static int b = 7;
    public JPanel[][] panelcontainer = new JPanel[a][b];
    private Maze maze;

    public Grid() {
        mainPanel = new JPanel();
        mainPanel.setLayout(new GridLayout(a, b));
        for (int i = 0; i < a; i++) {
            for (int j = 0; j < b; j++) {
                panelcontainer[i][j] = new JPanel();
                panelcontainer[i][j].setBorder(BorderFactory.createLineBorder(Color.black, 1));
                panelcontainer[i][j].setBackground(Color.blue);
                mainPanel.add(panelcontainer[i][j]);
                mainPanel.setBackground(Color.darkGray);
            }
        }
        //setting colors on the cells within the grid
        panelcontainer[3][1].setBackground(Color.GREEN);
        panelcontainer[2][3].setBackground(Color.darkGray);
        panelcontainer[3][3].setBackground(Color.darkGray);
        panelcontainer[4][3].setBackground(Color.darkGray);
        panelcontainer[1][5].setBackground(Color.darkGray);
        panelcontainer[2][5].setBackground(Color.darkGray);
        panelcontainer[0][0].setBackground(Color.darkGray);
        //  panelcontainer[0][0].setStart(true);
        panelcontainer[0][1].setBackground(Color.darkGray);
        panelcontainer[1][1].setBackground(Color.darkGray);
        panelcontainer[1][6].setBackground(Color.ORANGE);
        //populating each cell with the total movement costs
        JLabel label1 = new JLabel("84");
        label1.setForeground(Color.black);
        panelcontainer[0][2].add(label1);
        JLabel label2 = new JLabel("78");
        label2.setForeground(Color.black);
        panelcontainer[0][3].add(label2);
        JLabel label3 = new JLabel("78");
        label3.setForeground(Color.black);
        panelcontainer[0][4].add(label3);
        JLabel label4 = new JLabel("78");
        label4.setForeground(Color.black);
        panelcontainer[0][5].add(label4);
        JLabel label5 = new JLabel("78");
        label5.setForeground(Color.black);
        panelcontainer[0][6].add(label5);
        JLabel label6 = new JLabel("84");
        label6.setForeground(Color.black);
        panelcontainer[1][0].add(label6);
        JLabel label7 = new JLabel("64");
        label7.setForeground(Color.black);
        panelcontainer[1][2].add(label7);
        JLabel label8 = new JLabel("64");
        label8.setForeground(Color.black);
        panelcontainer[1][3].add(label8);
        JLabel label9 = new JLabel("64");
        label9.setForeground(Color.black);
        panelcontainer[1][4].add(label9);
        JLabel label10 = new JLabel("84");
        label10.setForeground(Color.black);
        panelcontainer[2][0].add(label10);
        JLabel label11 = new JLabel("70");
        label11.setForeground(Color.black);
        panelcontainer[2][1].add(label11);
        JLabel label12 = new JLabel("64");
        label12.setForeground(Color.black);
        panelcontainer[2][2].add(label12);
        JLabel label13 = new JLabel("84");
        label13.setForeground(Color.black);
        panelcontainer[2][4].add(label13);
        JLabel label14 = new JLabel("104");
        label14.setForeground(Color.black);
        panelcontainer[2][6].add(label14);
        JLabel label15 = new JLabel("90");
        label15.setForeground(Color.black);
        panelcontainer[3][0].add(label15);
        JLabel label16 = new JLabel("70");
        label16.setForeground(Color.black);
        panelcontainer[3][2].add(label16);
        JLabel label17 = new JLabel("104");
        label17.setForeground(Color.black);
        panelcontainer[3][4].add(label17);
        JLabel label18 = new JLabel("104");
        label18.setForeground(Color.black);
        panelcontainer[3][5].add(label18);
        JLabel label19 = new JLabel("104");
        label19.setForeground(Color.black);
        panelcontainer[3][6].add(label19);
        JLabel label20 = new JLabel("104");
        label20.setForeground(Color.black);
        panelcontainer[4][0].add(label20);
        JLabel label21 = new JLabel("90");
        label21.setForeground(Color.black);
        panelcontainer[4][1].add(label21);
        JLabel label22 = new JLabel("84");
        label22.setForeground(Color.black);
        panelcontainer[4][2].add(label22);
        JLabel label23 = new JLabel("124");
        label23.setForeground(Color.black);
        panelcontainer[4][4].add(label23);
        JLabel label24 = new JLabel("118");
        label24.setForeground(Color.black);
        panelcontainer[4][5].add(label24);
        JLabel label25 = new JLabel("118");
        label25.setForeground(Color.black);
        panelcontainer[4][6].add(label25);
        JLabel label26 = new JLabel("104");
        label26.setForeground(Color.black);
        panelcontainer[5][0].add(label26);
        JLabel label27 = new JLabel("110");
        label27.setForeground(Color.black);
        panelcontainer[5][1].add(label27);
        JLabel label28 = new JLabel("104");
        label28.setForeground(Color.black);
        panelcontainer[5][2].add(label28);
        JLabel label29 = new JLabel("98");
        label29.setForeground(Color.black);
        panelcontainer[5][3].add(label29);
        JLabel label30 = new JLabel("98");
        label30.setForeground(Color.black);
        panelcontainer[5][4].add(label30);
        JLabel label31 = new JLabel("98");
        label31.setForeground(Color.black);
        panelcontainer[5][5].add(label31);
        JLabel label32 = new JLabel("98");
        label32.setForeground(Color.black);
        panelcontainer[5][6].add(label32);
        JLabel label33 = new JLabel("144");
        label33.setForeground(Color.black);
        panelcontainer[6][0].add(label33);
        JLabel label34 = new JLabel("138");
        label34.setForeground(Color.black);
        panelcontainer[6][1].add(label34);
        JLabel label35 = new JLabel("124");
        label35.setForeground(Color.black);
        panelcontainer[6][2].add(label35);
        JLabel label36 = new JLabel("118");
        label36.setForeground(Color.black);
        panelcontainer[6][3].add(label36);
        JLabel label37 = new JLabel("112");
        label37.setForeground(Color.black);
        panelcontainer[6][4].add(label37);
        JLabel label38 = new JLabel("112");
        label38.setForeground(Color.black);
        panelcontainer[6][5].add(label38);
        JLabel label39 = new JLabel("112");
        label39.setForeground(Color.black);
        panelcontainer[6][6].add(label39);
        //new panel at the south border to hold start button
        southPanel = new JPanel();
        // --- Create a button. Add a listener to it.
        JButton startButton = new JButton("start");
        southPanel.add(startButton);
        southPanel.setBackground(Color.red);
        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Maze maze = new Maze(7, 7);
                maze.findBestPath();

            }
        });
        //JFrame specifications
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.add(mainPanel, BorderLayout.CENTER);
        mainFrame.add(southPanel, BorderLayout.PAGE_END);
        mainFrame.pack();
        mainFrame.setVisible(true);
        mainFrame.setSize(464, 485);
        mainFrame.setTitle("Astar Simulation");
        mainFrame.setLocationRelativeTo(null);
    }

    public boolean isStart() {
        return start;
    }

    public void setStart(boolean start) {
        this.start = start;
    }

    public boolean isEnd() {
        return end;
    }

    public void setEnd(boolean end) {
        this.end = end;
    }

    public Set<JPanel> getAdjacencies() {
        return adjacencies;
    }

    public void setAdjacencies(Set<JPanel> adjacencies) {
        this.adjacencies = adjacencies;
    }

    public JPanel getParent() {
        return parent;
    }

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

    public void calculateAdjacencies() {
        int top = x - 1;
        int bottom = x + 1;
        int left = y - 1;
        int right = y + 1;
        if (bottom < maze.getRows()) {
            if (isAdjacent()) {
                ((Grid) maze.getPanel(bottom, y)).addAdjacency(this);
                this.addAdjacency(maze.getPanel(bottom, y));
            }
        }
        if (right < maze.getColumns()) {
            if (isAdjacent()) {
                ((Grid) maze.getPanel(x, right)).addAdjacency(this);
                this.addAdjacency(maze.getPanel(x, right));
            }
        }
    }

    public void addAdjacency(JPanel panel) {
        adjacencies.add(panel);
    }

    public void removeAdjacency(JPanel panel) {
        adjacencies.remove(panel);
    }

    private boolean isAdjacent() {
        if (Math.random() > 5) {
            return true;
        }
        return false;
    }

    public double getPassThrough(JPanel goal) {
        if (isStart()) {
            return 0.0;
        }
        return getLocalCost(goal) + getParentCost();
    }

    public double getLocalCost(JPanel goal) {
        if (isStart()) {
            return 0.0;
        }
        localCost = 10.0 * (Math.abs(x - goal.getX()) + Math.abs(y - goal.getY()));
        return localCost;
    }

    public double getParentCost() {
        if (isStart()) {
            return 0.0;
        }
        if (parentCost == 0.0) {
            parentCost = 10.0 + 5 * (((Grid) parent).getParentCost() - 10.0);
        }
        return parentCost;
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Grid();
            }
        });
    }
}

The other class called Maze which has the algorithm:

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import javax.swing.JPanel;

public class Maze extends Grid {

    public int rows;
    public int columns;
    public JPanel goal;
    public Grid grid;
    public JPanel[][] panelcontainer;
    private List<JPanel> opened = new ArrayList<JPanel>();
    private List<JPanel> closed = new ArrayList<JPanel>();
    private List<JPanel> bestList = new ArrayList<JPanel>();

    public Maze(int rows, int columns) {
        new Grid();
        this.rows = rows;
        this.columns = columns;
        panelcontainer = new JPanel[rows][columns];
        generate();
    }

    private void generate() {
        createSquares();
        setStartAndGoal();
        generateAdjacenies();
    }

    public int getRows() {
        return rows;
    }

    public int getColumns() {
        return columns;
    }

    private void createSquares() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                panelcontainer[i][j] = new JPanel();
            }
        }
    }

    private void setStartAndGoal() {
        ((Grid) panelcontainer[1][1]).setStart(true);
        Random random = new Random();
        int goalX = 0, goalY = 0;
        while (goalX == 0 && goalY == 0) {
            goalX = random.nextInt(rows);
            goalY = random.nextInt(columns);
        }
        goal = panelcontainer[goalX][goalY];
        ((Grid) goal).setEnd(true);
    }

    private void generateAdjacenies() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                ((Grid) panelcontainer[i][j]).calculateAdjacencies();
            }
        }
    }

    public JPanel getPanel(int x, int y) {
        return panelcontainer[x][y];
    }

    public void setPanel(JPanel panel) {
        panelcontainer[panel.getX()][panel.getY()] = panel;
    }

    public void drawPath() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                JPanel panel = panelcontainer[i][j];
                if ((j - 1 < 0) && (i - 1 < 0)) {
                    if (bestList.contains(panel)) {
                        panelcontainer[i][j].setBackground(Color.CYAN);
                        return;
                    }
                }
            }
        }
    }

    public void findBestPath() {
        System.out.println("Calculating best path...");
        Set<JPanel> adjacencies = ((Grid) panelcontainer[0][0]).getAdjacencies();
        for (JPanel adjacency : adjacencies) {
            ((Grid) adjacency).setParent(panelcontainer[0][0]);
            if (((Grid) adjacency).isStart() == false) {
                opened.add(adjacency);
            }
        }
        while (opened.size() > 0) {
            JPanel best = findBestPassThrough();
            opened.remove(best);
            closed.add(best);
            if (((Grid) best).isEnd()) {
                //System.out.println("Found Goal");
                populateBestList(goal);
                drawPath();
                return;
            } else {
                Set<JPanel> neighbors = ((Grid) best).getAdjacencies();
                for (JPanel neighbor : neighbors) {
                    if (opened.contains(neighbor)) {
                        neighbor = panelcontainer[getX()][getY()];
                        JPanel tmpPanel = new JPanel();
                        tmpPanel = neighbor;
                        ((Grid) tmpPanel).setParent(best);
                        if (((Grid) tmpPanel).getPassThrough(goal) >= ((Grid) neighbor)
                                .getPassThrough(goal)) {
                            continue;
                        }
                    }
                    if (closed.contains(neighbor)) {
                        neighbor = panelcontainer[getX()][getY()];
                        JPanel tmpPanel = new JPanel();
                        tmpPanel = neighbor;
                        /*  JPanel tmpPanel = new JPanel(neighbor.getX(),
                         neighbor.getY(), this);*/
                        ((Grid) tmpPanel).setParent(best);
                        if (((Grid) tmpPanel).getPassThrough(goal) >= ((Grid) neighbor)
                                .getPassThrough(goal)) {
                            continue;
                        }
                    }
                    ((Grid) neighbor).setParent(best);
                    opened.remove(neighbor);
                    closed.remove(neighbor);
                    opened.add(0, neighbor);
                }
            }
        }//  System.out.println("No Path to goal");
    }

    private void populateBestList(JPanel panel) {
        bestList.add(panel);
        if (((Grid) panel.getParent()).isStart() == false) {
            populateBestList((JPanel) panel.getParent());
        }
        return;
    }

    private JPanel findBestPassThrough() {
        JPanel best = null;
        for (JPanel panel : opened) {
            if (best == null
                    || ((Grid) panel).getPassThrough(goal) < ((Grid) best).getPassThrough(goal)) {
                best = panel;
            }
        }
        return best;
    }
}

And this is the error i get:

 Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.JPanel cannot be cast to Grid
at Maze.setStartAndGoal(Maze.java:58)
at Maze.generate(Maze.java:32)
at Maze.<init>(Maze.java:27)
at Grid$1.actionPerformed(Grid.java:238)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6505)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6270)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4861)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:694)
at java.awt.EventQueue$3.run(EventQueue.java:692)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:708)
at java.awt.EventQueue$4.run(EventQueue.java:706)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

Basically, you have public JPanel [][] panelcontainer; , which is fine, but then you fill it with JPanel s

private void createSquares() {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            panelcontainer[i][j] = new JPanel();
        }
    }
}

And then you try and cast it to a Grid ...

((Grid) panelcontainer [1][1]).setStart(true);

But panelcontainer doesn't contain Grid s, it contains JPanel s.

It would be like filling a bus with African Elephants and expecting them to magically change to Indian Elephants when they arrive at their destination...Yes, they are Elephants, but they are not the same TYPE of Elephant...

I suspect that if you changed the createSquares method to generate instances of Grid instead of JPanel , you should be able to move forward a little more...

private void createSquares() {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            panelcontainer[i][j] = new Grid();
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM