]> git.leonardobizzoni.com Git - astar-visualizer/commitdiff
Basic A*
authorLeonardoBizzoni <leo2002714@gmail.com>
Sat, 19 Jun 2021 11:01:26 +0000 (13:01 +0200)
committerLeonardoBizzoni <leo2002714@gmail.com>
Sat, 19 Jun 2021 11:01:26 +0000 (13:01 +0200)
16 files changed:
src/main/java/Main/AStar.java [new file with mode: 0644]
src/main/java/Main/ControlPanel.java
src/main/java/Main/Map.java
src/main/java/Main/Node.java
src/main/java/Main/PathfinderUtils.java
target/PathVisualizer-1.0-SNAPSHOT.jar
target/classes/Main/AStar.class [new file with mode: 0644]
target/classes/Main/ControlPanel$1.class [deleted file]
target/classes/Main/ControlPanel.class
target/classes/Main/Map.class
target/classes/Main/Node.class
target/classes/Main/PathfinderUtils.class
target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
target/surefire-reports/Main.AppTest.txt
target/surefire-reports/TEST-Main.AppTest.xml

diff --git a/src/main/java/Main/AStar.java b/src/main/java/Main/AStar.java
new file mode 100644 (file)
index 0000000..6a60a95
--- /dev/null
@@ -0,0 +1,92 @@
+package Main;
+
+public class AStar{
+    private Map map;
+
+    public AStar(Map map) {
+        this.map = map;
+    }
+
+    public void start() {
+        searchPath(PathfinderUtils.startNode);
+    }
+    
+    public void searchPath(Node parent) {
+        for (int i = 0; i < 4; i++) {
+            int x = (int) Math.round(parent.getX() + (-map.size* Math.cos((Math.PI / 2) * i)));
+            int y = (int) Math.round(parent.getY() + (-map.size* Math.sin((Math.PI / 2) * i)));
+
+            calculateOpenNode(x, y, parent);
+        }
+
+        parent = getNextBestNode();
+
+        PathfinderUtils.closedNodes.add(parent);
+        PathfinderUtils.openNodes.remove(parent);
+
+        if (parent.getX() == PathfinderUtils.endNode.getX() && parent.getY() == PathfinderUtils.endNode.getY()) {
+            ControlPanel.toggleRunBtn.setText("End");
+            map.isFinished = true;
+            map.repaint();
+            return;
+        }
+
+        if (!map.isFinished) {
+            searchPath(parent);
+        }
+        else
+            System.exit(0);
+    }
+
+    public void calculateOpenNode(int nextX, int nextY, Node parent) {
+        if (nextX >= Map.width || nextY >= Map.height || nextX < 0 || nextY < 0)
+            return;
+        if (PathfinderUtils.locateBarrier(nextX, nextY) != -1)
+            return;
+        if (nextX == PathfinderUtils.startNode.getX() && nextY == PathfinderUtils.startNode.getY())
+            return;
+
+        Node openNode = new Node(nextX, nextY);
+        openNode.setParentNode(parent);
+
+        // Tests if a copy of the node has already been added
+        for (Node node : PathfinderUtils.closedNodes) {
+            if(openNode.getX() == node.getX() && openNode.getY() == node.getY())
+                return;
+        }
+
+        // Tests if a copy of the node has already been added
+        for (Node node : PathfinderUtils.openNodes) {
+            if(openNode.getX() == node.getX() && openNode.getY() == node.getY())
+                return;
+        }
+
+        int gx = openNode.getX() - parent.getX();
+        int gy = openNode.getY() - parent.getY();
+        int g = parent.getG();
+
+        if (gx != 0 && gy != 0) {
+            g += (int) (Math.sqrt(2 * (Math.pow(map.size, 2))));
+        } else {
+            g += map.size;
+        }
+        openNode.setG(g);
+
+        // Calculating H Cost
+        int hx = Math.abs(PathfinderUtils.endNode.getX() - openNode.getX());
+        int hy = Math.abs(PathfinderUtils.endNode.getY() - openNode.getY());
+        int h = hx + hy;
+        openNode.setH(h);
+
+        // Calculating F Cost
+        int f = g + h;
+        openNode.setF(f);
+
+        PathfinderUtils.openNodes.add(openNode);
+    }
+
+    public Node getNextBestNode() {
+        PathfinderUtils.sort();
+        return PathfinderUtils.openNodes.get(0);
+    }
+}
index 6c578213a51eac5e0d49d6c3b1d5b6918e749896..e5186ef86257751d952894bd30138763edfa5c60 100644 (file)
@@ -2,22 +2,15 @@ package Main;
 
 import java.awt.Color;
 import java.awt.Insets;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 
 import javax.swing.JButton;
 import javax.swing.JComboBox;
