From e2e6b817f15bb9b21bf34d67dd4388b1e5d53856 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Wed, 4 Jun 2025 14:26:41 +0200 Subject: [PATCH] solver --- projekt/Solver.java | 82 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/projekt/Solver.java b/projekt/Solver.java index b3eb119..ab85d6c 100644 --- a/projekt/Solver.java +++ b/projekt/Solver.java @@ -11,6 +11,9 @@ import java.io.ObjectOutputStream; import java.util.ArrayDeque; import java.util.Arrays; +import java.util.concurrent.*; +import java.util.List; +import java.util.ArrayList; import javax.swing.JFrame; import javax.swing.JPanel; @@ -113,6 +116,83 @@ final public class Solver extends JPanel { // Point[0] is only for making the return value have type Point[] (and not Object[]): return pathSoFar.toArray(new Point[0]); } + + public Point[] solveConcurrently() { + visited = new boolean[labyrinth.getWidth()][labyrinth.getHeight()]; // initially all false + + ArrayDeque startPath = new ArrayDeque<>(); + Point start = labyrinth.getStart(); + PointAndDirection startPD = new PointAndDirection(start, Direction.N); // Dummy-Richtung + //startPath.addLast(start); + + SolverForkJoinTask task = new SolverForkJoinTask(startPath, startPD); + ForkJoinPool pool = ForkJoinPool.commonPool(); + Point[] solution = pool.invoke(task); + return solution; + } + + public class SolverForkJoinTask extends RecursiveTask { + private ArrayDeque pathSoFar; // Path from start to just before current + Point current; + + //Jede Task muss den pathSoFar übergeben kriegen, aber braucht einen neuen backtrackStack, denn wenn die Task + //in eine Sackgasse läuft, soll sie nur maximal bis zur ihrer Erstellungs-Zelle zurück gehen + public SolverForkJoinTask(ArrayDeque pathSoFar, PointAndDirection pd) { + this.pathSoFar = new ArrayDeque<>(pathSoFar); + this.current = pd.getPoint(); + } + @Override + public Point[] compute() { + List subTasks = new ArrayList<>(); + + while (!labyrinth.isDestination(current)) { + Point next = null; + visit(current); + Direction[] dirs = Direction.values(); + + for (Direction directionToNeighbor : dirs) { + Point neighbor = current.getNeighbor(directionToNeighbor); + if (labyrinth.hasPassage(current, directionToNeighbor) + && !visitedBefore(neighbor) + && (!labyrinth.isBlindAlley(neighbor, directionToNeighbor.opposite) + || labyrinth.isDestination(neighbor))) { + + if (next == null) { + next = neighbor; + } else { + // pathSoFar kopieren! + ArrayDeque newPath = new ArrayDeque<>(pathSoFar); + newPath.addLast(current); + + SolverForkJoinTask subTask = new SolverForkJoinTask(newPath, + new PointAndDirection(neighbor, directionToNeighbor.opposite)); + subTask.fork(); + subTasks.add(subTask); + } + } + } + + //Es wurde ein Nachbar gefunden + if (next != null) { + pathSoFar.addLast(current); + current = next; + } else { //Es wurde kein gültiger Nachbar gefunden + for (SolverForkJoinTask sub : subTasks) { + Point[] result = sub.join(); + if (result != null) { + return result; + } + } + return null; + } + } + + //Ziel erreicht + pathSoFar.addLast(current); + return pathSoFar.toArray(new Point[0]); + } + + } @Override protected void paintComponent(Graphics graphics) { @@ -242,7 +322,7 @@ private static void displayLabyrinth(Solver solver) { } long startTime = System.currentTimeMillis(); - solver.solution = solver.solve(); + solver.solution = solver.solveConcurrently(); long endTime = System.currentTimeMillis(); if (solver.solution == null)