diff --git a/src/Program.java b/src/Program.java
index 2dda2440f00cdd849c956078b52c9e8ee362a830..a182e27ba7474e246c7b66769c7109d39548e725 100644
--- a/src/Program.java
+++ b/src/Program.java
@@ -1,10 +1,6 @@
 // - 1 -
 
-import window.MainWindowApproach1;
-import window.MainWindowApproach2;
-
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
+import approach2.window.MainWindowApproach2;
 
 public class Program {
 
diff --git a/src/window/MainWindowApproach1.java b/src/approach1/window/MainWindowApproach1.java
similarity index 97%
rename from src/window/MainWindowApproach1.java
rename to src/approach1/window/MainWindowApproach1.java
index 8fb9460b2d65297f4be2e4b0dca7dda80eb9ff9c..b340212e054774bd47677144b8dab5b09a42a324 100644
--- a/src/window/MainWindowApproach1.java
+++ b/src/approach1/window/MainWindowApproach1.java
@@ -1,8 +1,9 @@
-package window;
+package approach1.window;
 
 import approach1.algorithm.ParallelPathfinder;
 import approach1.parallel.MapLoader;
 import approach1.parallel.SharedRessources;
+import framework.Game;
 
 import javax.imageio.ImageIO;
 import java.awt.*;
diff --git a/src/approach2/ExplorerThread.java b/src/approach2/ExplorerThread.java
index 6e2693c51fd4a92356ed287f5c1800221cb4b228..0993db46331318a658f653357b7ee2c16a87dea7 100644
--- a/src/approach2/ExplorerThread.java
+++ b/src/approach2/ExplorerThread.java
@@ -8,6 +8,8 @@ public class ExplorerThread extends Thread {
 
     @Override
     public void run() {
+        if (explorer == null)
+            return;
         explorer.explore();
     }
 
diff --git a/src/approach2/algorithm/Explorer.java b/src/approach2/algorithm/Explorer.java
index dcff27d00c9ac3a4c51cfc9d1466bc8b6fba1afa..58f5c8ed59f888fbe2378eb212aff2081bf100dd 100644
--- a/src/approach2/algorithm/Explorer.java
+++ b/src/approach2/algorithm/Explorer.java
@@ -5,7 +5,9 @@ import structs.Vec3;
 
 import java.awt.*;
 import java.awt.geom.Point2D;
+import java.util.ArrayDeque;
 import java.util.HashMap;
+import java.util.Queue;
 import java.util.Stack;
 import java.util.concurrent.ConcurrentLinkedQueue;
 
@@ -22,23 +24,20 @@ public class Explorer {
         this.steps = steps;
     }
 
-    private ConcurrentLinkedQueue<Point> openPoints
-            = new ConcurrentLinkedQueue<>();
+    private Queue<Point> openPoints
+            = new ArrayDeque<>();
 
     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
diff --git a/src/window/MainWindowApproach2.java b/src/approach2/window/MainWindowApproach2.java
similarity index 93%
rename from src/window/MainWindowApproach2.java
rename to src/approach2/window/MainWindowApproach2.java
index e1769c6c489c5dc32b006bddc1969d3e70ce4995..993bed05a6d9747526ae0a20e8b21e4bf704fe8d 100644
--- a/src/window/MainWindowApproach2.java
+++ b/src/approach2/window/MainWindowApproach2.java
@@ -1,8 +1,9 @@
-package window;
+package approach2.window;
 
 import approach2.MapLoader;
 import approach2.SharedRessources;
 import approach2.algorithm.ParallelPathfinder;
+import framework.Game;
 
 import javax.imageio.ImageIO;
 import java.awt.*;
@@ -22,7 +23,7 @@ public class MainWindowApproach2 extends Game {
 
     @Override
     public void loadGame() {
-        SharedRessources.setMaximumCores(4);
+        SharedRessources.setMaximumCores(Integer.MAX_VALUE);
 
         try {
             MapLoader.getDefault().load(ImageIO.read(new File("examples/maze.png")));
diff --git a/src/approach3/misc/MapLoader.java b/src/approach3/misc/MapLoader.java
new file mode 100644
index 0000000000000000000000000000000000000000..d9abcdbddf1112506724a3a76047e34aef597752
--- /dev/null
+++ b/src/approach3/misc/MapLoader.java
@@ -0,0 +1,42 @@
+package approach3.misc;
+
+import approach3.parallel.SharedRessources;
+
+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().initialize(width, height);
+
+        // 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/approach3/parallel/SharedRessources.java b/src/approach3/parallel/SharedRessources.java
new file mode 100644
index 0000000000000000000000000000000000000000..198eef2111f38a85278a69eb637e14b04e90ae4a
--- /dev/null
+++ b/src/approach3/parallel/SharedRessources.java
@@ -0,0 +1,107 @@
+package approach3.parallel;
+
+import structs.Int3;
+
+import java.awt.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class SharedRessources {
+    private static final int AVAIBLE_CORES
+            = Runtime.getRuntime().availableProcessors();
+
+    private static int MAX_CORES = 1;
+
+    public static void setMaxCores(int cores) {
+        MAX_CORES = cores >= AVAIBLE_CORES ? AVAIBLE_CORES : cores;
+    }
+
+    private static SharedRessources sharedRessources;
+
+    public static SharedRessources getInstance() {
+        if (sharedRessources == null)
+            sharedRessources
+                    = new SharedRessources();
+
+        return sharedRessources;
+    }
+
+    private ExecutorService threadPool;
+
+    private Int3[] data;
+    private boolean[] walls;
+
+    private int width;
+    private int height;
+
+    private Point start;
+    private Point end;
+
+    private volatile boolean found;
+
+    private SharedRessources() {
+        threadPool = Executors.newFixedThreadPool(MAX_CORES);
+    }
+
+    public void initialize(int w, int h) {
+        this.width = w;
+        this.height = h;
+
+
+        data = new Int3[width * height];
+        for (int i = 0; i < data.length; i++)
+            data[i] = new Int3(0, 0, Integer.MAX_VALUE);
+
+        walls = new boolean[width * height];
+    }
+
+
+    public void setFound(boolean found) {
+        this.found = found;
+    }
+
+    public boolean isFound() {
+        return found;
+    }
+
+    public void setStart(int x, int y) {
+        start = new Point(x, y);
+    }
+
+    public void setEnd(int x, int y) {
+        end = new Point(x, y);
+    }
+
+    public Point getStart() {
+        return start;
+    }
+
+    public Point getEnd() {
+        return end;
+    }
+
+    public ExecutorService getExecutor() {
+        return threadPool;
+    }
+
+    public int getStep(int x, int y) {
+        synchronized (this) {
+            return data[x + y * width].getZ();
+        }
+    }
+
+    public void setData(int x, int y, int dirX, int dirY, int step) {
+        synchronized (this) {
+            data[x + y * width] = new Int3(dirX, dirY, step);
+        }
+    }
+
+    public boolean isWall(int x, int y) {
+        return walls[x + y * width];
+    }
+
+    public void setWall(int x, int y) {
+        walls[x + y * width] = true;
+    }
+
+}
diff --git a/src/approach3/parallel/WallBasedPathfinder.java b/src/approach3/parallel/WallBasedPathfinder.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0270c4597736085268e3c881d7eafcae11a9890
--- /dev/null
+++ b/src/approach3/parallel/WallBasedPathfinder.java
@@ -0,0 +1,7 @@
+package approach3.parallel;
+
+public class WallBasedPathfinder {
+
+
+
+}
diff --git a/src/approach3/parallel/operations/Flood.java b/src/approach3/parallel/operations/Flood.java
new file mode 100644
index 0000000000000000000000000000000000000000..952adfe9c6e8c3bae9e0f5a7b917560dbe7122be
--- /dev/null
+++ b/src/approach3/parallel/operations/Flood.java
@@ -0,0 +1,150 @@
+package approach3.parallel.operations;
+
+import approach3.parallel.SharedRessources;
+
+import java.awt.*;
+import java.util.ArrayDeque;
+import java.util.Queue;
+
+/**
+ * Diese Klasse überflutet alle Bereiche an der Wand und probiert an jedem Punkt eine
+ * neue Trace zum Ziel zu generieren
+ */
+public class Flood implements Runnable {
+
+    private int px;
+    private int py;
+
+    private int steps;
+
+    private Queue<Point> openPoints
+            = new ArrayDeque<>();
+
+    public Flood(int x, int y, int steps) {
+        this.px = x;
+        this.py = y;
+        this.steps = steps;
+    }
+
+
+    @Override
+    public void run() {
+        if (SharedRessources.getInstance().isWall(px, py))
+            return;
+
+        openPoints.offer(new Point(px, py));
+
+        while (!openPoints.isEmpty()) {
+
+            if (SharedRessources.getInstance().isFound())
+                return;
+
+            Point cur
+                    = openPoints.poll();
+
+
+
+            int x = cur.x;
+            int y = cur.y;
+
+
+            if(steps >= SharedRessources.getInstance().getStep(x, y))
+                break;
+
+            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);
+
+            boolean leftUp =
+                    SharedRessources.getInstance().isWall(x - 1, y - 1);
+            boolean rightUp =
+                    SharedRessources.getInstance().isWall(x + 1, y - 1);
+
+            boolean leftDown =
+                    SharedRessources.getInstance().isWall(x - 1, y + 1);
+            boolean rightDown =
+                    SharedRessources.getInstance().isWall(x + 1, 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 && !right && !up && !down && !rightDown && !rightUp && !leftDown && !leftUp)
+                continue;
+
+            if (!left) {
+                if (steps < stepLeft) {
+                    SharedRessources.getInstance()
+                            .setData(x - 1, y, 1, 0, steps + 1);
+
+                    openPoints
+                            .offer(new Point(x - 1, y));
+
+                }
+            }
+
+            if (!right) {
+                if (steps < stepRight) {
+                    SharedRessources.getInstance()
+                            .setData(x + 1, y, -1, 0, steps + 1);
+
+
+                    openPoints
+                            .offer(new Point(x + 1, y));
+                }
+            }
+
+            if (!up) {
+                if (steps < stepUp) {
+                    SharedRessources.getInstance()
+                            .setData(x, y - 1, 0, 1, steps + 1);
+
+
+                    openPoints
+                            .offer(new Point(x, y - 1));
+                }
+            }
+
+            if (!down) {
+                if (steps < stepDown) {
+                    SharedRessources.getInstance()
+                            .setData(x, y + 1, 0, -1, steps + 1);
+
+
+                    openPoints
+                            .offer(new Point(x, y + 1));
+                }
+            }
+
+
+            SharedRessources
+                    .getInstance()
+                    .getExecutor()
+                    .execute(new Trace(
+                            x,
+                            y,
+                            SharedRessources.getInstance().getStart().x,
+                            SharedRessources.getInstance().getStart().y,
+                            steps));
+
+            steps++;
+
+        }
+
+
+        System.out.println("Done flooding.");
+
+
+    }
+}
diff --git a/src/approach3/parallel/operations/Trace.java b/src/approach3/parallel/operations/Trace.java
new file mode 100644
index 0000000000000000000000000000000000000000..c1b93fc47eab9f6a9e6635af748f99337d76b10d
--- /dev/null
+++ b/src/approach3/parallel/operations/Trace.java
@@ -0,0 +1,106 @@
+package approach3.parallel.operations;
+
+import approach3.parallel.SharedRessources;
+
+// Source: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#All_cases
+public class Trace implements Runnable {
+
+    private int x0, y0;
+    private int x1, y1;
+
+    private int step;
+
+    public Trace(int x0, int y0, int x1, int y1, int step) {
+        this.x0 = x0;
+        this.y0 = y0;
+
+        this.x1 = x1;
+        this.y1 = y1;
+
+        this.step = step;
+    }
+
+    @Override
+    public void run() {
+
+        int oldX = 0;
+        int oldY = 0;
+
+
+        int dx = Math.abs(x1 - x0);
+        int sx = x0 < x1 ? 1 : -1;
+
+        int dy = -Math.abs(y1 - y0);
+        int sy = y0 < y1 ? 1 : -1;
+
+        int err = dx + dy;
+
+        while (true) {
+
+            if (SharedRessources.getInstance().isFound())
+                return;
+
+            oldX = x0;
+            oldY = y0;
+
+            if (x0 == x1 && y0 == y1) {
+                SharedRessources.getInstance().setFound(true);
+                System.out.println("FOUND!!!!!!!!");
+                break;
+            }
+
+            int err2 = 2 * err;
+
+            if (err2 >= dy) {
+                err += dy;
+                x0 += sx;
+            }
+            if (err2 <= dx) {
+                err += dx;
+                y0 += sy;
+            }
+
+            step++;
+
+            int currentStep
+                    = SharedRessources.getInstance().getStep(x0, y0);
+
+            if (SharedRessources.getInstance().isWall(x0, y0)) {
+
+                if (step < SharedRessources.getInstance().getStep(oldX - 1, oldY))
+                    SharedRessources
+                            .getInstance()
+                            .getExecutor()
+                            .execute(new Flood(oldX - 1, oldY, step));
+
+                if (step < SharedRessources.getInstance().getStep(oldX + 1, oldY))
+                    SharedRessources
+                            .getInstance()
+                            .getExecutor()
+                            .execute(new Flood(oldX + 1, oldY, step));
+
+                if (step < SharedRessources.getInstance().getStep(oldX, oldY - 1))
+                    SharedRessources
+                            .getInstance()
+                            .getExecutor()
+                            .execute(new Flood(oldX, oldY - 1, step));
+
+                if (step < SharedRessources.getInstance().getStep(oldX, oldY + 1))
+                    SharedRessources
+                            .getInstance()
+                            .getExecutor()
+                            .execute(new Flood(oldX, oldY + 1, step));
+
+                break;
+            } else if (step < currentStep) {
+                int dirX = x0 - oldX;
+                int dirY = y0 - oldY;
+
+                SharedRessources.getInstance()
+                        .setData(x0, y0, dirX, dirY, step);
+
+            }
+        }
+
+    }
+}
diff --git a/src/approach3/window/MainWindowApproach3.java b/src/approach3/window/MainWindowApproach3.java
new file mode 100644
index 0000000000000000000000000000000000000000..e70b60888ba286cbff1f23fdbcb91bbfc4f63339
--- /dev/null
+++ b/src/approach3/window/MainWindowApproach3.java
@@ -0,0 +1,26 @@
+package approach3.window;
+
+import framework.Game;
+
+import java.awt.*;
+
+public class MainWindowApproach3 extends Game {
+    public MainWindowApproach3(String title, int w, int h) {
+        super(title, w, h);
+    }
+
+    @Override
+    public void loadGame() {
+
+    }
+
+    @Override
+    public void updateGame() {
+
+    }
+
+    @Override
+    public void renderGame(Graphics g) {
+
+    }
+}
diff --git a/src/window/Game.java b/src/framework/Game.java
similarity index 99%
rename from src/window/Game.java
rename to src/framework/Game.java
index 8adbaa3190b4b7e7c49ca22c1da07c5a2732e5f2..061c4d9595ee01bc36397b63483719f6c4a49f10 100644
--- a/src/window/Game.java
+++ b/src/framework/Game.java
@@ -1,4 +1,4 @@
-package window;
+package framework;
 
 import javax.swing.*;
 import java.awt.*;
diff --git a/src/structs/Int3.java b/src/structs/Int3.java
new file mode 100644
index 0000000000000000000000000000000000000000..89ae1a9dab740ba2ff88e374f899484af75ecf5d
--- /dev/null
+++ b/src/structs/Int3.java
@@ -0,0 +1,37 @@
+package structs;
+
+public class Int3 {
+    private int x;
+    private int y;
+    private int z;
+
+    public Int3(int x, int y, int z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    public void setX(int x) {
+        this.x = x;
+    }
+
+    public void setY(int y) {
+        this.y = y;
+    }
+
+    public void setZ(int z) {
+        this.z = z;
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public int getY() {
+        return y;
+    }
+
+    public int getZ() {
+        return z;
+    }
+}