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
No results found
Select Git revision
  • main
  • variant
2 results
Show changes
70 files
+ 846
198
Compare changes
  • Side-by-side
  • Inline

Files

+142 −0
Original line number Diff line number Diff line
.background {
    -fx-background-color: #1d1d1d;
}

.label {
    -fx-font-size: 11pt;
    -fx-font-family: "Segoe UI Semibold";
    -fx-text-fill: white;
    -fx-opacity: 0.6;
}

.label-bright {
    -fx-font-size: 11pt;
    -fx-font-family: "Segoe UI Semibold";
    -fx-text-fill: white;
    -fx-opacity: 1;
}

.label-header {
    -fx-font-size: 32pt;
    -fx-font-family: "Segoe UI Light";
    -fx-text-fill: white;
    -fx-opacity: 1;
}

.table-view {
    -fx-base: #1d1d1d;
    -fx-control-inner-background: #1d1d1d;
    -fx-background-color: #1d1d1d;
    -fx-table-cell-border-color: transparent;
    -fx-table-header-border-color: transparent;
    -fx-padding: 5;
}

.table-view .column-header-background {
    -fx-background-color: transparent;
}

.table-view .column-header, .table-view .filler {
    -fx-border-width: 0 0 1 0;
    -fx-background-color: transparent;
    -fx-border-color: 
        transparent
        transparent
        derive(-fx-base, 80%) 
        transparent;
    -fx-border-insets: 0 10 1 0;
}

.table-view .column-header .label {
    -fx-font-size: 20pt;
    -fx-font-family: "Segoe UI Light";
    -fx-text-fill: white;
    -fx-alignment: center-left;
    -fx-opacity: 1;
}

.table-view:focused .table-row-cell:filled:focused:selected {
    -fx-background-color: -fx-focus-color;
}