-import javax.swing.JOptionPane;
 
 public class ControlPanel {
-    private Map map;
-
-    private JButton toggleRunBtn;
-    private JComboBox<String> algo;
+    static JButton toggleRunBtn;
+    static JComboBox<String> algo;
 
     public ControlPanel(Map map) {
-        this.map = map;
-
         algo = new JComboBox<>(new String[] { "Select an algorithm", "A*", "Dijkstra", "Breadth-first search"});
         algo.setVisible(true);
 
@@ -25,48 +18,7 @@ public class ControlPanel {
         toggleRunBtn.setVisible(true);
         toggleRunBtn.setMargin(new Insets(0, 0, 0, 0));
         toggleRunBtn.setBackground(Color.white);
-        toggleRunBtn.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-
-                if (toggleRunBtn.getText().equals("Run")) {
-                    switch (algo.getItemAt(algo.getSelectedIndex())) {
-
-                    case ("A*"):
-                        System.out.println("A* selected");
-                        // AStar.start();
-                        break;
-
-                    case ("Dijkstra"):
-                        System.out.println("Dijkstra selected");
-                        // AStar.start();
-                        break;
-
-                    case ("Greedy best-first search"):
-                        System.out.println("Greedy best-first search selected");
-                        // AStar.start();
-                        break;
-
-                    case ("Breadth-first search"):
-                        System.out.println("Breadth-first search selected");
-                        // AStar.start();
-                        break;
-
-                    default:
-                        JOptionPane.showMessageDialog(null,
-                                "You must select an algorithm before starting the pathfinder", "Algorithm not selected",
-                                JOptionPane.ERROR_MESSAGE);
-                        return;
-                    }
-
-                    toggleRunBtn.setText("Stop");
-                }
-
-                else {
-                    toggleRunBtn.setText("Run");
-                }
-            }
-        });
+        toggleRunBtn.addActionListener(map);
 
         map.add(algo);
         map.add(toggleRunBtn);
index 36f8ff2be9274356a02eafe4968a9f724b039028..167847aa12992b1663190f3ea0e6c3ff087b10e7 100644 (file)
@@ -9,25 +9,33 @@
  */
 package Main;
 
-import javax.swing.JFrame;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.SwingUtilities;
-
 import java.awt.Color;
 import java.awt.Graphics;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseMotionListener;
+import java.awt.Dimension;
 import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
 
-class Map extends JPanel implements MouseListener, MouseMotionListener, KeyListener {
+class Map extends JPanel implements ActionListener, MouseListener, MouseMotionListener, KeyListener {
     private JFrame window;
-    private int size = 30;
     private char key = (char) 0;
     private ControlPanel menu = new ControlPanel(this);
 
+    static int width;
+    static int height;
+    boolean isFinished = false;
+
+    int size = 30;
+
     public Map() {
         this.setBackground(new Color(40, 40, 40));
 
@@ -40,10 +48,14 @@ class Map extends JPanel implements MouseListener, MouseMotionListener, KeyListe
         window = new JFrame();
         window.setContentPane(this);
         window.setTitle("Pathfinding Algorithm Visualizer");
+        window.getContentPane().setPreferredSize(new Dimension(1920, 1080));
         window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         window.pack();
         window.setVisible(true);
 
+        width = this.getWidth();
+        height = this.getHeight();
+
         this.revalidate();
         this.repaint();
     }
@@ -78,6 +90,18 @@ class Map extends JPanel implements MouseListener, MouseMotionListener, KeyListe
         }
 
         menu.renderMenu();
+
+        // Draws open nodes
+        g.setColor(Color.white);
+        for (Node node : PathfinderUtils.openNodes) {
+            g.fillRect(node.getX() + 1, node.getY() + 1, size - 1, size - 1);
+        }
+
+        // Draws closed nodes
+        g.setColor(Color.orange);
+        for (Node node : PathfinderUtils.closedNodes) {
+            g.fillRect(node.getX() + 1, node.getY() + 1, size - 1, size - 1);
+        }
     }
 
     // Drawing on the grid
