diff --git a/examples/bug.png b/examples/bug.png new file mode 100644 index 0000000000000000000000000000000000000000..d6682e499d534f9b0ca56d3f83b3aacb9f431fb7 Binary files /dev/null and b/examples/bug.png differ diff --git a/examples/maze3.png b/examples/maze3.png new file mode 100644 index 0000000000000000000000000000000000000000..6f7b00b8faf317374bffd02d46b4b93ff3b439e7 Binary files /dev/null and b/examples/maze3.png differ diff --git a/src/approach3/misc/Lexicon.java b/src/approach3/misc/Lexicon.java new file mode 100644 index 0000000000000000000000000000000000000000..e19d03d361fc4f398264a58f3aecb7d20c4c0709 --- /dev/null +++ b/src/approach3/misc/Lexicon.java @@ -0,0 +1,38 @@ +package approach3.misc; + +import structs.Int3; + +import java.awt.*; +import java.util.HashMap; + +public class Lexicon { + + private HashMap<Point, String> directionOrientation + = new HashMap<>() { + { + put(new Point(+1, 0), "Osten"); + put(new Point(-1, 0), "Westen"); + put(new Point(0, -1), "Norden"); + put(new Point(0, +1), "Süden"); + + put(new Point(+1, -1), "Nord-Osten"); + put(new Point(-1, -1), "Nord-Westen"); + + put(new Point(+1, +1), "Süd-Osten"); + put(new Point(-1, +1), "Süd-Westen"); + } + }; + + private static Lexicon lexicon; + + public static Lexicon getInstance() { + if (lexicon == null) + lexicon = new Lexicon(); + + return lexicon; + } + + public String getText(Point direction) { + return directionOrientation.get(direction); + } +} diff --git a/src/approach3/parallel/SharedRessources.java b/src/approach3/parallel/SharedRessources.java index 94e1a487f278b019d261f2e2b1cf0432f8d89b24..4860103bc3ea757f95ceaa7cc41f59468331739d 100644 --- a/src/approach3/parallel/SharedRessources.java +++ b/src/approach3/parallel/SharedRessources.java @@ -10,12 +10,48 @@ public class SharedRessources { private static final int AVAIBLE_CORES = Runtime.getRuntime().availableProcessors(); - private static int MAX_CORES = 1; + public enum Profile { + + /*** + * Every iteration in flood a line to dest will be constructed + * <br>Information: The path found can be optimal + */ + BEST_NODES(1), + /*** + * Every 18th iteration in flood a line to dest will be constructed + * <br>Warning: The path found won't be optimal + */ + MEDIUM(18), + /*** + * Every 64th iteration in flood a line to dest will be constructed + * <br>Warning: The path found won't be optimal + */ + FAST(64), + /*** + * Every 128th iteration in flood a line to dest will be constructed + * <br>Warning: By using this profile, the algorithm can fail to find a solution + * <br>Warning: The path found won't be optimal + */ + FASTER(128), + /*** + * Every 256th iteration in flood a line to dest will be constructed + * <br>Warning: By using this profile, the algorithm can fail to find a solution + * <br>Warning: The path found won't be optimal + */ + FASTEST(256); + + private final int profile; + + Profile(int profile) { + this.profile = profile; + } - public static void setMaxCores(int cores) { - MAX_CORES = cores >= AVAIBLE_CORES ? AVAIBLE_CORES : cores; + public int getValue() { + return profile; + } } + private static SharedRessources sharedRessources; public static SharedRessources getInstance() { @@ -23,12 +59,15 @@ public class SharedRessources { sharedRessources = new SharedRessources(); + return sharedRessources; } + private ExecutorService threadPool; private Int3[] data; + private boolean[] walls; private int width; @@ -39,8 +78,12 @@ public class SharedRessources { private volatile boolean found; + private Profile currentProfile; + + private int maxCores = 1; + private SharedRessources() { - threadPool = Executors.newFixedThreadPool(MAX_CORES); + } public void initialize(int w, int h) { @@ -53,6 +96,10 @@ public class SharedRessources { data[i] = new Int3(0, 0, Integer.MAX_VALUE); walls = new boolean[width * height]; + + threadPool = Executors.newFixedThreadPool(maxCores); + + System.out.println("[*] Using " + maxCores + " cores."); } @@ -85,15 +132,11 @@ public class SharedRessources { } public int getStep(int x, int y) { - synchronized (this) { - return data[x + y * width].getZ(); - } + 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); - } + data[x + y * width] = new Int3(dirX, dirY, step); } public Int3 getData(int x, int y) { @@ -116,4 +159,16 @@ public class SharedRessources { return this.height; } + + public void setCurrentProfile(Profile profile) { + this.currentProfile = profile; + } + + public Profile getCurrentProfile() { + return currentProfile; + } + + public void setMaxCores(int cores) { + maxCores = cores >= AVAIBLE_CORES ? AVAIBLE_CORES : cores; + } } diff --git a/src/approach3/parallel/WallBasedPathfinder.java b/src/approach3/parallel/WallBasedPathfinder.java index 887ab246cd2d65f542f9429d509fb8782a720a2a..280f597fcd22325c46d5681f30ba1906afe9342e 100644 --- a/src/approach3/parallel/WallBasedPathfinder.java +++ b/src/approach3/parallel/WallBasedPathfinder.java @@ -1,6 +1,8 @@ package approach3.parallel; +import approach3.misc.Lexicon; import approach3.parallel.operations.Trace; +import approach3.window.MainWindowApproach3; import structs.Int3; import structs.Vec3; @@ -28,17 +30,17 @@ public class WallBasedPathfinder { } - ArrayList<Point> debug = new ArrayList<>(); - - 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) { - debug.add(new Point(x, y)); + path.add(new Point(x, y)); Int3 currentDir = @@ -50,72 +52,70 @@ public class WallBasedPathfinder { if (dx == 0 && dy == 0) break; + // System.out.println(Lexicon.getInstance().getText(new Point(dx, dy))); x += dx; y += dy; - - } - - System.out.println("Done."); - - return debug; + return path; } - public void draw(Graphics g) { - - + public void draw(Graphics g, boolean showMeta) { 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 * 5, j * 5, 5, 5); - } else { - int dx = (int) SharedRessources.getInstance().getData(i, j).getX() * 5; - int dy = (int) SharedRessources.getInstance().getData(i, j).getY() * 5; + g.fillRect(i * MainWindowApproach3.SIZE, j * MainWindowApproach3.SIZE, + MainWindowApproach3.SIZE, MainWindowApproach3.SIZE); + } else if (SharedRessources.getInstance().getStep(i, j) != Integer.MAX_VALUE && showMeta) { + int dx = + (int) SharedRessources.getInstance().getData(i, j).getX() * MainWindowApproach3.SIZE; + int dy = + (int) SharedRessources.getInstance().getData(i, j).getY() * MainWindowApproach3.SIZE; - if (dx != 0 || dy != 0) { - int green = SharedRessources.getInstance().getStep(i, j); - if (green >= 255) - green = 255; - Color color - = new Color(0, 255, 0); + int green = SharedRessources.getInstance().getStep(i, j); + if (green >= 255) + green = 255; + Color color + = new Color(0, green, 0); - g.setColor(color); + g.setColor(color); + g.fillRect(i * MainWindowApproach3.SIZE, j * MainWindowApproach3.SIZE, + MainWindowApproach3.SIZE, MainWindowApproach3.SIZE); - g.fillRect(i * 5, j * 5, 5, 5); - g.setColor(Color.red); - g.drawLine(i * 5, j * 5, i * 5 + dx, j * 5 + dy); + g.setColor(Color.red); + g.drawLine( + i * MainWindowApproach3.SIZE, + j * MainWindowApproach3.SIZE, + i * MainWindowApproach3.SIZE + dx, + j * MainWindowApproach3.SIZE + dy); - } else { - g.setColor(Color.black); - g.fillRect(i * 5, j * 5, 5, 5); - } + } else { + g.setColor(Color.black); + g.fillRect(i * MainWindowApproach3.SIZE, j * MainWindowApproach3.SIZE, + MainWindowApproach3.SIZE, MainWindowApproach3.SIZE); } } + } - if (SharedRessources.getInstance().getEnd() == null || SharedRessources.getInstance().getStart() == null) + if (SharedRessources.getInstance(). + getEnd() == null || SharedRessources.getInstance().getStart() == null) return; g.setColor(Color.yellow); - g.fillRect(SharedRessources.getInstance().getEnd().x * 5, - SharedRessources.getInstance().getEnd().y * 5, 5 - , 5); - - g.setColor(Color.red); - g.fillRect(SharedRessources.getInstance().getStart().x * 5, - SharedRessources.getInstance().getStart().y * 5 - , 5, 5); - + g.fillRect( + SharedRessources.getInstance().getEnd().x * MainWindowApproach3.SIZE, + SharedRessources.getInstance().getEnd().y * MainWindowApproach3.SIZE, + MainWindowApproach3.SIZE, MainWindowApproach3.SIZE); g.setColor(Color.red); - - for (int i = 0; i < debug.size(); i++) - g.fillRect(debug.get(i).x * 5, debug.get(i).y * 5, 5, 5); - + g.fillRect( + SharedRessources.getInstance().getStart().x * MainWindowApproach3.SIZE, + SharedRessources.getInstance().getStart().y * MainWindowApproach3.SIZE, + MainWindowApproach3.SIZE, MainWindowApproach3.SIZE); } } diff --git a/src/approach3/parallel/operations/Flood.java b/src/approach3/parallel/operations/Flood.java index 55563b52eaacb4764c918ffb29c27e5e1d9ad11b..6accf9ca81a1cc4ec1e18f5742372aab818c7228 100644 --- a/src/approach3/parallel/operations/Flood.java +++ b/src/approach3/parallel/operations/Flood.java @@ -17,7 +17,7 @@ public class Flood implements Runnable { private int steps; - private Queue<Point> openPoints + private ArrayDeque<Point> openPoints = new ArrayDeque<>(); public Flood(int x, int y, int steps) { @@ -123,7 +123,7 @@ public class Flood implements Runnable { } - if (steps % 18 == 0) + if (steps % SharedRessources.getInstance().getCurrentProfile().getValue() == 0) SharedRessources .getInstance() .getExecutor() diff --git a/src/approach3/parallel/operations/Trace.java b/src/approach3/parallel/operations/Trace.java index 3246e379217deff11444052f0d18673e337d2c8f..6a42ffa0e49eebd7f37415ed6eeadf3c88d6f519 100644 --- a/src/approach3/parallel/operations/Trace.java +++ b/src/approach3/parallel/operations/Trace.java @@ -46,7 +46,7 @@ public class Trace implements Runnable { if (x0 == x1 && y0 == y1) { SharedRessources.getInstance().setFound(true); - System.out.println("FOUND!!!!!!!!"); + System.out.println("Start-End-Connection established"); break; } diff --git a/src/approach3/parallel/path/PathOptimization.java b/src/approach3/parallel/path/PathOptimization.java new file mode 100644 index 0000000000000000000000000000000000000000..43067b6607c6b576a7ede6420bf325806257da81 --- /dev/null +++ b/src/approach3/parallel/path/PathOptimization.java @@ -0,0 +1,23 @@ +package approach3.parallel.path; + +import java.awt.*; +import java.util.ArrayList; + +public class PathOptimization { + + private static PathOptimization pathOptimization; + + public static PathOptimization getDefault() { + if (pathOptimization == null) + pathOptimization = new PathOptimization(); + return pathOptimization; + } + + + public ArrayList<Point> optimize(ArrayList<Point> path) { + + return null; + } + + +} diff --git a/src/approach3/window/MainWindowApproach3.java b/src/approach3/window/MainWindowApproach3.java index ab3226b55b343192abcdb25812057ac125ec87f2..e5fcc745ff62829ff0a1e7ecf3da660538f8d214 100644 --- a/src/approach3/window/MainWindowApproach3.java +++ b/src/approach3/window/MainWindowApproach3.java @@ -7,7 +7,6 @@ import framework.Game; import javax.imageio.ImageIO; import java.awt.*; -import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.io.File; @@ -20,40 +19,47 @@ public class MainWindowApproach3 extends Game { } + public static final int SIZE = 5; + private WallBasedPathfinder pathfinder; + private ArrayList<Point> foundPath; + + private boolean pressed; + @Override public void loadGame() { - SharedRessources.setMaxCores(4); + SharedRessources.getInstance().setMaxCores(4); + SharedRessources.getInstance() + .setCurrentProfile(SharedRessources.Profile.MEDIUM); + try { - MapLoader.getDefault().load(ImageIO.read(new File("examples/maze1.png"))); + MapLoader.getDefault().load(ImageIO.read(new File("examples/debug.png"))); } catch (IOException e) { e.printStackTrace(); } pathfinder = new WallBasedPathfinder(); - } - - private boolean pressed; + } @Override public void updateGame() { if (isMouseKeyDown(MouseEvent.BUTTON1)) - SharedRessources.getInstance().setStart(this.getMouseX() / 5, this.getMouseY() / 5); + SharedRessources.getInstance().setStart(this.getMouseX() / SIZE, this.getMouseY() / SIZE); if (isMouseKeyDown(MouseEvent.BUTTON3)) - SharedRessources.getInstance().setEnd(this.getMouseX() / 5, this.getMouseY() / 5); + SharedRessources.getInstance().setEnd(this.getMouseX() / SIZE, this.getMouseY() / SIZE); if (isKeyDown(KeyEvent.VK_ENTER) && !pressed) { pressed = true; pathfinder.find(); - while (!SharedRessources.getInstance().isFound()); + while (!SharedRessources.getInstance().isFound()) ; int beginX = SharedRessources.getInstance().getStart().x; int beginY = SharedRessources.getInstance().getStart().y; @@ -61,16 +67,7 @@ public class MainWindowApproach3 extends Game { int endX = SharedRessources.getInstance().getEnd().x; int endY = SharedRessources.getInstance().getEnd().y; - - SharedRessources.getInstance() - .getExecutor() - .execute(new Runnable() { - @Override - public void run() { - pts = pathfinder.calculatePath(beginX, beginY, endX, endY); - } - }); - + foundPath = pathfinder.calculatePath(beginX, beginY, endX, endY); } if (isKeyUp(KeyEvent.VK_ENTER)) @@ -79,13 +76,19 @@ public class MainWindowApproach3 extends Game { } - ArrayList<Point> pts; - @Override public void renderGame(Graphics g) { if (pathfinder == null) return; - pathfinder.draw(g); + pathfinder.draw(g, false); + + if (foundPath == null) + return; + + g.setColor(Color.red); + for (var pt : foundPath) + g.fillRect(pt.x * SIZE, pt.y * SIZE, SIZE, SIZE); + } }