.split-pane:horizontal > .split-pane-divider {
    -fx-border-color: transparent #1d1d1d transparent #1d1d1d;
    -fx-background-color: transparent, derive(#1d1d1d,20%);
}

.split-pane {
    -fx-padding: 1 0 0 0;
}

.menu-bar {
    -fx-background-color: derive(#1d1d1d,20%);
}

.context-menu {
    -fx-background-color: derive(#1d1d1d,50%);
}

.menu-bar .label {
    -fx-font-size: 14pt;
    -fx-font-family: "Segoe UI Light";
    -fx-text-fill: white;
    -fx-opacity: 0.9;
}

.menu .left-container {
    -fx-background-color: black;
}

.text-field {
    -fx-font-size: 12pt;
    -fx-font-family: "Segoe UI Semibold";
}

/* 
 * Metro style Push Button
 * Author: Pedro Duque Vieira
 * http://pixelduke.wordpress.com/2012/10/23/jmetro-windows-8-controls-on-java/
 */
.button {
    -fx-padding: 5 22 5 22;   
    -fx-border-color: #e2e2e2;
    -fx-border-width: 2;
    -fx-background-radius: 0;
    -fx-background-color: #1d1d1d;
    -fx-font-family: "Segoe UI", Helvetica, Arial, sans-serif;
    -fx-font-size: 11pt;
    -fx-text-fill: #d8d8d8;
    -fx-background-insets: 0 0 0 0, 0, 1, 2;
}

.button:hover {
    -fx-background-color: #3a3a3a;
}

.button:pressed, .button:default:hover:pressed {
  -fx-background-color: white;
  -fx-text-fill: #1d1d1d;
}

.button:focused {
    -fx-border-color: white, white;
    -fx-border-width: 1, 1;
    -fx-border-style: solid;
    -fx-border-radius: 0, 0;
    -fx-border-insets: 1 1 1 1, 0;
}

.button:disabled, .button:default:disabled {
    -fx-opacity: 0.4;
    -fx-background-color: #1d1d1d;
    -fx-text-fill: white;
}

.button:default {
    -fx-background-color: -fx-focus-color;
    -fx-text-fill: #ffffff;
}

.button:default:hover {
    -fx-background-color: derive(-fx-focus-color,30%);
}
 No newline at end of file
+40 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import view.FirefighterGrid?>

<?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.Label?>
<HBox styleClass="background" stylesheets="@DarkTheme.css"
      xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
      fx:controller="controller.Controller" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity">
  <VBox>
    <Separator maxHeight="-Infinity" maxWidth="-Infinity"
               prefHeight="24.0" prefWidth="200.0"/>
    <Label maxHeight="-Infinity" maxWidth="-Infinity" alignment="CENTER" prefHeight="24.0" prefWidth="200.0"
           text="Generation number"/>
    <Label fx:id="generationNumberLabel" alignment="CENTER" contentDisplay="TEXT_ONLY"
           maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="24.0" prefWidth="200.0"/>
    <Separator maxHeight="-Infinity" maxWidth="-Infinity"
               prefHeight="24.0" prefWidth="200.0"/>
    <Button fx:id="restartButton" maxHeight="-Infinity" maxWidth="-Infinity"
            mnemonicParsing="false" onAction="#restartButtonAction" prefHeight="24.0" prefWidth="200.0"
            text="Restart"/>
    <Button fx:id="oneStepButton" maxHeight="-Infinity" maxWidth="-Infinity"
            mnemonicParsing="false" onAction="#oneStepButtonAction" prefHeight="24.0" prefWidth="200.0"
            text="One step"/>
    <ToggleButton fx:id="playToggleButton" maxHeight="-Infinity" maxWidth="-Infinity"
                  mnemonicParsing="false" onAction="#playToggleButtonAction" prefHeight="24.0"
                  prefWidth="200.0" styleClass="button" text="Play"/>
    <ToggleButton fx:id="pauseToggleButton" maxHeight="-Infinity" maxWidth="-Infinity"
                  mnemonicParsing="false" onAction="#pauseToggleButtonAction" prefHeight="24.0"
                  prefWidth="200.0" styleClass="button" text="Pause"/>
  </VBox>
  <FirefighterGrid fx:id="grid"
                   xmlns="http://javafx.com/javafx"
                   xmlns:fx="http://javafx.com/fxml">
  </FirefighterGrid>
</HBox>
Original line number Diff line number Diff line
@@ -18,7 +18,8 @@ public class SimulatorApplication extends javafx.application.Application {
  private static final int BOX_WIDTH = 50;
  private static final int BOX_HEIGHT = 50;
  public static final int INITIAL_FIRE_COUNT = 3;
  public static final int INITIAL_FIREFIGHTER_COUNT = 6;
  public static final int INITIAL_FIREFIGHTER_COUNT = 0;
  public static final int INITIAL_CLOUD_COUNT = 3;

  private Stage primaryStage;
  private Parent view;
@@ -44,7 +45,7 @@ public class SimulatorApplication extends javafx.application.Application {
    view = loader.load();
    Controller controller = loader.getController();
    controller.initialize(BOX_WIDTH, BOX_HEIGHT, COLUMN_COUNT, ROW_COUNT,
            INITIAL_FIRE_COUNT, INITIAL_FIREFIGHTER_COUNT);
            INITIAL_FIRE_COUNT, INITIAL_FIREFIGHTER_COUNT,INITIAL_CLOUD_COUNT);
  }

  private void showScene() {
Original line number Diff line number Diff line
@@ -4,4 +4,5 @@ public class SimulatorMain {
  public static void main(String[] args){
    SimulatorApplication.main(args);
  }

}
Original line number Diff line number Diff line
@@ -12,9 +12,7 @@ import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.util.Duration;
import javafx.util.Pair;
import model.Board;
import model.ModelElement;
import model.FirefighterBoard;
import model.*;
import util.Position;
import view.Grid;
import view.ViewElement;
@@ -40,7 +38,7 @@ public class Controller {
  @FXML
  private Grid<ViewElement> grid;
  private Timeline timeline;
  private Board<List<ModelElement>> board;
  private FirefighterBoard board;

  @FXML
  private void initialize() {
@@ -59,7 +57,7 @@ public class Controller {
  }

  private void updateBoard(){
    List<Position> updatedPositions = board.updateToNextGeneration();
    List<Position> updatedPositions = board.getBehavior().updateToNextGeneration();
    List<Pair<Position, ViewElement>> updatedSquares = new ArrayList<>();
    for(Position updatedPosition : updatedPositions){
      List<ModelElement> squareState = board.getState(updatedPosition);
@@ -67,30 +65,36 @@ public class Controller {
      updatedSquares.add(new Pair<>(updatedPosition, viewElement));
    }
    grid.repaint(updatedSquares);
    updateGenerationLabel(board.stepNumber());
    updateGenerationLabel(board.getBehavior().stepNumber());
  }

  private void repaintGrid(){
    int columnCount = board.columnCount();
    int rowCount = board.rowCount();
    int columnCount = board.getProperties().columnCount();
    int rowCount = board.getProperties().rowCount();
    ViewElement[][] viewElements = new ViewElement[rowCount][columnCount];
    for(int column = 0; column < columnCount; column++)
      for(int row = 0; row < rowCount; row++)
        viewElements[row][column] = getViewElement(board.getState(new Position(row, column)));
    grid.repaint(viewElements);
    updateGenerationLabel(board.stepNumber());
    updateGenerationLabel(board.getBehavior().stepNumber());
  }

  private ViewElement getViewElement(List<ModelElement> squareState) {
    if(squareState.contains(ModelElement.FIREFIGHTER)){
    for (ModelElement element : squareState) {
      if (element instanceof FireFighter) {
        return ViewElement.FIREFIGHTER;
      }
    if (squareState.contains(ModelElement.FIRE)){
      if (element instanceof Fire) {
        return ViewElement.FIRE;
      }
      if (element instanceof Cloud) {
        return ViewElement.CLOUD;
      }

    }
    return ViewElement.EMPTY;
  }


  private void initializeTimeline() {
    Duration duration = new Duration(Controller.PERIOD_IN_MILLISECONDS);
    EventHandler<ActionEvent> eventHandler =
@@ -124,9 +128,9 @@ public class Controller {
  }

  public void initialize(int squareWidth, int squareHeight, int columnCount,
                                int rowCount, int initialFireCount, int initialFirefighterCount) {
                                int rowCount, int initialFireCount, int initialFirefighterCount,int initialCloud) {
    grid.setDimensions(columnCount, rowCount, squareWidth, squareHeight);
    this.setModel(new FirefighterBoard(columnCount, rowCount, initialFireCount, initialFirefighterCount));
    this.setModel(new FirefighterBoard(columnCount, rowCount, initialFireCount, initialFirefighterCount,initialCloud));
    repaintGrid();
  }

Original line number Diff line number Diff line
@@ -4,62 +4,23 @@ import util.Position;

import java.util.List;

/**
 * This interface represents a generic board for modeling various state-based systems.
 *
 * @param <S> The type of state represented on the board.
 */
public interface Board<S> {

public interface Board<S>  {
    /**
   * Get the state of the board at a specific position.
     * Retourne l'état des éléments situés à une position spécifique du tableau.
     *
   * @param position The position on the board for which to retrieve the state.
   * @return The state at the specified position.
     * @param position La position sur le tableau pour laquelle récupérer l'état.
     * @return L'état des éléments à la position donnée.
     */
  S getState(Position position);

    S getState(Position position); // État des éléments sur une position donnée.
    /**
   * Set the state of a specific position on the board to the specified state.
     * Définit l'état des éléments à une position spécifique du tableau.
     *
   * @param state The state to set for the given position.
   * @param position The position on the board for which to set the state.
     * @param state    L'état à définir pour la position donnée.
     * @param position La position sur le tableau pour laquelle définir l'état.
     */
    void setState(S state, Position position);

  /**
   * Get the number of rows in the board.
   *
   * @return The number of rows in the board.
   */
  int rowCount();

  /**
   * Get the number of columns in the board.
   *
   * @return The number of columns in the board.
   */
  int columnCount();

  /**
   * Update the board to its next generation or state. This method may modify the
   * internal state of the board and return a list of positions that have changed
   * during the update.
   *
   * @return A list of positions that have changed during the update.
   */
  List<Position> updateToNextGeneration();

  /**
   * Reset the board to its initial state.
   */
  void reset();

  /**
   * Get the current step number or generation of the board.
   *
   * @return The current step number or generation.
   */
  int stepNumber();
}
+27 −0
Original line number Diff line number Diff line
package model;

import util.Position;
import java.util.List;

public interface BoardBehavior<S>  {
    /**
     * Get the current step number or generation of the board.
     *
     * @return The current step number or generation.
     */
    int stepNumber();

    /**
     * Update the board to its next generation or state. This method may modify the
     * internal state of the board and return a list of positions that have changed
     * during the update.
     *
     * @return A list of positions that have changed during the update.
     */
    List<Position> updateToNextGeneration();

    /**
     * Reset the board to its initial state.
     */
    void reset();
}
+27 −0
Original line number Diff line number Diff line
package model;

import util.Position;

public abstract class BoardElement implements ModelElement{
    protected Position position;

    public BoardElement(Position position) {
        this.position = position;
    }

    @Override
    public Position getPosition() {
        return position;
    }
    public void setPosition(Position position) {
        this.position = position;
    }
    public boolean isAtPosition(Position position) {
        return this.position.equals(position);
    }

    public abstract String getType(); // Ajout de la méthode abstraite


    public abstract String toString();
}
Original line number Diff line number Diff line
package model;

import util.Position;
import util.TargetStrategy;

import java.util.*;

public class BoardFireFighterBehavior implements BoardBehavior{
    private final TargetStrategy targetStrategy = new TargetStrategy();
    private final Map<Position, List<Position>> neighbors;
    private List<Position> firefighterPositions;
    private Set<Position> firePositions;
    private final ElementFactory<FireFighter> firefighterFactory;
    private final ElementFactory<Fire> fireFactory;
    private final ElementFactory<Cloud> cloudFactory;
    private List<Position> cloudPositions;
    private int step;

    public BoardFireFighterBehavior(Map<Position, List<Position>> neighbors, ElementFactory<Fire> fireFactory ,ElementFactory<FireFighter> firefighterFactory,ElementFactory<Cloud> cloudFactory) {
        this.step=0;
        this.neighbors = neighbors;
        this.firefighterFactory = firefighterFactory;
        this.fireFactory = fireFactory;
        this.cloudFactory=cloudFactory;
    }

    public void initializeElements(int rowCount, int columnCount) {
        // Feux
        firePositions = new HashSet<>();
        List<Fire> fires = fireFactory.createElements(rowCount, columnCount);
        for (Fire fire : fires) {
            firePositions.add(fire.getPosition());
        }

        // Pompiers
        firefighterPositions = new ArrayList<>();
        List<FireFighter> firefighters = firefighterFactory.createElements(rowCount, columnCount);
        for (FireFighter firefighter : firefighters) {
            firefighterPositions.add(firefighter.getPosition());
        }

        // Nuages
        cloudPositions = new ArrayList<>();
        List<Cloud> clouds = cloudFactory.createElements(rowCount, columnCount);
        for (Cloud cloud : clouds) {
            cloudPositions.add(cloud.getPosition());
        }
    }


    public 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;
    }

    public List<Position> updateFirefighters() {
        List<Position> modifiedPositions = new ArrayList<>();
        List<Position> newFirefighterPositions = new ArrayList<>();
        for (Position firefighterPosition : firefighterPositions) {
            Position newFirefighterPosition = targetStrategy.neighborClosestToTarget(firefighterPosition, firePositions, neighbors);
            newFirefighterPositions.add(newFirefighterPosition);
            extinguish(newFirefighterPosition);
            modifiedPositions.add(firefighterPosition);
            modifiedPositions.add(newFirefighterPosition);

            List<Position> neighborFirePositions = neighbors.get(newFirefighterPosition).stream()
                    .filter(firePositions::contains).toList();
            for (Position firePosition : neighborFirePositions) {
                extinguish(firePosition);
            }
            modifiedPositions.addAll(neighborFirePositions);
        }
        firefighterPositions = newFirefighterPositions;
        return modifiedPositions;
    }

    private void extinguish(Position position) {
        firePositions.remove(position);
    }
    /**
     * Éteint les feux autour d'une position donnée.
     *
     * @param firePositions Les positions des feux actuels.
     * @param firefighterPosition La position actuelle du pompier.
     * @param modifiedPositions Les positions modifiées pendant ce tour.
     */
    protected void extinguishFire(Set<Position> firePositions, Position firefighterPosition, List<Position> modifiedPositions) {
        List<Position> nearbyFires = neighbors.get(firefighterPosition).stream()
                .filter(firePositions::contains)
                .toList();
        for (Position fire : nearbyFires) {
            firePositions.remove(fire);
            modifiedPositions.add(fire);
        }
    }


    public Set<Position> getFirePositions() {
        return firePositions;
    }

    public List<Position> getFirefighterPositions() {
        return firefighterPositions;
    }

    public void incrementStep() {
        step++;
    }


    @Override
    public int stepNumber() {
        return step;
    }

    @Override
    public List<Position> updateToNextGeneration() {
        List<Position> modifiedPositions = updateFirefighters();
        modifiedPositions.addAll(updateFires());
        modifiedPositions.addAll(updateClouds());
        incrementStep();
        return modifiedPositions;
    }

    @Override
    public void reset() {
        this.step=0;
    }
    public List<Position> updateClouds() {
        List<Position> modifiedPositions = new ArrayList<>();
        List<Position> newCloudPositions = new ArrayList<>();

        for (Position cloudPosition : cloudPositions) {
            // Déplacement aléatoire
            List<Position> possibleMoves = neighbors.get(cloudPosition);
            Position newCloudPosition = possibleMoves.get(new Random().nextInt(possibleMoves.size()));
            newCloudPositions.add(newCloudPosition);

            // Éteindre le feu à la position du nuage
            extinguish(newCloudPosition);
            modifiedPositions.add(cloudPosition);
            modifiedPositions.add(newCloudPosition);
        }

        cloudPositions = newCloudPositions;
        return modifiedPositions;
    }

    public List<Position> getCloudPositions() {
        return cloudPositions;
    }
}
Original line number Diff line number Diff line
package model;

import util.Position;

import java.util.List;
import java.util.Map;

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;
    }



}
Original line number Diff line number Diff line
package model;

import util.Position;

import java.util.List;

/**
 * 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.




}
+20 −0
Original line number Diff line number Diff line
package model;

import model.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;
    }
}
+37 −0
Original line number Diff line number Diff line
package model;

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);
    }
}
Original line number Diff line number Diff line
package model;

import java.util.List;

public interface ElementFactory<T extends ModelElement> {
    List<T> createElements(int rowCount, int columnCount);
    int getCount();
}
+24 −0
Original line number Diff line number Diff line
package model;

import util.Position;

public class Fire  extends BoardElement{
    public Fire(Position position) {
        super(position);
    }

    @Override
    public String getType() {
        return "FIRE";
    }




    @Override
    public String toString() {
        return "Fire{" +
                "position=" + position +
                '}';
    }
}
+52 −0
Original line number Diff line number Diff line
package model;

import util.Position;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class FireFactory implements ElementFactory<Fire>,PositionGenerator{
    private final Random random;
    private int count;

    public FireFactory(Random random, int count) {
        this.random = random; // Injecte un générateur aléatoire pour une flexibilité.
        this.count=count;
    }

    /**
     * Crée une liste de feux avec des positions et intensités aléatoires.
     *
     * @param rowCount   Nombre de lignes du plateau.
     * @param columnCount Nombre de colonnes du plateau.

     * @return Une liste d'objets `Fire`.
     */
    public List<Fire> createElements(int rowCount, int columnCount) {
        List<Fire> fires = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            Position randomPosition = generateRandomPosition(rowCount, columnCount);
            boolean add = fires.add(new Fire(randomPosition));
        }
        return fires;
    }

    /**
     * Génère une position aléatoire sur le plateau.
     *
     * @param rowCount   Nombre de lignes.
     * @param columnCount Nombre de colonnes.
     * @return Une position aléatoire.
     */
    @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;
    }
}
+19 −0
Original line number Diff line number Diff line
package model;

import util.Position;

public class FireFighter extends BoardElement{
    public FireFighter(Position position) {
        super(position);
    }

    @Override
    public String getType() {
        return "FIREFIGHTER";
    }

    @Override
    public String toString() {
        return "Firefighter at " + position;
    }
}
Original line number Diff line number Diff line
@@ -4,29 +4,35 @@ 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 BoardFireFighterBehavior behavior;
  private final BoardFirefighterProperties properties;


  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++)
  public FirefighterBoard(int columnCount, int rowCount, int initialFireCount, int initialFirefighterCount,int initialCloud) {
    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));

    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 column = 0; column < columnCount; 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]);
@@ -34,114 +40,55 @@ public class FirefighterBoard implements Board<List<ModelElement>> {
        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());
    return neighbors;
  }

  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;
  }
    // 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

  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;

  }
    // 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 FireFighter(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)));

  @Override
  public int stepNumber() {
    return step;
    return result;
  }

  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();
    behavior.reset();
    behavior.initializeElements(properties.rowCount(), properties.columnCount());
  }

  private void extinguish(Position position) {
    firePositions.remove(position);
  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 FireFighter) {
      behavior.getFirefighterPositions().add(position); // Ajouter un Firefighter
    } else if (element instanceof Cloud) {
      behavior.getCloudPositions().add(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);
  }

  public BoardFireFighterBehavior getBehavior() {
    return behavior;
  }

  public BoardFirefighterProperties getProperties() {
    return properties;
  }
}
Original line number Diff line number Diff line
package model;