@@ -92,7 +116,8 @@ class Map extends JPanel implements MouseListener, MouseMotionListener, KeyListe
                 // Checks if start node and end node are the same
                 if (PathfinderUtils.endNode != null) {
                     if (PathfinderUtils.endNode.getX() == posX && PathfinderUtils.endNode.getY() == posY) {
-                        JOptionPane.showMessageDialog(null, "End node and start node can't be the same node", "Same node error", JOptionPane.ERROR_MESSAGE);
+                        JOptionPane.showMessageDialog(null, "End node and start node can't be the same node",
+                                "Same node error", JOptionPane.ERROR_MESSAGE);
                         return;
                     }
                 }
@@ -115,7 +140,8 @@ class Map extends JPanel implements MouseListener, MouseMotionListener, KeyListe
                 // Checks if end node and start node are the same
                 if (PathfinderUtils.startNode != null) {
                     if (PathfinderUtils.startNode.getX() == posX && PathfinderUtils.startNode.getY() == posY) {
-                        JOptionPane.showMessageDialog(null, "End node and start node can't be the same node!", "SAME NODE ERROR", JOptionPane.ERROR_MESSAGE);
+                        JOptionPane.showMessageDialog(null, "End node and start node can't be the same node!",
+                                "SAME NODE ERROR", JOptionPane.ERROR_MESSAGE);
                         return;
                     }
                 }
@@ -137,7 +163,6 @@ class Map extends JPanel implements MouseListener, MouseMotionListener, KeyListe
 
                 // TODO controlla se si sta creando una barriera su start o end
 
-
                 PathfinderUtils.barriers.add(barrierNode);
 
                 repaint();
@@ -164,7 +189,7 @@ class Map extends JPanel implements MouseListener, MouseMotionListener, KeyListe
             }
 
             else {
-                int nodeID = PathfinderUtils.locate(posX, posY);
+                int nodeID = PathfinderUtils.locateBarrier(posX, posY);
 
                 if (nodeID != -1) {
                     PathfinderUtils.remove(nodeID);
@@ -195,21 +220,65 @@ class Map extends JPanel implements MouseListener, MouseMotionListener, KeyListe
     }
 
     @Override
-    public void keyTyped(KeyEvent e) {}
+    public void actionPerformed(ActionEvent e) {
+        if (ControlPanel.toggleRunBtn.getText().equals("Run")) {
+            switch (ControlPanel.algo.getItemAt(ControlPanel.algo.getSelectedIndex())) {
+
+            case ("A*"):
+                System.out.println("A* selected");
+                new AStar(this).start();
+                break;
+
+            case ("Dijkstra"):
+                System.out.println("Dijkstra selected");
+                // AStar.start();
+                break;
+
+            case ("Greedy best-first search"):
+                System.out.println("Greedy best-first search selected");
+                // AStar.start();
+                break;
+
+            case ("Breadth-first search"):
+                System.out.println("Breadth-first search selected");
+                // AStar.start();
+                break;
+
+            default:
+                JOptionPane.showMessageDialog(null, "You must select an algorithm before starting the pathfinder",
+                        "Algorithm not selected", JOptionPane.ERROR_MESSAGE);
+                return;
+            }
+
+            ControlPanel.toggleRunBtn.setText("Stop");
+        }
+
+        else {
+            ControlPanel.toggleRunBtn.setText("Run");
+        }
+    }
 
     @Override
-    public void mouseClicked(MouseEvent e) {}
+    public void keyTyped(KeyEvent e) {
+    }
 
     @Override
-    public void mouseReleased(MouseEvent e) {}
+    public void mouseClicked(MouseEvent e) {
+    }
 
     @Override
-    public void mouseEntered(MouseEvent e) {}
+    public void mouseReleased(MouseEvent e) {
+    }
 
     @Override
-    public void mouseExited(MouseEvent e) {}
+    public void mouseEntered(MouseEvent e) {
+    }
 
     @Override
-    public void mouseMoved(MouseEvent e) {}
+    public void mouseExited(MouseEvent e) {
+    }
 
+    @Override
+    public void mouseMoved(MouseEvent e) {
+    }
 }
