diff --git a/EscapeBot.java b/EscapeBot.java index cd368da..a1b4cb0 100644 --- a/EscapeBot.java +++ b/EscapeBot.java @@ -1,100 +1,171 @@ package bot; -import java.util.Scanner; +import java.util.*; public class EscapeBot extends Bot { - private int currentX = 0; - private int currentY = 0; - private int spiralSize = 1; - private int stepsInCurrentDirection = 0; - private char currentDirection = 'd'; // Start with moving to the right + private boolean rocketFound; + private int roverX; + private int roverY; public EscapeBot(String[] args) { super(args); + this.rocketFound = false; + this.roverX = -1; // Startposition des Rovers ist unbekannt + this.roverY = -1; + } + + @Override + protected char nextMove(View view) throws Exception { + if (rocketFound) { + System.out.println("Rakete gefunden! Rover kehrt zurück."); + return 'V'; // Rückwärts bewegen + } + + if (roverX == -1 || roverY == -1) { + for (int y = 0; y < view.width; y++) { + for (int x = 0; x < view.width; x++) { + char cell = view.data.charAt(y * view.width + x); + if (cell == 'A') { + roverX = x; + roverY = y; + } + } + } + } + + char[][] grid = new char[view.width][view.width]; + for (int y = 0; y < view.width; y++) { + for (int x = 0; x < view.width; x++) { + grid[y][x] = view.data.charAt(y * view.width + x); + } + } + + List path = aStarSearch(grid, roverX, roverY); + + if (path != null && !path.isEmpty()) { + Node nextNode = path.get(0); + if (nextNode.x > roverX) { + roverX++; + return 'd'; // Nach rechts bewegen + } else if (nextNode.x < roverX) { + roverX--; + return 'a'; // Nach links bewegen + } else if (nextNode.y > roverY) { + roverY++; + return '^'; // Vorwärts bewegen + } else if (nextNode.y < roverY) { + roverY--; + return 'V'; // Rückwärts bewegen + } + } + + return '^'; // Standardbewegung, wenn keine Richtung gefunden wurde + } + + private List aStarSearch(char[][] grid, int startX, int startY) { + PriorityQueue openList = new PriorityQueue<>(Comparator.comparingInt(a -> a.f)); + Set closedSet = new HashSet<>(); + Map cameFrom = new HashMap<>(); + Map gScore = new HashMap<>(); + Map fScore = new HashMap<>(); + + Node startNode = new Node(startX, startY); + openList.add(startNode); + gScore.put(startNode, 0); + fScore.put(startNode, heuristic(startNode)); + + while (!openList.isEmpty()) { + Node current = openList.poll(); + + if (grid[current.y][current.x] == 'o') { + return reconstructPath(cameFrom, current); + } + + closedSet.add(current); + + for (Node neighbor : getNeighbors(current, grid)) { + if (closedSet.contains(neighbor)) { + continue; + } + + int tentativeGScore = gScore.getOrDefault(current, Integer.MAX_VALUE) + 1; + + if (!openList.contains(neighbor) || tentativeGScore < gScore.getOrDefault(neighbor, Integer.MAX_VALUE)) { + cameFrom.put(neighbor, current); + gScore.put(neighbor, tentativeGScore); + fScore.put(neighbor, tentativeGScore + heuristic(neighbor)); + + if (!openList.contains(neighbor)) { + openList.add(neighbor); + } + } + } + } + + return null; // Kein Weg gefunden + } + + private List getNeighbors(Node node, char[][] grid) { + List neighbors = new ArrayList<>(); + + int[][] directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; // Rechts, Links, Unten, Oben + + for (int[] dir : directions) { + int newX = node.x + dir[0]; + int newY = node.y + dir[1]; + + if (newX >= 0 && newX < grid.length && newY >= 0 && newY < grid.length && + grid[newY][newX] != '#') { + neighbors.add(new Node(newX, newY)); + } + } + + return neighbors; + } + + private List reconstructPath(Map cameFrom, Node current) { + List path = new ArrayList<>(); + path.add(current); + while (cameFrom.containsKey(current)) { + current = cameFrom.get(current); + path.add(current); + } + Collections.reverse(path); + return path; + } + + private int heuristic(Node node) { + // Verwenden Sie die Manhattan-Distanz als Heuristik, um die tatsächliche Entfernung zum Ziel zu schätzen + return Math.abs(node.x - roverX) + Math.abs(node.y - roverY); + } + + private static class Node { + int x; + int y; + int f; + + Node(int x, int y) { + this.x = x; + this.y = y; + this.f = 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Node node = (Node) o; + return x == node.x && y == node.y; + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } } public static void main(String[] args) { EscapeBot escapeBot = new EscapeBot(args); escapeBot.run(); } - - @Override - protected char nextMove(View view) throws Exception { - char[][] map = parseMap(view.data, view.width); - - char nextMove = 'w'; // Default move is to go forward - - if (map[currentY][currentX] == 'o') { - System.out.println("Rakete gefunden!"); - nextMove = 'q'; // Beende die Verbindung, wenn die Rakete gefunden wurde - } else { - // Bewegungslogik im Spiralmuster - switch (currentDirection) { - case 'd': // Bewege nach rechts - currentX++; - break; - case 's': // Bewege nach unten - currentY++; - break; - case 'a': // Bewege nach links - currentX--; - break; - case 'w': // Bewege nach oben - currentY--; - break; - } - stepsInCurrentDirection++; - - // Wenn der Rover die maximale Anzahl von Schritten in dieser Richtung erreicht hat - if (stepsInCurrentDirection == spiralSize) { - // Ändere die Richtung nach rechts - switch (currentDirection) { - case 'd': - currentDirection = 's'; - break; - case 's': - currentDirection = 'a'; - break; - case 'a': - currentDirection = 'w'; - break; - case 'w': - currentDirection = 'd'; - break; - } - - // Setze die Anzahl der Schritte in dieser Richtung zurück und erhöhe die Spiralgöße - stepsInCurrentDirection = 0; - if (currentDirection == 'd' || currentDirection == 'a') { - spiralSize++; - } - } - - // Überprüfe, ob der nächste Zug innerhalb der Karte liegt - if (currentX < 0 || currentX >= view.width || currentY < 0 || currentY >= view.width) { - // Der nächste Zug liegt außerhalb der Karte, also drehe den Rover um - nextMove = 'a'; - } else { - // Der nächste Zug liegt innerhalb der Karte, bewege den Rover dorthin - nextMove = currentDirection; - } - } - - return nextMove; - } - - // Hilfsmethode zum Parsen des Kartenscans in ein char-Array - private char[][] parseMap(String data, int width) { - char[][] map = new char[width][width]; - String[] lines = data.split("\n"); - for (int i = 0; i < width; i++) { - String line = lines[i]; - for (int j = 0; j < width; j++) { - map[i][j] = line.charAt(j); - } - } - return map; - } } - -