import util.Position;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class FirefighterFactory implements ElementFactory<FireFighter>, PositionGenerator{
    private final Random random;
    private int count;

    public FirefighterFactory(Random random,int count) {
        this.random = random;
        this.count=count;
    }

    @Override
    public List<FireFighter> createElements(int rowCount, int columnCount) {
        List<FireFighter> firefighters = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            Position randomPosition = generateRandomPosition(rowCount, columnCount);
            firefighters.add(new FireFighter(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;
    }
}
Original line number Diff line number Diff line
package model;

public enum ModelElement {
  FIREFIGHTER, FIRE
import util.Position;

public interface ModelElement {
    public Position getPosition();

}
Original line number Diff line number Diff line
package model;

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);
    }



    public Position move(List<Position> positions,Map<Position, List<Position>> neighbors, Set<Position> firePositions) {
        List<Position> modifiedPositions = new ArrayList<>();
        List<Position> newPositions = new ArrayList<>();
        Position finalPosition=null;
        for (Position firefighterPosition : positions) {
            // Déplacement motorisé (deux cases maximum)
            Position firstStep = targetStrategy.neighborClosestToTarget(firefighterPosition, firePositions, neighbors);
            Position secondStep = targetStrategy.neighborClosestToTarget(firstStep, firePositions, neighbors);
            finalPosition = secondStep != null ? secondStep : firstStep;

        }

        return finalPosition;
    }
}
Original line number Diff line number Diff line
package model;