index 479a5fbdf1d673d1c8fa3729b918ad337d5aeb3a..1df44d5475e1dddc79ec6c2179f8654d0b456c8d 100644 (file)
@@ -1,7 +1,8 @@
 package Main;
 
 public class Node {
-    private int x, y;
+    private int x, y, f = 0, g = 0, h = 0;
+    private Node parentNode;
 
     public Node(int x, int y) {
         this.x = x;
@@ -23,4 +24,37 @@ public class Node {
     public void setX(int x) {
         this.x = x;
     }
+
+    public Node getParentNode() {
+        return parentNode;
+    }
+
+    public void setParentNode(Node parentNode) {
+        this.parentNode = parentNode;
+    }
+
+
+    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 int getH() {
+        return h;
+    }
+
+    public void setH(int h) {
+        this.h = h;
+    }
 }
index 560453857933ff3caf3f7e09854bfe34ceaa5ab3..528a005cff13e3d3532d0386e98eb8773cb8e0db 100644 (file)
@@ -5,18 +5,36 @@ import java.util.List;
 
 public class PathfinderUtils {
     static List<Node> barriers = new ArrayList<>();
+    static List<Node> openNodes = new ArrayList<>();
+    static List<Node> closedNodes = new ArrayList<>();
     static Node startNode, endNode;
 
-    static int locate(int x, int y) {
+    // Returns index of barrier if the coordinates are of a barrier node
+    static int locateBarrier(int x, int y) {
         for (int i = 0; i < barriers.size(); i++) {
-            if(barriers.get(i).getX() == x && barriers.get(i).getY() == y)
+            if (barriers.get(i).getX() == x && barriers.get(i).getY() == y)
                 return i;
         }
 
         return -1;
     }
 
+    // Removes barrier node
     static void remove(int id) {
         barriers.remove(id);
     }
+
+    static void sort() {
+        Node tmp;
+
+        for (int i = 0; i < openNodes.size(); i++) {
+            for (int j = 0; j < openNodes.size(); j++) {
+                if (openNodes.get(i).getF() < openNodes.get(j).getF()) {
+                    tmp = openNodes.get(j);
+                    openNodes.set(j, openNodes.get(i));
+                    openNodes.set(i, tmp);
+                }
+            }
+        }
+    }
 }
index f6745016c95ba1301b57088bc64760982bdb25f1..39668b14f55524d269800ce1d9d903ab3692a8ff 100644 (file)
Binary files a/target/PathVisualizer-1.0-SNAPSHOT.jar and b/target/PathVisualizer-1.0-SNAPSHOT.jar differ
diff --git a/target/classes/Main/AStar.class b/target/classes/Main/AStar.class
new file mode 100644 (file)
index 0000000..e722d34
Binary files /dev/null and b/target/classes/Main/AStar.class differ
diff --git a/target/classes/Main/ControlPanel$1.class b/target/classes/Main/ControlPanel$1.class
deleted file mode 100644 (file)
index fa3a702..0000000
Binary files a/target/classes/Main/ControlPanel$1.class and /dev/null differ
index 340d99e184cc669282b6ffa42af863d8e5b86be6..920e67e59aa47f53584766312ba2b8e1fef391d6 100644 (file)
Binary files a/target/classes/Main/ControlPanel.class and b/target/classes/Main/ControlPanel.class differ
index f08455046d96f4cffd047e12075a8a0ad5cc47d8..28b921daf45d913656448e9b0545604e806d7037 100644 (file)
Binary files a/target/classes/Main/Map.class and b/target/classes/Main/Map.class differ
index 8ff1fb222e009e5806cc7c7529a3a2e888feaac2..930f2951c3a36fe849966c6cd6a37e211530f7d2 100644 (file)
Binary files a/target/classes/Main/Node.class and b/target/classes/Main/Node.class differ
index 78aa867d1893dc7d532b3d361f62e6ce5190d8ca..c3ec61a485a76e38401acec470836359f9e571ee 100644 (file)
Binary files a/target/classes/Main/PathfinderUtils.class and b/target/classes/Main/PathfinderUtils.class differ
index 6b22cb60e04447a5f837f7d4382be4e7994f5f1b..b1dccf06b9b3d1b6c61bfc2ec791098bffc88fc3 100644 (file)
@@ -1,5 +1,5 @@
-Main/ControlPanel$1.class
 Main/Node.class
+Main/AStar.class
 Main/ControlPanel.class
 Main/Map.class
 Main/App.class
index b97cf8ab4f3f2add7be70a8e610725e483ed539d..cdd74a9efead34156a15a8d5baa5f65cc30a91d3 100644 (file)
@@ -1,5 +1,6 @@
 /home/leo/Docs/Proj/PathVisualizer/src/main/java/Main/ControlPanel.java
 /home/leo/Docs/Proj/PathVisualizer/src/main/java/Main/Map.java
 /home/leo/Docs/Proj/PathVisualizer/src/main/java/Main/Node.java
+/home/leo/Docs/Proj/PathVisualizer/src/main/java/Main/AStar.java
 /home/leo/Docs/Proj/PathVisualizer/src/main/java/Main/App.java
 /home/leo/Docs/Proj/PathVisualizer/src/main/java/Main/PathfinderUtils.java
index b957bda8238ef9b90bcd0a3991fdea68dda3099d..bdab1da3b2f7dfb74b92b57e5049b807f43802b3 100644 (file)
@@ -1,4 +1,4 @@
 -------------------------------------------------------------------------------
 Test set: Main.AppTest
 -------------------------------------------------------------------------------
-Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.026 s - in Main.AppTest
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.02 s - in Main.AppTest
index 9f3f13dafd1e42b725da51f55ed88dec4505bf8d..396d6b02f0ad224eb6e38248afdd78f8db9584f4 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd" name="Main.AppTest" time="0.026" tests="1" errors="0" skipped="0" failures="0">
+<testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd" name="Main.AppTest" time="0.02" tests="1" errors="0" skipped="0" failures="0">
   <properties>
     <property name="awt.toolkit" value="sun.awt.X11.XToolkit"/>
     <property name="java.specification.version" value="11"/>
@@ -16,7 +16,7 @@
     <property name="sun.java.launcher" value="SUN_STANDARD"/>
     <property name="user.country" value="GB"/>
     <property name="sun.boot.library.path" value="/opt/openjdk-bin-11.0.11_p9/lib"/>
-    <property name="sun.java.command" value="/home/leo/Docs/Proj/PathVisualizer/target/surefire/surefirebooter6228058189104108718.jar /home/leo/Docs/Proj/PathVisualizer/target/surefire 2021-06-18T12-26-30_233-jvmRun1 surefire16797671742172820636tmp surefire_018142986162871324276tmp"/>
+    <property name="sun.java.command" value="/home/leo/Docs/Proj/PathVisualizer/target/surefire/surefirebooter12422851706423362175.jar /home/leo/Docs/Proj/PathVisualizer/target/surefire 2021-06-19T13-00-08_471-jvmRun1 surefire10461286948834527749tmp surefire_05278180969358337674tmp"/>
     <property name="jdk.debug" value="release"/>
     <property name="surefire.test.class.path" value="/home/leo/Docs/Proj/PathVisualizer/target/test-classes:/home/leo/Docs/Proj/PathVisualizer/target/classes:/home/leo/.m2/repository/junit/junit/4.11/junit-4.11.jar:/home/leo/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:"/>
     <property name="sun.cpu.endian" value="little"/>
@@ -32,7 +32,7 @@
     <property name="java.specification.name" value="Java Platform API Specification"/>
     <property name="java.vm.specification.vendor" value="Oracle Corporation"/>
     <property name="java.awt.graphicsenv" value="sun.awt.X11GraphicsEnvironment"/>
-    <property name="surefire.real.class.path" value="/home/leo/Docs/Proj/PathVisualizer/target/surefire/surefirebooter6228058189104108718.jar"/>
+    <property name="surefire.real.class.path" value="/home/leo/Docs/Proj/PathVisualizer/target/surefire/surefirebooter12422851706423362175.jar"/>
     <property name="sun.management.compiler" value="HotSpot 64-Bit Tiered Compilers"/>
     <property name="java.runtime.version" value="11.0.11+9"/>
     <property name="user.name" value="leo"/>