From f46e527fbd107e08f690e6f3ad8924edfe64d001 Mon Sep 17 00:00:00 2001 From: Yanis O <oualanyanis01@gmail.com> Date: Sat, 23 Nov 2024 15:57:43 +0100 Subject: [PATCH] =?UTF-8?q?[Ajout]=20AirTanker=20:=20Canadair=20qui=20?= =?UTF-8?q?=C3=A9teins=20les=20feux=20sur=20un=20rayon=20de=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/AirTanker.java | 172 +++++++++++++++++ src/main/java/model/Cloud.java | 18 +- src/main/java/model/Fire.java | 89 +++++---- src/main/java/model/FireFighter.java | 180 ++++++++++++------ src/main/java/model/MotorizedFireFighter.java | 110 ++++++++--- src/main/java/model/Mountain.java | 9 +- src/main/java/util/Direction.java | 5 + src/main/java/util/Matrix.java | 3 + src/main/java/util/PositionUtil.java | 33 ++++ 9 files changed, 488 insertions(+), 131 deletions(-) create mode 100644 src/main/java/model/AirTanker.java create mode 100644 src/main/java/util/Direction.java diff --git a/src/main/java/model/AirTanker.java b/src/main/java/model/AirTanker.java new file mode 100644 index 0000000..b723a7b --- /dev/null +++ b/src/main/java/model/AirTanker.java @@ -0,0 +1,172 @@ +package model; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import javafx.scene.paint.Color; +import util.Direction; +import util.Position; +import util.PositionUtil; + +public class AirTanker implements Entity{ + private final Color viewColor = Color.GOLD; + private Direction direction; // Direction in which the AirTanker moves + private int age; + private Position position; + private int priority = 3; + + public AirTanker(Position position, Board<Square> b) { + this.age = 0; + this.position = position; + determineDirection(b); + extinguish(position,b); + } + + @Override + public int getPriority() { + return this.priority; + } + + private void determineDirection(Board<Square> b) { + int rowCount = b.rowCount(); + int columnCount = b.columnCount(); + + if (position.x() == 0) { + direction = Direction.EAST; // Move east if on left edge + } else if (position.x() == columnCount - 1) { + direction = Direction.WEST; // Move west if on right edge + } else if (position.y() == 0) { + direction = Direction.SOUTH; // Move south if on top edge + } else if (position.y() == rowCount - 1) { + direction = Direction.NORTH; // Move north if on bottom edge + } else { + System.out.println("not on a edge"); + // Not on an edge; default to moving east or choose a random direction + direction = Direction.EAST; + } + } + + @Override + public List<Position> nextTurn(Board<Square> b) { + + List<Position> positions = new ArrayList<>(); + // Move in the determined direction + Position nextPos = getNextPosition(position, direction, b); + + if (nextPos == null || !b.doesPositionExist(nextPos)) { + // Reached the edge; remove AirTanker from the board + System.out.println("end of airtanker mission"); + b.clearCaseFrom(this, position); + positions.add(position); + return positions; + } else { + // Extinguish fires within a 3-square radius + + positions.addAll(extinguish(position, b)); + // Move to the next position + b.clearCaseFrom(this, position); + positions.add(new Position(position.x(), position.y())); // Old position + this.position = nextPos; + b.addEntityAtSquare(this, nextPos); + positions.add(nextPos); // New position + + + // Increment age if needed + this.age++; + + return positions; + } + } + protected List<Position> extinguish(Position position, Board<Square> b){ + List<Position> positions = new ArrayList<Position>(); + List<Position> positionsInRange = PositionUtil.getPositionsInRadius(position, 3, b); + for (Position p : positionsInRange) { + if (b.doesSquareContainEntity(p, Fire.class)) { + b.getStates(p).getEntities().removeIf(e -> e instanceof Fire); + positions.add(p); // Add position where fire was extinguished + } + } + return positions; + } + private Position getNextPosition(Position currentPosition, Direction direction, Board<Square> b) { + int x = currentPosition.x(); + int y = currentPosition.y(); + + switch (direction) { + case NORTH: + y -= 1; + break; + case SOUTH: + y += 1; + break; + case EAST: + x += 1; + break; + case WEST: + x -= 1; + break; + default: + break; // Only handling cardinal directions + } + Position newPos = new Position(x, y); + System.out.println("trying to move to : " + newPos.toString()); + if (b.doesPositionExist(newPos)) { + return newPos; + } else { + return null; // Reached the edge + } + } + + public Direction getDirection(){ + return this.direction; + } + + @Override + public void setPosition(Position p) { + this.position = p; + } + + @Override + public Position getPosition() { + return this.position; + } + + @Override + public Color getViewColor() { + return this.viewColor; + } + + @Override + public int getAge() { + return this.age; + } + + @Override + public void incrementAge() { + this.age++; + } + + @Override + public void setAge(int age) { + this.age = age; + } + + + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; // Check if same object + if (obj == null || getClass() != obj.getClass()) return false; // Check for null and class match + AirTanker airTanker = (AirTanker) obj; // Cast to Fire + return age == airTanker.age && position.equals(airTanker.position); // Compare age and position + } + + + @Override + public int hashCode() { + return Objects.hash(position, age); + } + + +} diff --git a/src/main/java/model/Cloud.java b/src/main/java/model/Cloud.java index baf7b0a..840195d 100644 --- a/src/main/java/model/Cloud.java +++ b/src/main/java/model/Cloud.java @@ -1,19 +1,17 @@ package model; -import javafx.geometry.Pos; +import java.util.List; +import java.util.Random; + import javafx.scene.paint.Color; import util.Position; import util.PositionUtil; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - public class Cloud implements Entity{ private int age; private Position position; - private final Color viewColor = Color.GREEN; - private final int priority = 3; + private final Color viewColor = Color.GRAY; + private final int priority = 2; @@ -59,7 +57,7 @@ public class Cloud implements Entity{ b.getStates(p).getEntities().removeIf(element -> element instanceof Fire); List<Entity> entities = b.getStates(p).getEntities(); for (Entity e : entities) { - if (e instanceof EmptyEntity) { + if (e instanceof EmptySquare) { e.setAge(b.stepNumber() + 1); } } @@ -99,7 +97,9 @@ public class Cloud implements Entity{ } @Override - public int getPriority(){ return this.priority;} + public int getPriority(){ + return this.priority; + } } diff --git a/src/main/java/model/Fire.java b/src/main/java/model/Fire.java index c3814b3..8ad742e 100644 --- a/src/main/java/model/Fire.java +++ b/src/main/java/model/Fire.java @@ -2,6 +2,7 @@ package model; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import javafx.scene.paint.Color; import util.Position; @@ -9,46 +10,62 @@ import util.PositionUtil; public class Fire implements Entity { - Board<Square> b; private Position position; private final Color viewColor = Color.RED; private int age; - private final int priority = 0; + private final int priority = 1; - public Fire(Position position, Board<Square> b) { - this.b = b; + public Fire(Position position) { this.position = position; this.age = 0; } - public Fire(Position position, Board<Square> b, int age) { - this.b = b; + public Fire(Position position, int age) { this.position = position; this.age = age; } @Override public List<Position> nextTurn(Board<Square> board) { - if (board.getStepNumber() % 2 == 0) - return new ArrayList<Position>(); - if (age == 0) { - age = age + 1; - return new ArrayList<Position>(); + List<Position> newFirePositions = new ArrayList<>(); + if(board.getStepNumber() <= 1){ + return newFirePositions; } - List<Position> positions = PositionUtil.generateAdjacentPositions(position, board); - positions.removeIf( p -> b.doesSquareContainEntity(p, Mountain.class)); - for (Position p : positions) { - if (b.getStates(p).isEmpty() && !b.getStates(p).getEntities().contains(Cloud.class)) { - if (b.getStates(p).getMaxAge() < b.getStepNumber() - && PositionUtil.getManhattanDistance(position, p) == 1) { - board.addEntityAtSquare(new Fire(p, board), p); - } + // Fire propagates every 2 turns + if (age % 2 != 0) { + return newFirePositions; // No propagation this turn + } + + // Generate adjacent positions + List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, board); + + for (Position p : adjacentPositions) { + // Skip if position does not exist + if (!board.doesPositionExist(p)) { + continue; + } + + // Skip if the position contains a Mountain + if (board.doesSquareContainEntity(p, Mountain.class)) { + continue; } - if (!b.doesPositionExist(p)) { - positions.remove(p); + + // Skip if the position already contains a Fire + if (board.doesSquareContainEntity(p, Fire.class)) { + continue; + } + + // Skip if the position contains a Cloud (if clouds prevent fire spread) + if (board.doesSquareContainEntity(p, Cloud.class)) { + continue; } + + // Add new Fire to the board + board.addEntityAtSquare(new Fire(p), p); + newFirePositions.add(p); // Keep track of new fires for updates } - return positions; + + return newFirePositions; } @Override @@ -61,6 +78,7 @@ public class Fire implements Entity { return this.position; } + @Override public Color getViewColor() { return this.viewColor; } @@ -72,7 +90,7 @@ public class Fire implements Entity { @Override public void incrementAge() { - this.age = age + 1; + this.age++; } @Override @@ -81,27 +99,22 @@ public class Fire implements Entity { } @Override - public int getPriority(){ return this.priority;} + public int getPriority() { + return this.priority; + } @Override public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null || getClass() != obj.getClass()) return false; - Fire fire = (Fire) obj; - return age == fire.age && - priority == fire.priority && - (position == null ? fire.position == null : position.equals(fire.position)) && - (b == null ? fire.b == null : b.equals(fire.b)) && - (viewColor == null ? fire.viewColor == null : viewColor.equals(fire.viewColor)); + if (this == obj) return true; // Check if same object + if (obj == null || getClass() != obj.getClass()) return false; // Check for null and class match + Fire fire = (Fire) obj; // Cast to Fire + return age == fire.age && position.equals(fire.position); // Compare age and position } + @Override public int hashCode() { - int result = (b == null ? 0 : b.hashCode()); - result = 31 * result + (position == null ? 0 : position.hashCode()); - result = 31 * result + (viewColor == null ? 0 : viewColor.hashCode()); - result = 31 * result + age; - result = 31 * result + priority; - return result; + return Objects.hash(position, age); } + } diff --git a/src/main/java/model/FireFighter.java b/src/main/java/model/FireFighter.java index bd7ffb6..bc070cb 100644 --- a/src/main/java/model/FireFighter.java +++ b/src/main/java/model/FireFighter.java @@ -1,7 +1,11 @@ package model; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + import javafx.scene.paint.Color; -import util.*; +import util.Position; +import util.PositionUtil; @@ -10,103 +14,171 @@ public class FireFighter implements Entity { private Position position; private final Color viewColor = Color.BLUE; private final int priority = 1; + protected List<Position> lastThreePosition; public FireFighter(Position position, Board<Square> b) { this.position = position; this.age = 0; + this.lastThreePosition = new ArrayList<Position>(); } public FireFighter(Position position, Board<Square> b, int age) { this.position = position; this.age = age; + this.lastThreePosition = new ArrayList<Position>(); } public List<Position> nextTurn(Board<Square> b) { List<Position> positions = new ArrayList<>(); - - // Générer les positions adjacentes + + // Generate adjacent positions, excluding mountains List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, b); - adjacentPositions.removeIf( p -> b.doesSquareContainEntity(p, Mountain.class)); - - // Vérifier s'il y a du feu dans une des positions adjacentes + adjacentPositions.removeIf(p -> b.doesSquareContainEntity(p, Mountain.class)); + + // Check if there is fire in any adjacent positions boolean hasFire = adjacentPositions.stream() .anyMatch(p -> b.doesSquareContainEntity(p, Fire.class)); + + boolean isStuck = isStuck(); + if (hasFire) { - // Si du feu est trouvé, on éteint les feux adjacents + // Extinguish fires in adjacent positions positions.addAll(extinguish(adjacentPositions, b)); - } else { - // Chercher la position du feu le plus proche - Position nearestFirePos = b.getNearestEntity(position, Fire.class); - - if (nearestFirePos != null && !nearestFirePos.equals(position)) { - // Trouver la meilleure position pour se rapprocher du feu - Position nextPos = getNextPositionTowards(position, nearestFirePos, b); - if (nextPos != null) { - // Mettre à jour la position du pompier - b.clearCaseFrom(this, position); // Vider l'ancienne case - positions.add(new Position(position.x(), position.y())); - this.position = nextPos; - b.addEntityAtSquare(this, nextPos); // Mettre à jour la nouvelle case - positions.add(nextPos); - adjacentPositions = PositionUtil.generateAdjacentPositions(nextPos, b); - positions.addAll(extinguish(adjacentPositions, b)); - } - // Aucun déplacement possible = le pompier reste sur place + if (isStuck) { + // If stuck, attempt to move and then extinguish fires + positions.addAll(moveAndExtinguish(b)); } + } else { + // No fire adjacent; move and attempt to extinguish fires + positions.addAll(moveAndExtinguish(b)); } - + + // Update last three positions + updateLastPositions(); + return positions; } + + protected boolean isStuck() { + if (lastThreePosition.size() < 3) { + return false; + } + Position first = lastThreePosition.get(lastThreePosition.size() - 1); + return lastThreePosition.stream().allMatch(pos -> pos.equals(first)); + } + + private void updateLastPositions() { + if (lastThreePosition.size() >= 3) { + lastThreePosition.remove(0); + } + lastThreePosition.add(this.position); + } + protected List<Position> extinguish(List<Position> adjacentPositions, Board<Square> b) { List<Position> extinguishedPositions = new ArrayList<>(); for (Position p : adjacentPositions) { - extinguishedPositions.addAll(adjacentPositions); - b.getStates(p).getEntities().removeIf(element -> element instanceof Fire); - List<Entity> entities = b.getStates(p).getEntities(); - for (Entity e : entities) { - if (e instanceof EmptyEntity) { - e.setAge(b.stepNumber() + 1); - } + if (b.doesSquareContainEntity(p, Fire.class)) { + b.getStates(p).getEntities().removeIf(element -> element instanceof Fire); + // Update age for EmptyEntity if needed + b.getStates(p).getEntities().forEach(e -> { + if (e instanceof EmptySquare) { + e.setAge(b.stepNumber() + 1); + } + }); + extinguishedPositions.add(p); // Add position where fire was extinguished } - extinguishedPositions.add(p); // Ajouter la position où le feu a été éteint - } return extinguishedPositions; } + + protected List<Position> moveAndExtinguish(Board<Square> b) { + List<Position> positions = new ArrayList<>(); + + // Find the nearest fire + Position nearestFirePos = b.getNearestEntity(position, Fire.class); + if (nearestFirePos != null) { + // Get the next position towards the fire + Position nextPos = getNextPositionTowards(position, nearestFirePos, b); + if (nextPos != null && !nextPos.equals(position)) { + // Move the firefighter + b.clearCaseFrom(this, position); // Clear old position + positions.add(new Position(position.x(), position.y())); // Add old position + this.position = nextPos; + b.addEntityAtSquare(this, nextPos); // Add to new position + positions.add(nextPos); // Add new position + + // After moving, attempt to extinguish fires adjacent to new position + List<Position> newAdjacentPositions = PositionUtil.generateAdjacentPositions(nextPos, b); + newAdjacentPositions.removeIf(p -> b.doesSquareContainEntity(p, Mountain.class)); + positions.addAll(extinguish(newAdjacentPositions, b)); + } + } + return positions; + } + protected Position getNextPositionTowards(Position currentPos, Position targetPos, Board<Square> b) { - // Générer les 8 positions adjacentes possibles + // Generate adjacent positions List<Position> possibleMoves = PositionUtil.generateAllAdjacentPositions(currentPos, b); - - // Filtrer les positions qui sont libres - possibleMoves.removeIf(p -> !(b.isPositionEmpty(p))); - - // Si aucune position libre n'est disponible, retourner null + + // Filter out positions that are not empty or contain obstacles + possibleMoves.removeIf(p -> !b.isPositionEmpty(p) || b.doesSquareContainEntity(p, Mountain.class)); + + // If no possible moves, return null if (possibleMoves.isEmpty()) { return null; } - - // Calculer la distance actuelle vers la cible + + // Calculate the current distance to the target int currentDistance = PositionUtil.getManhattanDistance(currentPos, targetPos); - - // Choisir la position libre qui réduit le plus la distance vers le feu - Position bestMove = null; - int minDistance = currentDistance; + + // Initialize variables to find the best moves + int minDistance = Integer.MAX_VALUE; + List<Position> bestMoves = new ArrayList<>(); + for (Position move : possibleMoves) { int distance = PositionUtil.getManhattanDistance(move, targetPos); + + // Skip positions occupied by other firefighters + if (b.doesSquareContainEntity(move, FireFighter.class)) { + continue; + } + + // Find positions that minimize the distance if (distance < minDistance) { minDistance = distance; - bestMove = move; + bestMoves.clear(); + bestMoves.add(move); + } else if (distance == minDistance) { + bestMoves.add(move); } } - - // Si aucun déplacement ne réduit la distance, annuler le déplacement - if (bestMove == null) { - return null; + + // If no better move is found, consider moves that maintain the same distance + if (bestMoves.isEmpty()) { + minDistance = currentDistance; + for (Position move : possibleMoves) { + int distance = PositionUtil.getManhattanDistance(move, targetPos); + if (distance == minDistance) { + bestMoves.add(move); + } + } + } + + // If still no move is found, stay in the current position + if (bestMoves.isEmpty()) { + return currentPos; } - return bestMove; + + // Select a move from the best moves (e.g., randomly or based on additional criteria) + Random r = new Random(); + + Position nextMove = bestMoves.get(r.nextInt(bestMoves.size())); + + return nextMove; } + @Override public void setPosition(Position p) { diff --git a/src/main/java/model/MotorizedFireFighter.java b/src/main/java/model/MotorizedFireFighter.java index 4ad3f74..146fb38 100644 --- a/src/main/java/model/MotorizedFireFighter.java +++ b/src/main/java/model/MotorizedFireFighter.java @@ -1,52 +1,110 @@ package model; -import java.util.*; +import java.util.ArrayList; +import java.util.List; + import javafx.scene.paint.Color; -import util.*; +import util.Position; +import util.PositionUtil; public class MotorizedFireFighter extends FireFighter { private final Color viewColor = Color.CYAN; - public MotorizedFireFighter(Position position, Board<Square> b){ + + public MotorizedFireFighter(Position position, Board<Square> b) { super(position, b); } + + @Override public List<Position> nextTurn(Board<Square> b) { List<Position> positions = new ArrayList<>(); - // Générer les positions adjacentes + // Generate adjacent positions excluding mountains List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(getPosition(), b); - adjacentPositions.removeIf( p -> b.doesSquareContainEntity(p, Mountain.class)); + adjacentPositions.removeIf(p -> b.doesSquareContainEntity(p, Mountain.class)); - // Vérifier s'il y a du feu dans une des positions adjacentes + // Check if there is fire in any adjacent positions boolean hasFire = adjacentPositions.stream() .anyMatch(p -> b.doesSquareContainEntity(p, Fire.class)); + + boolean isStuck = isStuck(); + if (hasFire) { - // Si du feu est trouvé, on éteint les feux adjacents + // Extinguish fires in adjacent positions positions.addAll(extinguish(adjacentPositions, b)); + + if (isStuck) { + // If stuck, attempt to move and extinguish after moving + positions.addAll(moveAndExtinguish(b)); + } } else { - // Chercher la position du feu le plus proche - Position nearestFirePos = b.getNearestEntity(getPosition(), Fire.class); - - if (nearestFirePos != null && !nearestFirePos.equals(getPosition())) { - // Trouver la meilleure position pour se rapprocher du feu - Position nextPos = getNextPositionTowards(getNextPositionTowards(getPosition(), nearestFirePos, b),nearestFirePos, b); - if (nextPos != null) { - // Mettre à jour la position du pompier - b.clearCaseFrom(this, getPosition()); // Vider l'ancienne case - positions.add(new Position(getPosition().x(), getPosition().y())); - setPosition(nextPos); - b.addEntityAtSquare(this, nextPos); // Mettre à jour la nouvelle case - positions.add(nextPos); - adjacentPositions = PositionUtil.generateAdjacentPositions(nextPos, b); - positions.addAll(extinguish(adjacentPositions, b)); - } - // Aucun déplacement possible = le pompier reste sur place + // No fire adjacent; move and attempt to extinguish fires + positions.addAll(moveAndExtinguish(b)); + } + + // Update last positions for stuck detection + updateLastPositions(); + + return positions; + } + + @Override + protected List<Position> moveAndExtinguish(Board<Square> b) { + List<Position> positions = new ArrayList<>(); + + // Find the nearest fire + Position nearestFirePos = b.getNearestEntity(getPosition(), Fire.class); + if (nearestFirePos != null) { + // Get the next position after moving up to two steps towards the fire + Position nextPos = getNextPositionTowards(getPosition(), nearestFirePos, b, 2); + + if (nextPos != null && !nextPos.equals(getPosition())) { + // Move the firefighter + b.clearCaseFrom(this, getPosition()); // Clear old position + positions.add(new Position(getPosition().x(), getPosition().y())); // Add old position + setPosition(nextPos); + b.addEntityAtSquare(this, nextPos); // Add to new position + positions.add(nextPos); // Add new position + + // After moving, attempt to extinguish fires adjacent to new position + List<Position> newAdjacentPositions = PositionUtil.generateAdjacentPositions(nextPos, b); + newAdjacentPositions.removeIf(p -> b.doesSquareContainEntity(p, Mountain.class)); + positions.addAll(extinguish(newAdjacentPositions, b)); } } return positions; } - public Color getViewColor(){ + + // Overloaded method to handle multiple steps + protected Position getNextPositionTowards(Position currentPos, Position targetPos, Board<Square> b, int steps) { + Position nextPos = currentPos; + + for (int i = 0; i < steps; i++) { + Position stepPos = super.getNextPositionTowards(nextPos, targetPos, b); + + if (stepPos == null || stepPos.equals(nextPos)) { + // Can't move further + break; + } + + nextPos = stepPos; + } + + return nextPos; + } + + // Override to ensure correct color + @Override + public Color getViewColor() { return this.viewColor; } -} + // Ensure the last positions are updated correctly + protected void updateLastPositions() { + if (lastThreePosition.size() >= 3) { + lastThreePosition.remove(0); + } + lastThreePosition.add(this.getPosition()); + } + +} \ No newline at end of file diff --git a/src/main/java/model/Mountain.java b/src/main/java/model/Mountain.java index 4962526..02f7fd6 100644 --- a/src/main/java/model/Mountain.java +++ b/src/main/java/model/Mountain.java @@ -1,15 +1,15 @@ package model; +import java.util.List; + import javafx.scene.paint.Color; import util.Position; -import java.util.List; - public class Mountain implements Entity{ - private final int priority = 3; + private final int priority = 0; Position position; private int age; - private final Color viewColor = Color.YELLOW; + private final Color viewColor = Color.CHOCOLATE; public Mountain(Position p ){ this.position = p; @@ -23,6 +23,7 @@ public class Mountain implements Entity{ @Override public List<Position> nextTurn(Board<Square> board) { + List<Entity> states = board.getStates(position).getEntities(); return List.of(); } diff --git a/src/main/java/util/Direction.java b/src/main/java/util/Direction.java new file mode 100644 index 0000000..471e8e7 --- /dev/null +++ b/src/main/java/util/Direction.java @@ -0,0 +1,5 @@ +package util; + +public enum Direction { + NORTH, EAST, WEST, SOUTH +} diff --git a/src/main/java/util/Matrix.java b/src/main/java/util/Matrix.java index 9fb7703..920d2a4 100644 --- a/src/main/java/util/Matrix.java +++ b/src/main/java/util/Matrix.java @@ -82,6 +82,9 @@ public class Matrix<E> implements Iterable<E> { } else if(s.getEntities().stream().anyMatch(p -> p instanceof FireFighter)){ System.out.print(" ff | "); + } + else if(s.getEntities().stream().anyMatch(p -> p instanceof FireFighter)){ + System.out.print(" A | "); }else{ System.out.print(" | "); } diff --git a/src/main/java/util/PositionUtil.java b/src/main/java/util/PositionUtil.java index 4fa6408..278bf9f 100644 --- a/src/main/java/util/PositionUtil.java +++ b/src/main/java/util/PositionUtil.java @@ -122,4 +122,37 @@ public class PositionUtil { return Math.abs(p1.x() - p2.x()) + Math.abs(p1.y() - p2.y()); } + /** + * Generates all positions within a specified radius from a center position. + * It uses Manhattan distance by default. + * + * @param center The center position. + * @param radius The radius (distance) from the center position. + * @param board The board to consider boundaries. + * @return A list of positions within the radius. + */ + public static List<Position> getPositionsInRadius(Position center, int radius, Board<Square> board) { + List<Position> positions = new ArrayList<>(); + + int startX = center.x() - radius; + int endX = center.x() + radius; + int startY = center.y() - radius; + int endY = center.y() + radius; + + for (int x = startX; x <= endX; x++) { + for (int y = startY; y <= endY; y++) { + Position pos = new Position(x, y); + if (board.doesPositionExist(pos)) { + // Calculate Manhattan distance from the center + int distance = Math.abs(center.x() - x) + Math.abs(center.y() - y); + if (distance <= radius) { + positions.add(pos); + } + } + } + } + + return positions; + } + } \ No newline at end of file -- GitLab