import util.Position;

public interface PositionGenerator {
    public Position generateRandomPosition(int rowCount, int columnCount);
}
Original line number Diff line number Diff line
package util;

public record Position(int row, int column) {
    public boolean isAtPosition(Position position) {
        return row == position.row() && column == position.column();
    }


}
+11 −0
Original line number Diff line number Diff line
package util;

import view.ViewElement;

import java.util.Collection;
import java.util.List;
import java.util.Map;

public interface Strategy {
    Position neighborClosestToTarget(Position position, Collection<Position> targets, Map<Position, List<Position>> neighbors);
}
Original line number Diff line number Diff line
package model;
package util;

import util.Position;
import view.ViewElement;

import java.util.*;

public class TargetStrategy {
public class TargetStrategy implements Strategy{


    /**
@@ -12,7 +13,7 @@ public class TargetStrategy {
     * @param targets positions that are targeted.
     * @return the position next to the current position that is on the path to the closest target.
     */
    Position neighborClosestToFire(Position position, Collection<Position> targets,
    public Position neighborClosestToTarget(Position position, Collection<Position> targets,
                                          Map<Position, List<Position>> neighbors) {
        Set<Position> seen = new HashSet<Position>();
        HashMap<Position, Position> firstMove = new HashMap<Position, Position>();
@@ -21,6 +22,7 @@ public class TargetStrategy {
            firstMove.put(initialMove, initialMove);
        while (!toVisit.isEmpty()) {
            Position current = toVisit.poll();
         //   if (grid[current.row()][current.column()] == ViewElement.MOUNTAIN) continue;
            if (targets.contains(current))
                return firstMove.get(current);
            for (Position adjacent : neighbors.get(current)) {
Original line number Diff line number Diff line
@@ -96,4 +96,5 @@ public class FirefighterGrid extends Canvas implements Grid<ViewElement>{
    private void clearBox(int row, int column){
        getGraphicsContext2D().clearRect(column * boxWidth,row * boxHeight, boxWidth, boxHeight);
    }

}
 No newline at end of file
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@ package view;
import javafx.scene.paint.Color;

public enum ViewElement {
  FIREFIGHTER(Color.BLUE), FIRE(Color.RED), EMPTY(Color.WHITE);
  FIREFIGHTER(Color.BLUE), FIRE(Color.RED), EMPTY(Color.WHITE) ,  CLOUD(Color.GRAY),  MOUNTAIN(Color.GREEN), ROCKY(Color.BLACK);
  final Color color;
  ViewElement(Color color) {
    this.color = color;
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@
<?import javafx.scene.control.Label?>
<HBox styleClass="background" stylesheets="@DarkTheme.css"
      xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
      fx:controller="controller.Controller">
      fx:controller="controller.Controller" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity">
  <VBox>
    <Separator maxHeight="-Infinity" maxWidth="-Infinity"
               prefHeight="24.0" prefWidth="200.0"/>
Original line number Diff line number Diff line
@@ -8,19 +8,20 @@ import java.util.List;
import static org.assertj.core.api.Assertions.*;

public class FirefighterBoardTest {
  /*
  @Test
  void testColumnCount(){
    Board<List<ModelElement>> board = new FirefighterBoard(20, 10, 1, 3);
    FirefighterBoard board = new FirefighterBoard(20, 10, 1, 3);
    assertThat(board.columnCount()).isEqualTo(20);
  }
  @Test
  void testRowCount(){
    Board<List<ModelElement>> board = new FirefighterBoard(20, 10, 1, 3);
    FirefighterBoard board = new FirefighterBoard(20, 10, 1, 3);
    assertThat(board.rowCount()).isEqualTo(10);
  }
  @Test
  void testStepNumber(){
    Board<List<ModelElement>> board = new FirefighterBoard(20, 10, 1, 3);
    FirefighterBoard board = new FirefighterBoard(20, 10, 1, 3);
    for(int index = 0; index < 10; index++){
      assertThat(board.stepNumber()).isEqualTo(index);
      board.updateToNextGeneration();
@@ -29,11 +30,11 @@ public class FirefighterBoardTest {
  }
  @Test
  void testGetState_afterSet(){
    Board<List<ModelElement>> board = new FirefighterBoard(20, 10, 0, 0);
    FirefighterBoard board = new FirefighterBoard(20, 10, 0, 0);
    Position position = new Position(1,2);
    assertThat(board.getState(position)).isEmpty();
    board.setState(List.of(ModelElement.FIRE), position);
    assertThat(board.getState(position)).containsExactly(ModelElement.FIRE);
  }
  }*/

}