diff --git a/src/SpecificAiPlayerHard.java b/src/SpecificAiPlayerHard.java index a9a1345..067af48 100644 --- a/src/SpecificAiPlayerHard.java +++ b/src/SpecificAiPlayerHard.java @@ -14,6 +14,17 @@ public class SpecificAiPlayerHard extends AiPlayer{ private int nextChessRow; private int nextChessCol; + // Enum für die Orientierung + private enum Orientierung { + UNBEKANNT, + HORIZONTAL, + VERTIKAL + } + private Orientierung orientierung; + private Point firstHit; // Speichert den ersten Treffer zur Bestimmung der Orientierung + + + public SpecificAiPlayerHard() { super(); this.setName("AI Player Hard"); @@ -24,6 +35,8 @@ public class SpecificAiPlayerHard extends AiPlayer{ this.random = new Random(); this.nextChessRow = 0; this.nextChessCol = 0; + this.orientierung = Orientierung.UNBEKANNT; + this.firstHit = null; } // Checks if a position has already been shot at @@ -37,16 +50,16 @@ public class SpecificAiPlayerHard extends AiPlayer{ this.gridSize = super.board.getSize(); this.shotsFired = new boolean[gridSize][gridSize]; } - // If there are hits to process, prioritize those + // Wenn wir noch Treffer in der Queue haben, diese priorisieren while (!hitQueue.isEmpty()) { - Point target = hitQueue.remove(0); - + Point target = hitQueue.remove(0); if (!alreadyShot(target)) { + shotsFired[target.getX()][target.getY()] = true; return target; } } - // Otherwise, use chess pattern targeting + // Ansonsten weiterhin "Schachbrettmuster" int row = nextChessRow; int col = nextChessCol; while (alreadyShot(new Point(row, col))) { @@ -59,15 +72,109 @@ public class SpecificAiPlayerHard extends AiPlayer{ advanceChessPattern(); return new Point(row, col); } - + @Override public synchronized void receiveHit(HitResponse hitResponse) { super.receiveHit(hitResponse); - // If it's a hit or sunk, add adjacent cells to the hitsQueue + + // Wenn es ein Treffer ist, Adjacent-Punkte hinzufügen if (hitResponse.getHitResponse() == HitResponseType.HIT) { - addAdjacentPoints(hitResponse.getPoint()); + Point hitPoint = hitResponse.getPoint(); + + // Wenn wir noch keinen ersten Treffer haben, speicher ihn + if (firstHit == null) { + firstHit = hitPoint; + // Orientierung noch unbekannt: alle möglichen Richtungen hinzufügen + addAdjacentPoints(hitPoint); + } else { + // Wenn Orientierung noch nicht bestimmt, jetzt prüfen + if (this.orientierung == Orientierung.UNBEKANNT) { + // Prüfen, ob der zweite Treffer horizontal oder vertikal liegt + if (firstHit.getY() == hitPoint.getY()) { + this.orientierung = Orientierung.VERTIKAL; + } else if (firstHit.getX() == hitPoint.getX()) { + this.orientierung = Orientierung.HORIZONTAL; + } + + // Sobald die Orientierung erkannt wurde, entferne alle „unpassenden“ Punkte + if (this.orientierung != Orientierung.UNBEKANNT) { + cleanUpHitQueue(); + } + } + // Für den aktuellen Treffer nur in passender Orientierung erweitern + addPointsByOrientation(hitPoint); + } + } else if (hitResponse.getHitResponse() == HitResponseType.SUNK) { + this.orientierung = Orientierung.UNBEKANNT; + firstHit = null; + hitQueue.clear(); } } + + /** + * Entfernt aus der hitQueue alle Punkte, die nicht der erkannten Orientierung entsprechen. + */ + private void cleanUpHitQueue() { + if (firstHit == null || this.orientierung == Orientierung.UNBEKANNT) { + return; + } + ArrayList toRemove = new ArrayList<>(); + for (Point p : hitQueue) { + if (this.orientierung == Orientierung.HORIZONTAL) { + // HORIZONTAL => gleiche Zeile wie firstHit + if (p.getX() != firstHit.getX()) { + toRemove.add(p); + } + } else if (this.orientierung == Orientierung.VERTIKAL) { + // VERTICAL => gleiche Spalte wie firstHit + if (p.getY() != firstHit.getY()) { + toRemove.add(p); + } + } + } + hitQueue.removeAll(toRemove); + } + + /** + * Fügt benachbarte Felder in der **erkannten Orientierung** hinzu. + * - Ist die Orientierung HORIZONTAL, so werden nur links/rechts hinzugefügt. + * - Ist sie VERTICAL, so werden nur oben/unten hinzugefügt. + */ + private void addPointsByOrientation(Point point) { + if (this.orientierung == Orientierung.UNBEKANNT) { + // Fallback: füge alle benachbarten Punkte hinzu + addAdjacentPoints(point); + return; + } + + int x = point.getX(); + int y = point.getY(); + if (this.orientierung == Orientierung.HORIZONTAL) { + // Gleiche Zeile => links und rechts vom Point + Point left = new Point(x, y - 1); + Point right = new Point(x, y + 1); + + if (isValidPoint(left) && !alreadyShot(left) && !hitQueue.contains(left)) { + hitQueue.add(left); + } + if (isValidPoint(right) && !alreadyShot(right) && !hitQueue.contains(right)) { + hitQueue.add(right); + } + } else if (this.orientierung == Orientierung.VERTIKAL) { + // Gleiche Spalte => oben und unten + Point up = new Point(x - 1, y); + Point down = new Point(x + 1, y); + + if (isValidPoint(up) && !alreadyShot(up) && !hitQueue.contains(up)) { + hitQueue.add(up); + } + if (isValidPoint(down) && !alreadyShot(down) && !hitQueue.contains(down)) { + hitQueue.add(down); + } + } + } + + /** * Diese Methode erweitert die hitsQueue um die umliegenden Punkte die Schiffe seien könnten. * @param point