From 7990f5d06d9da5c421010e96632e4420e483e35a Mon Sep 17 00:00:00 2001
From: NET-D3v3l0p3r <3r0rxx@gmail.com>
Date: Fri, 23 Apr 2021 18:11:44 +0200
Subject: [PATCH] =?UTF-8?q?2=20Ans=C3=A4tze=20->=20simples=20flood=20fill?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 examples/debug.png                            | Bin 0 -> 884 bytes
 src/Program.java                              |   6 +-
 src/{ => approach1}/algorithm/Explorer.java   |  10 +-
 .../algorithm/ParallelPathfinder.java         |   5 +-
 .../algorithm/WorkingExplorers.java           |   8 +-
 .../parallel/EagerWorkingThread.java          |   2 +-
 src/{ => approach1}/parallel/MapLoader.java   |   2 +-
 .../parallel/SharedRessources.java            |  16 ++-
 src/approach2/ExplorerThread.java             |  17 +++
 src/approach2/MapLoader.java                  |  45 ++++++
 src/approach2/SharedRessources.java           | 121 ++++++++++++++++
 src/approach2/algorithm/Explorer.java         | 119 ++++++++++++++++
 .../algorithm/ParallelPathfinder.java         | 130 ++++++++++++++++++
 ...inWindow.java => MainWindowApproach1.java} |  11 +-
 src/window/MainWindowApproach2.java           |  71 ++++++++++
 15 files changed, 531 insertions(+), 32 deletions(-)
 create mode 100644 examples/debug.png
 rename src/{ => approach1}/algorithm/Explorer.java (95%)
 rename src/{ => approach1}/algorithm/ParallelPathfinder.java (97%)
 rename src/{ => approach1}/algorithm/WorkingExplorers.java (89%)
 rename src/{ => approach1}/parallel/EagerWorkingThread.java (97%)
 rename src/{ => approach1}/parallel/MapLoader.java (98%)
 rename src/{ => approach1}/parallel/SharedRessources.java (90%)
 create mode 100644 src/approach2/ExplorerThread.java
 create mode 100644 src/approach2/MapLoader.java
 create mode 100644 src/approach2/SharedRessources.java
 create mode 100644 src/approach2/algorithm/Explorer.java
 create mode 100644 src/approach2/algorithm/ParallelPathfinder.java
 rename src/window/{MainWindow.java => MainWindowApproach1.java} (86%)
 create mode 100644 src/window/MainWindowApproach2.java

