This commit is contained in:
Luca Conte 2025-06-04 14:26:41 +02:00
parent a9383ce3e7
commit e2e6b817f1
1 changed files with 81 additions and 1 deletions

View File

@ -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<Point> 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<Point[]> {
private ArrayDeque<Point> 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<Point> pathSoFar, PointAndDirection pd) {
this.pathSoFar = new ArrayDeque<>(pathSoFar);
this.current = pd.getPoint();
}
@Override
public Point[] compute() {
List<SolverForkJoinTask> 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<Point> 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)