Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • main
  • variant
2 results

Target

Select target project
  • l22015417/firefighterstarter
  • m19023837/firefighter-starter-mansour-chadi-chahine-rami
  • r24025701/firefighterstarter
  • n24026202/firefighterstarter
  • couetoux.b/firefighterstarter
  • b23027938/firefighterstarter
  • z20039716/fire-fighter
  • a18023913/firefighterstarter
  • o22010261/firefighterstarter
  • b22015516/firefighterstarter
  • alaboure/firefighter-template
  • p21211679/firefighter-luis-parra-yanis-lounadi
  • v23014723/firefighter-project
  • k20014011/firefighter-template
  • m23022217/firefighter-template
  • p20006624/firefighter-template
  • l21221596/firefighter-template
  • s21232465/firefighter-template
  • y21224754/firefighter-template
  • w21225935/firefighter-template
  • h22023886/firefighter-template
  • b21221604/firefighter-template-boucenna-yacine-zeghar-mohamed-lamine
  • c23025119/firefighterstarter
  • b20031964/firefighterstarter
24 results
Select Git revision
  • main
  • variant
2 results
Show changes
Showing
with 1007 additions and 149 deletions
package model.Board;
import model.ElementFactory;
import model.ElementGenerator;
import model.ExtinguishFire.*;
import model.Obstacle.MountainGenerator;
import model.Obstacle.Road;
import model.Obstacle.Terrain;
import model.StrategyElement;
import model.flammable.Fire;
import model.flammable.FireStrategyElement;
import model.flammable.Rocky;
import util.Position;
import util.TargetStrategy;
import java.util.*;
import static model.flammable.Rocky.canFirePropagate;
public class BoardFireFighterBehavior implements BoardBehavior {
private static TargetStrategy targetStrategy = new TargetStrategy();
private static Map<Position, List<Position>> neighbors;
private static List<Position> rocky;
private ElementFactory<Rocky> rockyFactory;
private static Map<Position, Terrain> terrainMap = new HashMap<>();
private static int step;
static StrategyElement fireStrategyElement;
static StrategyElement fireFighterStrategyElement;
static StrategyElement cloudStrategyElement;
static StrategyElement motorizedStrategyElement;
private ElementGenerator moutainGenerator;
public BoardFireFighterBehavior(Map<Position, List<Position>> neighbors, ElementFactory<Fire> fireFactory , ElementFactory<DefaultFireFighter> firefighterFactory,
ElementFactory<Cloud> cloudFactory, ElementFactory<MotorizedFireFighter> motorizedFactory, ElementFactory<Rocky> rockyFactory) {
this.step=0;
this.neighbors = neighbors;
this.rockyFactory=rockyFactory;
fireStrategyElement =new FireStrategyElement(fireFactory);
fireFighterStrategyElement =new FireFighterStrategyElement(firefighterFactory);
cloudStrategyElement =new CloudStrategyElement(cloudFactory);
motorizedStrategyElement =new MotorizedStrategyElement(motorizedFactory);
moutainGenerator=new MountainGenerator();
}
public void initializeElements(int rowCount, int columnCount) {
fireStrategyElement.initializeElement(rowCount,columnCount);
fireFighterStrategyElement.initializeElement(rowCount,columnCount);
cloudStrategyElement.initializeElement(rowCount,columnCount);
// Pompiers motorisés
motorizedStrategyElement.initializeElement(rowCount,columnCount);
// Rocky
rocky = new ArrayList<>();
List<Rocky> rockies = rockyFactory.createElements(rowCount, columnCount);
for (Rocky rockyElement : rockies) {
rocky.add(rockyElement.getPosition());
}
moutainGenerator.generateElement(rowCount,columnCount);
generateRoads(rowCount,columnCount);
}
public static void extinguish(Position position) {
fireStrategyElement.getPositions().remove(position);
}
public Set<Position> getFirePositions() {
return (Set<Position>) fireStrategyElement.getPositions();
}
public void incrementStep() {
step++;
}
@Override
public int stepNumber() {
return step;
}
@Override
public List<Position> updateToNextGeneration() {
List<Position> modifiedPositions = fireFighterStrategyElement.updateElements();
modifiedPositions.addAll(fireStrategyElement.updateElements());
modifiedPositions.addAll(cloudStrategyElement.updateElements());
modifiedPositions.addAll(motorizedStrategyElement.updateElements());
incrementStep();
return modifiedPositions;
}
@Override
public void reset() {
this.step=0;
// Vider toutes les positions stockées
fireStrategyElement.getPositions().clear();
fireFighterStrategyElement.getPositions().clear();
cloudStrategyElement.getPositions().clear();
motorizedStrategyElement.getPositions().clear();
rocky.clear();
terrainMap.clear();
}
/**
* Éteint les feux à proximité d'une position donnée.
*
* @param firefighterPosition La position actuelle du pompier.
* @param modifiedPositions Les positions modifiées pendant ce tour.
*/
public static void extinguishNearbyFires(Position firefighterPosition, List<Position> modifiedPositions) {
List<Position> nearbyFires = getNeighbors().getOrDefault(firefighterPosition, Collections.emptyList())
.stream()
.filter(fireStrategyElement.getPositions()::contains)
.toList();
for (Position fire : nearbyFires) {
fireStrategyElement.getPositions().remove(fire);
modifiedPositions.add(fire);
System.out.println("Feu éteint à : " + fire);
}
}
public static Map<Position, Terrain> getTerrainMap() {
return terrainMap;
}
public static boolean canMoveTo(Position position, Set<Position> firePositions, List<Position> firefighterPositions) {
// Vérifie si la position est hors des limites (par exemple, en dehors de la grille ou inaccessible)
if (!neighbors.containsKey(position)) {
return false;
}
// Si la position est occupée par un feu et que le terrain n'est pas traversable par le feu
if(cloudStrategyElement.getPositions().contains(position))
{
return false;
}
// Si la position est une montagne, aucun élément ne peut la franchir sauf les nuages
if (terrainMap.get(position) != null && !cloudStrategyElement.getPositions().contains(position)) {
return false; // Impossible de franchir une montagne, sauf pour un nuage
}
if(rocky.contains(position))
{
rocky.remove(position);
return canFirePropagate();
}
return true; // La position est traversable
}
private void generateRoads(int rowCount, int columnCount) {
Random random = new Random();
// Définir les bords de départ et d'arrivée
int startRow = random.nextInt(rowCount); // Bord gauche
int endRow = random.nextInt(rowCount); // Bord droit
int startCol = 0; // Bord gauche (colonne 0)
int endCol = columnCount - 1; // Bord droit (dernière colonne)
// Générer une route connectant ces deux points
List<Position> path = createPath(new Position(startRow, startCol), new Position(endRow, endCol));
// Placer la route dans la grille
for (Position pos : path) {
if (!terrainMap.containsKey(pos)) { // Éviter les obstacles
terrainMap.put(pos, new Road(pos));
}
}
}
/**
* Génère un chemin connectant deux positions.
*/
private List<Position> createPath(Position start, Position end) {
List<Position> path = new ArrayList<>();
int currentRow = start.row();
int currentCol = start.column();
// Algorithme simple de connexion entre les points (chemin en "zigzag")
while (currentRow != end.row() || currentCol != end.column()) {
path.add(new Position(currentRow, currentCol));
// Mouvement vertical
if (currentRow < end.row()) {
currentRow++;
} else if (currentRow > end.row()) {
currentRow--;
}
// Mouvement horizontal
if (currentCol < end.column()) {
currentCol++;
} else if (currentCol > end.column()) {
currentCol--;
}
}
// Ajouter la position finale
path.add(end);
return path;
}
public static List<Position> getRocky() {
return rocky;
}
public static int getStep() {
return step;
}
public static Map<Position, List<Position>> getNeighbors() {
return neighbors;
}
public static TargetStrategy getTargetStrategy() {
return targetStrategy;
}
public static Collection<Position> getFirefighterPositions() {
return fireFighterStrategyElement.getPositions();
}
public Collection<Position> getCloudPositions() {
return cloudStrategyElement.getPositions();
}
public List<Position> getMotorizedFighters() {
return (List<Position>) motorizedStrategyElement.getPositions();
}
public static StrategyElement getFireMovements() {
return fireStrategyElement;
}
}
package model.Board;
import util.Position;
public class BoardFirefighterProperties implements BoardProperties {
private final int rowCount;
private final int columnCount;
private final Position[][] positions;
public BoardFirefighterProperties(int rowCount, int columnCount) {
this.rowCount = rowCount;
this.columnCount = columnCount;
this.positions = new Position[rowCount][columnCount];
initializePositions();
}
private void initializePositions() {
for (int row = 0; row < rowCount; row++) {
for (int column = 0; column < columnCount; column++) {
positions[row][column] = new Position(row, column);
}
}
}
public Position getPosition(int row, int column) {
return positions[row][column];
}
@Override
public int rowCount() {
return rowCount;
}
@Override
public int columnCount() {
return columnCount;
}
}
package model.Board;
/**
* Interface représentant les propriétés d'un tableau générique pour la gestion de l'état.
*
* @param <S> Le type d'état utilisé pour les éléments du tableau.
*/
public interface BoardProperties<S> {
/**
* Retourne le nombre de lignes du tableau.
*
* @return Le nombre de lignes.
*/
int rowCount(); // Nombre de lignes.
/**
* Retourne le nombre de colonnes du tableau.
*
* @return Le nombre de colonnes.
*/
int columnCount(); // Nombre de colonnes.
}
package model.Board;
import model.ExtinguishFire.*;
import model.ModelElement;
import model.Obstacle.Mountain;
import model.Obstacle.Road;
import model.flammable.Fire;
import model.flammable.FireFactory;
import model.flammable.Rocky;
import model.flammable.RockyFactory;
import util.Position;
import java.util.*;
public class FirefighterBoard implements Board<List<ModelElement>> {
private final BoardFireFighterBehavior behavior;
private final BoardFirefighterProperties properties;
private final Random randomGenerator = new Random();
public FirefighterBoard(int columnCount, int rowCount, int initialFireCount, int initialFirefighterCount,int initialCloud,int initialMotorized,
int initialRocky) {
Map<Position, List<Position>> neighbors = initializeNeighbors(rowCount, columnCount);
this.properties = new BoardFirefighterProperties(rowCount, columnCount);
this.behavior = new BoardFireFighterBehavior(neighbors,new FireFactory(randomGenerator,initialFireCount),new FirefighterFactory(randomGenerator,initialFirefighterCount),
new CloudFactory(randomGenerator,initialCloud),new MotorizedFactory(randomGenerator,initialMotorized),new RockyFactory(randomGenerator,initialRocky));
behavior.initializeElements( properties.rowCount(), properties.columnCount());
}
private Map<Position, List<Position>> initializeNeighbors(int rowCount, int columnCount) {
Map<Position, List<Position>> neighbors = new HashMap<>();
Position[][] positions = new Position[rowCount][columnCount];
for (int row = 0; row < rowCount; row++) {
for (int column = 0; column < columnCount; column++) {
positions[row][column] = new Position(row, column);
}
}
for (int row = 0; row < rowCount; row++) {
for (int column = 0; column < columnCount; column++) {
List<Position> list = new ArrayList<>();
if (row > 0) list.add(positions[row - 1][column]);
if (column > 0) list.add(positions[row][column - 1]);
if (row < rowCount - 1) list.add(positions[row + 1][column]);
if (column < columnCount - 1) list.add(positions[row][column + 1]);
neighbors.put(positions[row][column], list);
}
}
return neighbors;
}
public List<ModelElement> getState(Position position) {
List<ModelElement> result = new ArrayList<>();
// Filtrage des éléments Fire (en transformant les positions en objets Fire)
behavior.getFirePositions().stream()
.filter(pos -> pos.isAtPosition(position)) // Vérifier si la position correspond
.forEach(pos -> result.add(new Fire(pos))); // Créer un objet Fire à partir de Position
// Filtrage des éléments Firefighter (en transformant les positions en objets FireFighter)
behavior.getFirefighterPositions().stream()
.filter(pos -> pos.isAtPosition(position)) // Vérifier si la position correspond
.forEach(pos -> result.add(new DefaultFireFighter(pos))); // Créer un objet Firefighter à partir de Position
// Filtrage des éléments Cloud
behavior.getCloudPositions().stream()
.filter(pos -> pos.isAtPosition(position))
.forEach(pos -> result.add(new Cloud(pos)));
// Filtrage des éléments Motorized
behavior.getMotorizedFighters().stream()
.filter(pos -> pos.isAtPosition(position))
.forEach(pos -> result.add(new MotorizedFireFighter(pos)));
behavior.getTerrainMap().forEach((pos, value) -> {
if (pos.isAtPosition(position) && value instanceof Mountain) {
result.add((Mountain) value); // Ajouter uniquement un objet Mountain
}
});
behavior.getTerrainMap().forEach((pos, value) -> {
if (pos.isAtPosition(position) && value instanceof Road) {
result.add((Road) value); // Ajouter uniquement un objet Mountain
}
});
// Filtrage des éléments Rocky
behavior.getRocky().stream()
.filter(pos -> pos.isAtPosition(position))
.forEach(pos -> result.add(new Rocky(pos)));
return result;
}
public void reset() {
behavior.reset();
behavior.initializeElements(properties.rowCount(), properties.columnCount());
}
public void setState(List<ModelElement> state, Position position) {
// Pour chaque élément dans l'état, on l'ajoute sur le plateau
state.forEach(element -> addElementToBoard(element, position));
}
private void addElementToBoard(ModelElement element, Position position) {
if (element instanceof Fire) {
behavior.getFirePositions().add(position); // Ajouter un Fire
} else if (element instanceof DefaultFireFighter) {
behavior.getFirefighterPositions().add(position); // Ajouter un Firefighter
} else if (element instanceof Cloud) {
behavior.getCloudPositions().add(position);
} else if (element instanceof MotorizedFireFighter) {
behavior.getMotorizedFighters().add(position);
}else if(element instanceof Rocky)
{
behavior.getRocky().add(position);
}
}
public BoardFireFighterBehavior getBehavior() {
return behavior;
}
public BoardFirefighterProperties getProperties() {
return properties;
}
}
package model;
import java.util.List;
public interface ElementFactory<T extends ModelElement> {
List<T> createElements(int rowCount, int columnCount);
int getCount();
}
package model;
public interface ElementGenerator {
public void generateElement(int rowCount, int columnCount);
}
package model.ExtinguishFire;
import model.Board.BoardElement;
import util.Position;
public class Cloud extends BoardElement {
public Cloud(Position position) {
super(position);
}
@Override
public String getType() {
return "CLOUD";
}
@Override
public String toString() {
return "Cloud at " + position;
}
}
package model.ExtinguishFire;
import model.ElementFactory;
import model.PositionGenerator;
import util.Position;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class CloudFactory implements ElementFactory<Cloud>, PositionGenerator {
private final Random random;
private final int count;
public CloudFactory(Random random, int count) {
this.random = random;
this.count = count;
}
@Override
public List<Cloud> createElements(int rowCount, int columnCount) {
List<Cloud> clouds = new ArrayList<>();
for (int i = 0; i < count; i++) {
Position position = generateRandomPosition(rowCount, columnCount);
clouds.add(new Cloud(position));
}
return clouds;
}
@Override
public int getCount() {
return 0;
}
@Override
public Position generateRandomPosition(int rowCount, int columnCount) {
int row = random.nextInt(rowCount);
int col = random.nextInt(columnCount);
return new Position(row, col);
}
}
package model.ExtinguishFire;
import model.ElementFactory;
import model.StrategyElement;
import util.Position;
import java.util.*;
import static model.Board.BoardFireFighterBehavior.*;
public class CloudStrategyElement implements StrategyElement {
private List<Position> cloudPositions;
private final ElementFactory<Cloud> cloudFactory;
public CloudStrategyElement(ElementFactory<Cloud> cloudFactory) {
this.cloudPositions = new ArrayList<>();
this.cloudFactory = cloudFactory;
}
@Override
public void initializeElement(int rowCount, int columnCount) {
// Nuages
cloudPositions = new ArrayList<>();
List<Cloud> clouds = cloudFactory.createElements(rowCount, columnCount);
for (Cloud cloud : clouds) {
cloudPositions.add(cloud.getPosition());
}
}
@Override
public List<Position> updateElements() {
List<Position> modifiedPositions = new ArrayList<>();
List<Position> newCloudPositions = new ArrayList<>();
// Copier les positions actuelles des feux pour éviter les incohérences pendant l'itération
Set<Position> firePositions = new HashSet<>(getFireMovements().getPositions());
for (Position cloudPosition : cloudPositions) {
// Déplacement aléatoire parmi les voisins
List<Position> possibleMoves = getNeighbors().get(cloudPosition);
Position newCloudPosition = possibleMoves.get(new Random().nextInt(possibleMoves.size()));
// Vérification que le nuage ne se déplace pas vers une montagne ou une position invalide
if (!canMoveTo(newCloudPosition, firePositions, (List<Position>) getFirefighterPositions())) {
newCloudPositions.add(cloudPosition); // Le nuage reste sur place
continue;
}
// Ajouter la nouvelle position du nuage
newCloudPositions.add(newCloudPosition);
// Si la nouvelle position contient un feu, l'éteindre
if (firePositions.contains(newCloudPosition)) {
extinguish(newCloudPosition); // Extinction du feu
firePositions.remove(newCloudPosition); // Mise à jour locale des positions des feux
modifiedPositions.add(newCloudPosition);
System.out.println("Feu éteint par un nuage à : " + newCloudPosition);
}
// Ajouter les positions modifiées pour le nuage
modifiedPositions.add(cloudPosition);
modifiedPositions.add(newCloudPosition);
}
// Mise à jour des positions des nuages
cloudPositions = newCloudPositions;
return modifiedPositions;
}
@Override
public Collection<Position> getPositions() {
return cloudPositions;
}
}
package model.ExtinguishFire;
import util.Position;
public class DefaultFireFighter extends FireFighter{
public DefaultFireFighter(Position position) {
super(position);
}
}
package model.ExtinguishFire;
import model.Board.BoardElement;
import util.Position;
public abstract class FireFighter extends BoardElement {
public FireFighter(Position position) {
super(position);
}
@Override
public String getType() {
return "FIREFIGHTER";
}
@Override
public String toString() {
return "Firefighter at " + position;
}
}
package model.ExtinguishFire;
import model.ElementFactory;
import model.StrategyElement;
import util.Position;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static model.Board.BoardFireFighterBehavior.*;
public class FireFighterStrategyElement implements StrategyElement {
private final ElementFactory<DefaultFireFighter> firefighterFactory;
private List<Position> firefighterPositions;
public FireFighterStrategyElement(ElementFactory<DefaultFireFighter> firefighterFactory) {
this.firefighterFactory = firefighterFactory;
this.firefighterPositions = new ArrayList<>();
}
@Override
public List<Position> updateElements() {
List<Position> modifiedPositions = new ArrayList<>();
List<Position> newFirefighterPositions = new ArrayList<>();
for (Position firefighterPosition : firefighterPositions) {
// Calcul de la position vers laquelle le pompier devrait se déplacer
Position newFirefighterPosition =getTargetStrategy().neighborClosestToTarget(firefighterPosition, getFireMovements().getPositions(), getNeighbors());
// Vérification si la position cible est valide pour le mouvement
if (canMoveTo(newFirefighterPosition, (Set<Position>) getFireMovements().getPositions(), firefighterPositions)) {
// Si le déplacement est valide, on met à jour la position du pompier
newFirefighterPositions.add(newFirefighterPosition);
// Éteindre le feu à la nouvelle position
extinguish(newFirefighterPosition);
modifiedPositions.add(firefighterPosition);
modifiedPositions.add(newFirefighterPosition);
// Vérification des voisins et extinction des feux voisins
List<Position> neighborFirePositions = getNeighbors().get(newFirefighterPosition).stream()
.filter(getFireMovements().getPositions()::contains).toList();
// Log pour débogage
System.out.println("Pompiers se déplacent de " + firefighterPosition + " vers " + newFirefighterPosition);
// Éteindre les feux voisins
for (Position firePosition : neighborFirePositions) {
extinguish(firePosition);
modifiedPositions.add(firePosition); // Ajout des feux éteints dans la liste des positions modifiées
}
} else {
// Si la position n'est pas valide, le pompier reste sur place
newFirefighterPositions.add(firefighterPosition);
System.out.println("Pompier ne peut pas se déplacer à " + newFirefighterPosition + ", il reste à " + firefighterPosition);
}
}
// Mettre à jour la liste des positions des pompiers
firefighterPositions = newFirefighterPositions;
return modifiedPositions;
}
@Override
public void initializeElement(int rowCount, int columnCount) {
// Pompiers
firefighterPositions = new ArrayList<>();
List<DefaultFireFighter> firefighters = firefighterFactory.createElements(rowCount, columnCount);
for (FireFighter firefighter : firefighters) {
firefighterPositions.add(firefighter.getPosition());
}
}
@Override
public Collection<Position> getPositions() {
return firefighterPositions;
}
}
package model.ExtinguishFire;
import model.ElementFactory;
import model.PositionGenerator;
import util.Position;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class FirefighterFactory implements ElementFactory<DefaultFireFighter>, PositionGenerator {
private final Random random;
private int count;
public FirefighterFactory(Random random,int count) {
this.random = random;
this.count=count;
}
@Override
public List<DefaultFireFighter> createElements(int rowCount, int columnCount) {
List<DefaultFireFighter> firefighters = new ArrayList<>();
for (int i = 0; i < count; i++) {
Position randomPosition = generateRandomPosition(rowCount, columnCount);
firefighters.add(new DefaultFireFighter(randomPosition));
}
return firefighters;
}
@Override
public Position generateRandomPosition(int rowCount, int columnCount) {
int row = random.nextInt(rowCount);
int column = random.nextInt(columnCount);
return new Position(row, column);
}
public int getCount() {
return count;
}
}
package model.ExtinguishFire;
import model.ElementFactory;
import model.PositionGenerator;
import util.Position;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class MotorizedFactory implements ElementFactory<MotorizedFireFighter>, PositionGenerator {
private final Random random;
private int count;
public MotorizedFactory(Random random, int count) {
this.random = random;
this.count = count;
}
@Override
public List<MotorizedFireFighter> createElements(int rowCount, int columnCount) {
List<MotorizedFireFighter> firefighters = new ArrayList<>();
for (int i = 0; i < count; i++) {
Position randomPosition = generateRandomPosition(rowCount, columnCount);
firefighters.add(new MotorizedFireFighter(randomPosition));
}
return firefighters;
}
@Override
public Position generateRandomPosition(int rowCount, int columnCount) {
int row = random.nextInt(rowCount);
int column = random.nextInt(columnCount);
return new Position(row, column);
}
public int getCount() {
return count;
}
}
package model.ExtinguishFire;
import model.Board.BoardElement;
import util.Position;
import util.TargetStrategy;
import java.util.*;
public class MotorizedFireFighter extends FireFighter{
private final TargetStrategy targetStrategy = new TargetStrategy();
public MotorizedFireFighter(Position position) {
super(position);
}
@Override
public String getType() {
return "MotorizedFireFighter";
}
@Override
public String toString() {
return null;
}
/**
* Déplace le pompier motorisé en deux étapes maximum vers un feu.
*
* @param firePositions Les positions des feux.
* @param neighbors Les positions voisines accessibles.
* @return La nouvelle position du pompier.
*/
public Position move(Set<Position> firePositions, Map<Position, List<Position>> neighbors) {
// Première étape
Position firstStep = targetStrategy.neighborClosestToTarget(getPosition(), firePositions, neighbors);
if (firstStep == null) {
return getPosition(); // Aucun déplacement possible
}
// Deuxième étape
Position secondStep = targetStrategy.neighborClosestToTarget(firstStep, firePositions, neighbors);
// Mise à jour de la position
Position newPosition = (secondStep != null) ? secondStep : firstStep;
setPosition(newPosition); // Mettre à jour la position interne
return newPosition;
}
}
package model.ExtinguishFire;
import model.ElementFactory;
import model.StrategyElement;
import util.Position;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static model.Board.BoardFireFighterBehavior.*;
public class MotorizedStrategyElement implements StrategyElement {
private final ElementFactory<MotorizedFireFighter> motorizedFactory;
private List<Position> motorizedFighters;
public MotorizedStrategyElement(ElementFactory<MotorizedFireFighter> motorizedFactory) {
this.motorizedFactory = motorizedFactory;
this.motorizedFighters = new ArrayList<>();
}
@Override
public List<Position> updateElements() {
List<Position> modifiedPositions = new ArrayList<>();
List<Position> newPositions = new ArrayList<>();
for (Position currentPosition : motorizedFighters) {
// Vérification de validité de la position actuelle
if (!getNeighbors().containsKey(currentPosition)) {
System.err.println("Position actuelle invalide : " + currentPosition);
newPositions.add(currentPosition);
continue;
}
// Étape 1 : Calcul du premier déplacement
Position firstStep = getTargetStrategy().neighborClosestToTarget(currentPosition, getFireMovements().getPositions(), getNeighbors());
if (firstStep == null || !getNeighbors().containsKey(firstStep)) {
// Aucun déplacement possible, rester sur place
System.out.println("Pas de première étape possible pour : " + currentPosition);
newPositions.add(currentPosition);
continue;
}
// Étape 2 : Calcul du deuxième déplacement
Position secondStep = getTargetStrategy().neighborClosestToTarget(firstStep, getFireMovements().getPositions(), getNeighbors());
Position finalPosition = (secondStep != null && getNeighbors().containsKey(secondStep)) ? secondStep : firstStep;
// Ajout de la position finale aux nouvelles positions
newPositions.add(finalPosition);
// Mise à jour des positions modifiées
modifiedPositions.add(currentPosition); // Ancienne position
modifiedPositions.add(finalPosition); // Nouvelle position
// Étape 3 : Éteindre les feux à la position finale
extinguish(finalPosition);
extinguishNearbyFires(finalPosition, modifiedPositions);
}
// Mettre à jour les positions globales
motorizedFighters = newPositions;
return modifiedPositions;
}
@Override
public void initializeElement(int rowCount, int columnCount) {
motorizedFighters = new ArrayList<>();
List<MotorizedFireFighter> motorizedFirefighters = motorizedFactory.createElements(rowCount, columnCount);
for (MotorizedFireFighter motorizedFirefighter : motorizedFirefighters) {
motorizedFighters.add(motorizedFirefighter.getPosition());
}
}
@Override
public Collection<Position> getPositions() {
return this.motorizedFighters;
}
}
package model;
import util.Position;
import java.util.*;
public class FirefighterBoard implements Board<List<ModelElement>> {
private final int columnCount;
private final int rowCount;
private final int initialFireCount;
private final int initialFirefighterCount;
private final TargetStrategy targetStrategy = new TargetStrategy();
private List<Position> firefighterPositions;
private Set<Position> firePositions;
private Map<Position, List<Position>> neighbors = new HashMap();
private final Position[][] positions;
private int step = 0;
private final Random randomGenerator = new Random();
public FirefighterBoard(int columnCount, int rowCount, int initialFireCount, int initialFirefighterCount) {
this.columnCount = columnCount;
this.rowCount = rowCount;
this.positions = new Position[rowCount][columnCount];
for (int column = 0; column < columnCount; column++)
for (int row = 0; row < rowCount; row++)
positions[row][column] = new Position(row, column);
for (int column = 0; column < columnCount; column++)
for (int row = 0; row < rowCount; row++) {
List<Position> list = new ArrayList<>();
if (row > 0) list.add(positions[row - 1][column]);
if (column > 0) list.add(positions[row][column - 1]);
if (row < rowCount - 1) list.add(positions[row + 1][column]);
if (column < columnCount - 1) list.add(positions[row][column + 1]);
neighbors.put(positions[row][column], list);
}
this.initialFireCount = initialFireCount;
this.initialFirefighterCount = initialFirefighterCount;
initializeElements();
}
public void initializeElements() {
firefighterPositions = new ArrayList<>();
firePositions = new HashSet<>();
for (int index = 0; index < initialFireCount; index++)
firePositions.add(randomPosition());
for (int index = 0; index < initialFirefighterCount; index++)
firefighterPositions.add(randomPosition());
}
private Position randomPosition() {
return new Position(randomGenerator.nextInt(rowCount), randomGenerator.nextInt(columnCount));
}
@Override
public List<ModelElement> getState(Position position) {
List<ModelElement> result = new ArrayList<>();
for (Position firefighterPosition : firefighterPositions)
if (firefighterPosition.equals(position))
result.add(ModelElement.FIREFIGHTER);
if (firePositions.contains(position))
result.add(ModelElement.FIRE);
return result;
}
@Override
public int rowCount() {
return rowCount;
}
@Override
public int columnCount() {
return columnCount;
}
public List<Position> updateToNextGeneration() {
List<Position> modifiedPositions = updateFirefighters();
modifiedPositions.addAll(updateFires());
step++;
return modifiedPositions;
}
private List<Position> updateFires() {
List<Position> modifiedPositions = new ArrayList<>();
if (step % 2 == 0) {
List<Position> newFirePositions = new ArrayList<>();
for (Position fire : firePositions) {
newFirePositions.addAll(neighbors.get(fire));
}
firePositions.addAll(newFirePositions);
modifiedPositions.addAll(newFirePositions);
}
return modifiedPositions;
}
@Override
public int stepNumber() {
return step;
}
private List<Position> updateFirefighters() {
List<Position> modifiedPosition = new ArrayList<>();
List<Position> firefighterNewPositions = new ArrayList<>();
for (Position firefighterPosition : firefighterPositions) {
Position newFirefighterPosition =
targetStrategy.neighborClosestToFire(firefighterPosition,
firePositions, neighbors);
firefighterNewPositions.add(newFirefighterPosition);
extinguish(newFirefighterPosition);
modifiedPosition.add(firefighterPosition);
modifiedPosition.add(newFirefighterPosition);
List<Position> neighborFirePositions = neighbors.get(newFirefighterPosition).stream()
.filter(firePositions::contains).toList();
for (Position firePosition : neighborFirePositions)
extinguish(firePosition);
modifiedPosition.addAll(neighborFirePositions);
}
firefighterPositions = firefighterNewPositions;
return modifiedPosition;
}
@Override
public void reset() {
step = 0;
initializeElements();
}
private void extinguish(Position position) {
firePositions.remove(position);
}
@Override
public void setState(List<ModelElement> state, Position position) {
firePositions.remove(position);
for (; ; ) {
if (!firefighterPositions.remove(position)) break;
}
for (ModelElement element : state) {
switch (element) {
case FIRE -> firePositions.add(position);
case FIREFIGHTER -> firefighterPositions.add(position);
}
}
}
}
\ No newline at end of file
package model;
public enum ModelElement {
FIREFIGHTER, FIRE
import util.Position;
public interface ModelElement {
public Position getPosition();
}
package model.Obstacle;
import model.Board.BoardElement;
import util.Position;
public class Mountain extends BoardElement implements Terrain {
public Mountain(Position position) {
super(position);
}
@Override
public String getType() {
return null;
}
@Override
public String toString() {
return null;
}
@Override
public boolean isTraversableByFire() {
return false; // Les montagnes ne sont pas franchissables par le feu
}
@Override
public boolean isTraversableByFirefighter() {
return false; // Les pompiers ne peuvent pas passer non plus
}
}
package model.Obstacle;
import model.ElementGenerator;
import util.Position;
import java.util.Random;
import static model.Board.BoardFireFighterBehavior.getTerrainMap;
public class MountainGenerator implements ElementGenerator {
@Override
public void generateElement(int rowCount, int columnCount) {
Random random = new Random();
int maxMountains = 5; // Par exemple, générer 5 blocs de montagnes
int blockSize = 4; // Taille du bloc de montagnes (4 cases)
for (int i = 0; i < maxMountains; i++) {
// Générer un coin aléatoire pour chaque bloc de montagne (en s'assurant que les blocs ne dépassent pas la grille)
int startRow = random.nextInt(rowCount - 1); // -1 pour éviter le débordement
int startCol = random.nextInt(columnCount - 1);
// Vérifier si les cases sont libres avant d'y placer une montagne
if (canPlaceMountainBlock(startRow, startCol)) {
// Placer les montagnes sur la grille
placeMountainBlock(startRow, startCol);
}
}
}
private boolean canPlaceMountainBlock(int startRow, int startCol) {
// Vérifier si les 4 cases sont libres
for (int row = startRow; row < startRow + 2; row++) {
for (int col = startCol; col < startCol + 2; col++) {
Position pos = new Position(row, col);
if (getTerrainMap().containsKey(pos)) {
return false; // Une case est déjà occupée
}
}
}
return true; // Toutes les cases sont libres
}
private void placeMountainBlock(int startRow, int startCol) {
// Placer les 4 cases de montagne
for (int row = startRow; row < startRow + 2; row++) {
for (int col = startCol; col < startCol + 2; col++) {
Position pos = new Position(row, col);
getTerrainMap().put(pos, new Mountain(pos));
}
}
}
}