diff --git a/examples/debug.png b/examples/debug.png
new file mode 100644
index 0000000000000000000000000000000000000000..bbb918962ed113c30f201511e1c0da6f8bebec8c
GIT binary patch
literal 884
zcmeAS@N?(olHy`uVBq!ia0y~yVA#&Uz_6TyiGhLP&aJ3m1_lPk;vjb?hIQv;UNSH+
zu%tWsIx;Y9?C1WI$jZRLz**oCS<Jw|cNl~jkLRyQVPIh9^mK6ysfc@f$&l-S14GM!
z-~X2jb4-hFXP$fO(qt9SqQ&Yz4UV`7*|yE_Sae)K*z=1-l2WIfvyaNf<c?02Djvg$
uF8zvXlU^8(DjE%fA({#%sr<ZbslRU@&zbjjB|Qub3=E#GelF{r5}E*XNJD%8

literal 0
HcmV?d00001

diff --git a/src/Program.java b/src/Program.java
index a25e53b..ee73c02 100644
--- a/src/Program.java
+++ b/src/Program.java
@@ -1,13 +1,13 @@
 // - 1 -
 
-import parallel.EagerWorkingThread;
-import window.MainWindow;
+import window.MainWindowApproach1;
+import window.MainWindowApproach2;
 
 public class Program {
 
 
     public static void main(String[] args) throws Exception {
-        MainWindow window = new MainWindow("Pathfinder v1", 1080, 1080);
+        MainWindowApproach2 window = new MainWindowApproach2("Pathfinder v1", 1080, 1080);
         window.run();
 
     }
diff --git a/src/algorithm/Explorer.java b/src/approach1/algorithm/Explorer.java
similarity index 95%
rename from src/algorithm/Explorer.java
rename to src/approach1/algorithm/Explorer.java
index 7e9fe2c..092cfc7 100644
--- a/src/algorithm/Explorer.java
+++ b/src/approach1/algorithm/Explorer.java
@@ -1,7 +1,6 @@
-package algorithm;
+package approach1.algorithm;
 
-import parallel.EagerWorkingThread;
-import parallel.SharedRessources;
+import approach1.parallel.SharedRessources;
 import structs.Vec3;
 
 public class Explorer {
@@ -20,11 +19,6 @@ public class Explorer {
 
     private Direction direction;
 
-
-    public int getSteps() {
-        return steps;
-    }
-
     public Explorer(int x, int y, int steps, Direction direction) {
         this.x = x;
         this.y = y;
diff --git a/src/algorithm/ParallelPathfinder.java b/src/approach1/algorithm/ParallelPathfinder.java
similarity index 97%
rename from src/algorithm/ParallelPathfinder.java
rename to src/approach1/algorithm/ParallelPathfinder.java
index 217e09a..fbb5bc4 100644
--- a/src/algorithm/ParallelPathfinder.java
+++ b/src/approach1/algorithm/ParallelPathfinder.java
@@ -1,7 +1,6 @@
-package algorithm;
+package approach1.algorithm;
 
-import parallel.EagerWorkingThread;
-import parallel.SharedRessources;
+import approach1.parallel.SharedRessources;
 import structs.Vec3;
 
 import java.awt.*;
diff --git a/src/algorithm/WorkingExplorers.java b/src/approach1/algorithm/WorkingExplorers.java
similarity index 89%
rename from src/algorithm/WorkingExplorers.java
rename to src/approach1/algorithm/WorkingExplorers.java
index 8b6ad68..787350c 100644
--- a/src/algorithm/WorkingExplorers.java
+++ b/src/approach1/algorithm/WorkingExplorers.java
@@ -1,12 +1,10 @@
-package algorithm;
+package approach1.algorithm;
 
-import parallel.EagerWorkingThread;
-import parallel.SharedRessources;
+import approach1.parallel.EagerWorkingThread;
+import approach1.parallel.SharedRessources;
 
 import java.util.*;
-import java.util.concurrent.ConcurrentLinkedDeque;
 import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.LinkedBlockingQueue;
 
 public class WorkingExplorers extends EagerWorkingThread {
 
diff --git a/src/parallel/EagerWorkingThread.java b/src/approach1/parallel/EagerWorkingThread.java
similarity index 97%
rename from src/parallel/EagerWorkingThread.java
rename to src/approach1/parallel/EagerWorkingThread.java
index cb1bba6..6145beb 100644
--- a/src/parallel/EagerWorkingThread.java
+++ b/src/approach1/parallel/EagerWorkingThread.java
@@ -1,4 +1,4 @@
-package parallel;
+package approach1.parallel;
 
 public abstract class EagerWorkingThread extends Thread {
 
diff --git a/src/parallel/MapLoader.java b/src/approach1/parallel/MapLoader.java
similarity index 98%
rename from src/parallel/MapLoader.java
rename to src/approach1/parallel/MapLoader.java
index d0721ba..50906d9 100644
--- a/src/parallel/MapLoader.java
+++ b/src/approach1/parallel/MapLoader.java
@@ -1,4 +1,4 @@
-package parallel;
+package approach1.parallel;
 
 import structs.Vec3;
 
diff --git a/src/parallel/SharedRessources.java b/src/approach1/parallel/SharedRessources.java
similarity index 90%
rename from src/parallel/SharedRessources.java
rename to src/approach1/parallel/SharedRessources.java
index 7f115e9..5119654 100644
--- a/src/parallel/SharedRessources.java
+++ b/src/approach1/parallel/SharedRessources.java
@@ -1,11 +1,9 @@
-package parallel;
+package approach1.parallel;
 
-import algorithm.Explorer;
-import algorithm.WorkingExplorers;
+import approach1.algorithm.Explorer;
+import approach1.algorithm.WorkingExplorers;
 import structs.Vec3;
 
-import java.util.Stack;
-
 public class SharedRessources {
     private static int USING_CORES;
 
@@ -81,6 +79,14 @@ public class SharedRessources {
     }
 
     public void add(Explorer explorer) {
+
+        for(int i = 0; i < maxCores; i++){
+            if(workingThreads[i].isReady()){
+                workingThreads[i].add(explorer);
+                return;
+            }
+        }
+
         this.workingThreads[(currentCore++) % maxCores].add(explorer);
     }
 
diff --git a/src/approach2/ExplorerThread.java b/src/approach2/ExplorerThread.java
new file mode 100644
index 0000000..6e2693c
--- /dev/null
+++ b/src/approach2/ExplorerThread.java
@@ -0,0 +1,17 @@
+package approach2;
+
+import approach2.algorithm.Explorer;
+
+public class ExplorerThread extends Thread {
+
+    private Explorer explorer;
+
+    @Override
+    public void run() {
+        explorer.explore();
+    }
+
+    public void setExplorer(Explorer explorer) {
+        this.explorer = explorer;
+    }
+}
diff --git a/src/approach2/MapLoader.java b/src/approach2/MapLoader.java
new file mode 100644
index 0000000..d9dd596
--- /dev/null
+++ b/src/approach2/MapLoader.java
@@ -0,0 +1,45 @@
+package approach2;
+
+import structs.Vec3;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferByte;
+
+public class MapLoader {
+
+    private int width;
+    private int height;
+
+    private MapLoader() {
+    }
+
+    private static MapLoader mapLoader;
+
+    public static MapLoader getDefault() {
+        if (mapLoader == null)
+            mapLoader = new MapLoader();
+        return mapLoader;
+    }
+
+    public void load(BufferedImage src) {
+        this.width = src.getWidth();
+        this.height = src.getHeight();
+
+        SharedRessources.getInstance().setWidth(width);
+        SharedRessources.getInstance().setHeight(height);
+
+        SharedRessources.getInstance().initializeArrays();
+
+        // https://stackoverflow.com/a/9470843/14727115
+        byte[] pixels = ((DataBufferByte) src.getRaster().getDataBuffer()).getData();
+
+        for (int j = 0; j < height; j++) {
+            for (int i = 0; i < width; i++) {
+                if (((BufferedImage) src).getRGB(i, j) == Color.black.getRGB())
+                    SharedRessources.getInstance().setWall(i, j);
+            }
+        }
+    }
+
+}
diff --git a/src/approach2/SharedRessources.java b/src/approach2/SharedRessources.java
new file mode 100644
index 0000000..2166944
--- /dev/null
+++ b/src/approach2/SharedRessources.java
@@ -0,0 +1,121 @@
+package approach2;
+
+import approach1.algorithm.WorkingExplorers;
+import approach2.algorithm.Explorer;
+import structs.Vec3;
+
+public class SharedRessources {
+
+    private static SharedRessources sharedRessources;
+
+    public static SharedRessources getInstance() {
+        if (sharedRessources == null)
+            sharedRessources = new SharedRessources(USING_CORES);
+        return sharedRessources;
+    }
+
+    private static int USING_CORES;
+
+    /***
+     * Use Integer.MAX_VALUE for all cores
+     * @param cores
+     */
+    public static void setMaximumCores(int cores) {
+        if (cores >= Runtime.getRuntime().availableProcessors())
+            cores = Runtime.getRuntime().availableProcessors();
+        USING_CORES = cores;
+    }
+
+    private int width;
+    private int height;
+
+    private boolean[] wallMatrix;
+    private boolean[] visitMatrix;
+
+    private Vec3[] directionMatrix;
+
+    private int maxCores;
+    private int currentCore;
+
+    private ExplorerThread[] workingThreads;
+
+
+    private SharedRessources(int cores) {
+        maxCores = cores;
+        currentCore = 0;
+
+        System.out.println("[*] Using " + maxCores + " cores.");
+
+        workingThreads = new ExplorerThread[maxCores];
+        for (int i = 0; i < maxCores; i++)
+            workingThreads[i] = new ExplorerThread();
+    }
+
+    public void initializeArrays() {
+        wallMatrix = new boolean[width * height];
+        visitMatrix = new boolean[width * height];
+        directionMatrix = new Vec3[width * height];
+
+        for (int i = 0; i < directionMatrix.length; i++)
+            directionMatrix[i] = new Vec3(0, 0, Integer.MAX_VALUE);
+    }
+
+    public void setExplorer(Explorer explorer) {
+        int index
+                = (currentCore++) % maxCores;
+
+        workingThreads[index]
+                .setExplorer(explorer);
+    }
+
+    public void start() {
+        for (int i = 0; i < maxCores; i++)
+            workingThreads[i].start();
+    }
+
+
+    public int getWidth() {
+        return width;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    protected void setWidth(int width) {
+        this.width = width;
+    }
+
+    protected void setHeight(int height) {
+        this.height = height;
+    }
+
+    protected void setWall(int x, int y) {
+        wallMatrix[x + y * width] = true;
+    }
+
+    public boolean isWall(int x, int y) {
+        return wallMatrix[x + y * width];
+    }
+
+    public int getStep(int x, int y) {
+        return (int) directionMatrix[x + y * width].getZ();
+    }
+
+    public void visit(int x, int y) {
+        visitMatrix[x + y * width] = true;
+    }
+
+    public boolean isVisited(int x, int y) {
+        return visitMatrix[x + y * width];
+    }
+
+    public Vec3 getData(int x, int y) {
+        return directionMatrix[x + y * width];
+    }
+
+    public void set(int x, int y, Vec3 data) {
+        directionMatrix[x + y * width]
+                = new Vec3(data.getX(), data.getY(), data.getZ());
+    }
+}
diff --git a/src/approach2/algorithm/Explorer.java b/src/approach2/algorithm/Explorer.java
new file mode 100644
index 0000000..727edd3
--- /dev/null
+++ b/src/approach2/algorithm/Explorer.java
@@ -0,0 +1,119 @@
+package approach2.algorithm;
+
+import approach2.SharedRessources;
+import structs.Vec3;
+
+import java.awt.*;
+import java.awt.geom.Point2D;
+import java.util.HashMap;
+import java.util.Stack;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+public class Explorer {
+
+    private int px;
+    private int py;
+
+    private int steps;
+
+    public Explorer(int x, int y, int steps) {
+        this.px = x;
+        this.py = y;
+        this.steps = steps;
+    }
+
+    private ConcurrentLinkedQueue<Point> openPoints
+            = new ConcurrentLinkedQueue<>();
+
+    public void explore() {
+        openPoints.offer(new Point(px, py));
+
+
+        while (!openPoints.isEmpty()) {
+
+
+            Point cur
+                    = openPoints.poll();
+
+            int x = cur.x;
+            int y = cur.y;
+
+            SharedRessources.getInstance().visit(x, y);
+
+
+            boolean
+                    left = SharedRessources.getInstance().isWall(x - 1, y);
+            boolean
+                    right = SharedRessources.getInstance().isWall(x + 1, y);
+            boolean up
+                    = SharedRessources.getInstance().isWall(x, y - 1);
+            boolean down
+                    = SharedRessources.getInstance().isWall(x, y + 1);
+
+            int stepLeft
+                    = SharedRessources.getInstance().getStep(x - 1, y);
+            int stepRight
+                    = SharedRessources.getInstance().getStep(x + 1, y);
+            int stepUp
+                    = SharedRessources.getInstance().getStep(x, y - 1);
+            int stepDown
+                    = SharedRessources.getInstance().getStep(x, y + 1);
+
+            if (!left) {
+                if (steps < stepLeft) {
+                    SharedRessources.getInstance()
+                            .set(x - 1, y, new Vec3(1, 0, steps + 1));
+
+                    openPoints
+                            .offer(new Point(x - 1, y));
+
+                }
+            }
+
+            if (!right) {
+                if (steps < stepRight) {
+                    SharedRessources.getInstance()
+                            .set(x + 1, y, new Vec3(-1, 0, steps + 1));
+
+
+                    openPoints
+                            .offer(new Point(x + 1, y));
+                }
+            }
+
+            if (!up) {
+                if (steps < stepUp) {
+                    SharedRessources.getInstance()
+                            .set(x, y - 1, new Vec3(0, 1, steps + 1));
+
+
+                    openPoints
+                            .offer(new Point(x, y - 1));
+                }
+            }
+
+            if (!down) {
+                if (steps < stepDown) {
+                    SharedRessources.getInstance()
+                            .set(x, y + 1, new Vec3(0, -1, steps + 1));
+
+
+                    openPoints
+                            .offer(new Point(x, y + 1));
+                }
+            }
+
+
+
+            steps++;
+
+
+
+
+        }
+
+
+    }
+
+
+}
diff --git a/src/approach2/algorithm/ParallelPathfinder.java b/src/approach2/algorithm/ParallelPathfinder.java
new file mode 100644
index 0000000..724f4ca
--- /dev/null
+++ b/src/approach2/algorithm/ParallelPathfinder.java
@@ -0,0 +1,130 @@
+package approach2.algorithm;
+
+import approach2.SharedRessources;
+import structs.Vec3;
+
+import java.awt.*;
+import java.util.ArrayList;
+
+public class ParallelPathfinder {
+
+    int lastDestX;
+    int lastDestY;
+
+    public void flood(int destX, int destY) {
+        System.out.println("[*] Flooding...");
+
+        lastDestX = destX;
+        lastDestY = destY;
+
+        SharedRessources
+                .getInstance()
+                .setExplorer(new Explorer(destX - 1, destY, 1));
+
+        SharedRessources
+                .getInstance()
+                .setExplorer(new Explorer(destX + 1, destY, 1));
+
+        SharedRessources
+                .getInstance()
+                .setExplorer(new Explorer(destX, destY - 1, 1));
+        SharedRessources
+                .getInstance()
+                .setExplorer(new Explorer(destX, destY + 1, 1));
+
+
+
+
+        SharedRessources.getInstance()
+                .set(destX - 1, destY, new Vec3(1, 0, 1));
+
+        SharedRessources.getInstance()
+                .set(destX + 1, destY, new Vec3(-1, 0, 1));
+
+        SharedRessources.getInstance()
+                .set(destX, destY - 1, new Vec3(0, +1, 1));
+
+        SharedRessources.getInstance()
+                .set(destX, destY + 1, new Vec3(0, -1, 1));
+
+
+        SharedRessources
+                .getInstance().start();
+
+    }
+
+    public ArrayList<Point> calculatePath(int startX, int startY, int destX, int destY) {
+        ArrayList<Point> path
+                = new ArrayList<>();
+
+        int x = startX;
+        int y = startY;
+
+        while (x != destX || y != destY) {
+
+            path.add(new Point(x, y));
+
+            Vec3 currentDir
+                    =
+                    SharedRessources.getInstance().getData(x, y);
+
+            int dx = (int) currentDir.getX();
+            int dy = (int) currentDir.getY();
+
+            if (dx == 0 && dy == 0)
+                return null;
+
+            x += dx;
+            y += dy;
+        }
+
+        System.out.println("Done.");
+
+        return path;
+    }
+
+    public void draw(Graphics g) {
+
+        for (int j = 0; j < SharedRessources.getInstance().getHeight(); j++) {
+            for (int i = 0; i < SharedRessources.getInstance().getWidth(); i++) {
+
+
+                if (SharedRessources.getInstance().isWall(i, j)) {
+                    g.setColor(Color.blue);
+                    g.fillRect(i * 10, j * 10, 10, 10);
+                }
+                else {
+
+
+                    int dx = (int) SharedRessources.getInstance().getData(i, j).getX() * 5;
+                    int dy = (int) SharedRessources.getInstance().getData(i, j).getY() * 5;
+
+                    if (dx != 0 || dy != 0) {
+                        int green = SharedRessources.getInstance().getStep(i, j);
+                        if (green >= 255)
+                            green = 255;
+                        Color color
+                                = new Color(0, green, 0);
+
+                        g.setColor(color);
+
+                        g.fillRect(i * 10, j * 10, 10, 10);
+
+                        g.setColor(Color.red);
+                        g.drawLine(i * 10, j * 10, i * 10 + dx, j * 10 + dy);
+
+
+
+                    } else {
+                        g.setColor(Color.black);
+                        g.fillRect(i * 10, j * 10, 10, 10);
+                    }
+                }
+
+
+
+
+            }
+        }
+    }
+}
diff --git a/src/window/MainWindow.java b/src/window/MainWindowApproach1.java
similarity index 86%
rename from src/window/MainWindow.java
rename to src/window/MainWindowApproach1.java
index 3600393..8fb9460 100644
--- a/src/window/MainWindow.java
+++ b/src/window/MainWindowApproach1.java
@@ -1,19 +1,18 @@
 package window;
 
-import algorithm.ParallelPathfinder;
-import parallel.MapLoader;
-import parallel.SharedRessources;
+import approach1.algorithm.ParallelPathfinder;
+import approach1.parallel.MapLoader;
+import approach1.parallel.SharedRessources;
 
 import javax.imageio.ImageIO;
 import java.awt.*;
-import java.awt.event.KeyEvent;
 import java.awt.event.MouseEvent;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 
-public class MainWindow extends Game {
-    public MainWindow(String title, int w, int h) {
+public class MainWindowApproach1 extends Game {
+    public MainWindowApproach1(String title, int w, int h) {
         super(title, w, h);
     }
 
diff --git a/src/window/MainWindowApproach2.java b/src/window/MainWindowApproach2.java
new file mode 100644
index 0000000..e1769c6
--- /dev/null
+++ b/src/window/MainWindowApproach2.java
@@ -0,0 +1,71 @@
+package window;
+
+import approach2.MapLoader;
+import approach2.SharedRessources;
+import approach2.algorithm.ParallelPathfinder;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class MainWindowApproach2 extends Game {
+    public MainWindowApproach2(String title, int w, int h) {
+        super(title, w, h);
+    }
+
+
+    ParallelPathfinder parallelPathfinder
+            = new ParallelPathfinder();
+
+    @Override
+    public void loadGame() {
+        SharedRessources.setMaximumCores(4);
+
+        try {
+            MapLoader.getDefault().load(ImageIO.read(new File("examples/maze.png")));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        parallelPathfinder.flood(80 ,80);
+
+
+    }
+
+
+    private boolean pressed;
+    ArrayList<Point> pts = new ArrayList<>();
+    @Override
+    public void updateGame() {
+
+        if (isMouseKeyDown(MouseEvent.BUTTON1) && !pressed) {
+            pts =
+                    parallelPathfinder.calculatePath(this.getMouseX() / 10, this.getMouseY() / 10, 80, 80);
+            pressed = true;
+        }
+
+        if (isMouseKeyUp(MouseEvent.BUTTON1))
+            pressed = false;
+
+    }
+
+    @Override
+    public void renderGame(Graphics g) {
+        parallelPathfinder.draw(g);
+
+
+
+        if (pts == null)
+            return;
+
+        g.setColor(Color.red);
+        for (var pt : pts) {
+            g.fillRect(pt.x * 10, pt.y * 10, 10, 10);
+        }
+    }
+
+
+}
-- 
GitLab