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
  • melissa
  • variant
  • yanis
4 results

Target

Select target project
  • 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
23 results
Select Git revision
  • main
  • variant
2 results
Show changes
Commits on Source (71)
Showing
with 1168 additions and 286 deletions
......@@ -32,3 +32,11 @@ fabric.properties
.idea/caches/build_file_checksums.ser
.gradle/
*.class
bin/
.gradle
*.bin
*.lock
.gradle/8.10.2/executionHistory/executionHistory.bin
build/
\ No newline at end of file
.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
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import view.FirefighterGrid?>
<HBox styleClass="background" stylesheets="@DarkTheme.css"
xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="controller.Controller">
<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>
diagrams/model.png

77.1 KiB

package app;
import java.io.IOException;
import java.net.URL;
import controller.Controller;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
......@@ -7,21 +10,20 @@ import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
public class SimulatorApplication extends javafx.application.Application {
private static final String VIEW_RESOURCE_PATH = "/view/view.fxml";
private static final String APP_NAME = "Firefighter simulator";
private static final int ROW_COUNT = 20;
private static final int COLUMN_COUNT = 20;
private static final int BOX_WIDTH = 50;
private static final int BOX_HEIGHT = 50;
private static final int ROW_COUNT = 22;
private static final int COLUMN_COUNT = 22;
private static final int BOX_WIDTH = 25;
private static final int BOX_HEIGHT = 25;
public static final int INITIAL_FIRE_COUNT = 3;
public static final int INITIAL_FIREFIGHTER_COUNT = 6;
public static final int INITIAL_CLOUD_COUNT = 6;
private Stage primaryStage;
private Parent view;
private void initializePrimaryStage(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle(APP_NAME);
......@@ -31,7 +33,7 @@ public class SimulatorApplication extends javafx.application.Application {
}
@Override
public void start(Stage primaryStage) throws IOException {
public void start(@SuppressWarnings("exports") Stage primaryStage) throws IOException {
initializePrimaryStage(primaryStage);
initializeView();
showScene();
......@@ -44,7 +46,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() {
......
package controller;
import static java.util.Objects.*;
import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.*;
import java.util.ArrayList;
import java.util.List;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
......@@ -13,17 +23,12 @@ import javafx.scene.control.ToggleGroup;
import javafx.util.Duration;
import javafx.util.Pair;
import model.Board;
import model.ModelElement;
import model.FirefighterBoard;
import model.FireFighterScenario;
import model.Square;
import util.Position;
import view.Grid;
import view.ViewElement;
import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
public class Controller {
public static final int PERIOD_IN_MILLISECONDS = 50;
......@@ -40,7 +45,7 @@ public class Controller {
@FXML
private Grid<ViewElement> grid;
private Timeline timeline;
private Board<List<ModelElement>> board;
private Board<Square> board;
@FXML
private void initialize() {
......@@ -54,15 +59,15 @@ public class Controller {
pauseToggleButton.setSelected(true);
}
private void setModel(FirefighterBoard firefighterBoard) {
this.board = requireNonNull(firefighterBoard, "firefighter.model is null");
private void setModel(Board<Square> board) {
this.board = requireNonNull(board, "board is null");
}
private void updateBoard() {
List<Position> updatedPositions = board.updateToNextGeneration();
List<Pair<Position, ViewElement>> updatedSquares = new ArrayList<>();
for (Position updatedPosition : updatedPositions) {
List<ModelElement> squareState = board.getState(updatedPosition);
Square squareState = board.getStates(updatedPosition);
ViewElement viewElement = getViewElement(squareState);
updatedSquares.add(new Pair<>(updatedPosition, viewElement));
}
......@@ -76,25 +81,18 @@ public class Controller {
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)));
viewElements[row][column] = getViewElement(board.getStates(new Position(row, column)));
grid.repaint(viewElements);
updateGenerationLabel(board.stepNumber());
}
private ViewElement getViewElement(List<ModelElement> squareState) {
if(squareState.contains(ModelElement.FIREFIGHTER)){
return ViewElement.FIREFIGHTER;
}
if (squareState.contains(ModelElement.FIRE)){
return ViewElement.FIRE;
}
return ViewElement.EMPTY;
private ViewElement getViewElement(Square square) {
return new ViewElement(square.getViewColor());
}
private void initializeTimeline() {
Duration duration = new Duration(Controller.PERIOD_IN_MILLISECONDS);
EventHandler<ActionEvent> eventHandler =
event -> updateBoard();
EventHandler<ActionEvent> eventHandler = event -> updateBoard();
KeyFrame keyFrame = new KeyFrame(duration, eventHandler);
timeline = new Timeline(keyFrame);
timeline.setCycleCount(Animation.INDEFINITE);
......@@ -124,9 +122,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 initialcloudCount) {
grid.setDimensions(columnCount, rowCount, squareWidth, squareHeight);
this.setModel(new FirefighterBoard(columnCount, rowCount, initialFireCount, initialFirefighterCount));
this.setModel(new FireFighterScenario(columnCount, rowCount, initialFireCount, initialFirefighterCount, initialcloudCount));
repaintGrid();
}
......
package model;
import java.util.List;
import util.Position;
import java.util.List;
import util.Position;
/**
* This interface represents a generic board for modeling various state-based systems.
* This interface represents a generic board for modeling various state-based
* systems.
*
* @param <S> The type of state represented on the board.
*/
......@@ -17,7 +20,7 @@ public interface Board<S> {
* @param position The position on the board for which to retrieve the state.
* @return The state at the specified position.
*/
S getState(Position position);
S getStates(Position position);
/**
* Set the state of a specific position on the board to the specified state.
......@@ -25,7 +28,7 @@ public interface Board<S> {
* @param state The state to set for the given position.
* @param position The position on the board for which to set the state.
*/
void setState(S state, Position position);
void setSquare(S square);
/**
* Get the number of rows in the board.
......@@ -61,5 +64,23 @@ public interface Board<S> {
* @return The current step number or generation.
*/
int stepNumber();
}
public int getStepNumber();
// Le booléen replaceState permet de forcer le remplacement des cases vides
public void setSquare(S square, boolean replaceStates);
public boolean doesPositionExist(Position position);
public void clearCaseFrom(Entity entity, Position position);
public Position getNearestEntity(Position fromPos, Class<?> entityType);
public boolean doesSquareContainEntity(Position squarePos, Class<?> entityType);
public void addEntityAtSquare(Entity entity, Position position);
public boolean isPositionEmpty(Position position);
public void addEntityAtSquare(Entity entity, Position position, boolean replaceStates);
}
package model;
import javafx.geometry.Pos;
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;
public Cloud(Position position, Board<Square> b){
this.age = 0;
this.position = position;
}
public Cloud(Position position, Board<Square> b, int age){
this.age = age;
this.position = position;
}
@Override
public List<Position> nextTurn(Board<Square> b) {
List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, b);
adjacentPositions.removeIf( p -> b.doesSquareContainEntity(p, Cloud.class));
// Filtrer pour obtenir uniquement les positions qui ne contiennent pas de pompier
adjacentPositions.removeIf(p -> b.doesSquareContainEntity(p, FireFighter.class));
// Choisir une position aléatoire parmi les mouvements possibles
Position next_position = adjacentPositions.get(new Random().nextInt(adjacentPositions.size()));
// Si la nouvelle position contient un feu, éteindre le feu
if (b.getStates(next_position).getEntities().stream().anyMatch(element -> element instanceof Fire) ){
extinguish(next_position, b);
}
Position old_position = this.position;
this.position = next_position;
b.addEntityAtSquare(this, next_position);
b.clearCaseFrom(this, old_position);
return List.of(old_position, this.position);
}
private Position extinguish(Position p, Board<Square> b) {
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);
}
}
return p;
}
@Override
public Position getPosition() {
return this.position;
}
@Override
public void setPosition(Position p) {
this.position = p;
}
@Override
public int getAge() {
return age;
}
@Override
public void setAge(int age) {
this.age =age;
}
@Override
public void incrementAge() {
this.age += 1;
}
@Override
public Color getViewColor() {
return this.viewColor;
}
@Override
public int getPriority(){ return this.priority;}
}
package model;
import java.util.ArrayList;
import java.util.List;
import javafx.scene.paint.Color;
import util.Position;
public class EmptyEntity implements Entity{
private Position position;
private int age;
public EmptyEntity(Position position){
this.position = position;
this.age = 0;
}
public EmptyEntity(Position position, int age){
this.position = position;
this.age = age;
}
@Override
public List<Position> nextTurn(Board<Square> board) {
return new ArrayList<Position>();
}
@Override
public Position getPosition() {
return this.position;
}
@Override
public void setPosition(Position p) {
this.position = p;
}
@Override
public int getAge() {
return age;
}
@Override
public void setAge(int age){
this.age = age;
}
@Override
public void incrementAge() {
this.age = age + 1;
}
@Override
public Color getViewColor() {
return Color.WHITE;
}
}
\ No newline at end of file
package model;
import java.util.ArrayList;
import java.util.List;
import javafx.scene.paint.Color;
import util.Position;
public class EmptySquare implements Entity {
private Position position;
private final Color viewColor = Color.WHITE;
private int age;
public EmptySquare(Position p) {
this.position = p;
this.age = -999;
}
public EmptySquare(Position p, int age) {
this.position = p;
this.age = age;
}
@Override
public List<Position> nextTurn(Board<Square> board) {
return new ArrayList<Position>();
}
@Override
public Position getPosition() {
return position;
}
@Override
public void setPosition(Position p) {
this.position = p;
}
public Color getViewColor() {
return this.viewColor;
}
@Override
public int getAge() {
return this.age;
}
@Override
public void incrementAge() {
age = age + 1;
}
@Override
public void setAge(int age) {
this.age = age;
}
}
package model;
import java.util.List;
import javafx.scene.paint.Color;
import util.Position;
import java.util.List;
import javafx.scene.paint.Color;
import util.Position;
public interface Entity {
/**
* Exécute un tour de jeu, en vérifiant les cases adjacentes pour des instances de Fire.
*
* @param b Le plateau de jeu contenant des entités.
* @return Une liste de positions affectées durant le tour (que la vue doit mettre à jour).
*/
public List<Position> nextTurn(Board<Square> board);
public Position getPosition();
public void setPosition(Position p);
public int getAge();
public void setAge(int age);
public void incrementAge();
public Color getViewColor();
public int getPriority();
}
package model;
import util.Matrix;
import util.Position;
public abstract class EntityScenario implements Scenario{
public void initScenario(Matrix<Square> matrix){
for(int x = 0; x < matrix.getRows(); x++){
for(int y = 0; y < matrix.getColumns(); y++){
Square s = new Square(new Position(x, y), new EmptyEntity(new Position(x,y)));
matrix.set(x,y, s);
}
}
}
}
package model;
import java.util.ArrayList;
import java.util.List;
import javafx.scene.paint.Color;
import util.Position;
import util.PositionUtil;
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;
public Fire(Position position, Board<Square> b) {
this.b = b;
this.position = position;
this.age = 0;
}
public Fire(Position position, Board<Square> b, int age) {
this.b = b;
this.position = position;
this.age = age;
}
@Override
public List<Position> nextTurn(Board<Square> board) {
if (board.getStepNumber() % 2 == 0)
return new ArrayList<Position>();
List<Position> positions = PositionUtil.generateAdjacentPositions(position, board);
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);
}
}
if (!b.doesPositionExist(p)) {
positions.remove(p);
}
}
return positions;
}
@Override
public void setPosition(Position p) {
this.position = p;
}
@Override
public Position getPosition() {
return this.position;
}
public Color getViewColor() {
return this.viewColor;
}
@Override
public int getAge() {
return this.age;
}
@Override
public void incrementAge() {
this.age = age + 1;
}
@Override
public void setAge(int age) {
this.age = age;
}
@Override
public int getPriority(){ return this.priority;}
}
package model;
import java.util.ArrayList;
import java.util.List;
import javafx.scene.paint.Color;
import util.Position;
import util.PositionUtil;
import util.PositionUtil;
public class FireFighter implements Entity {
private int age;
private Position position;
private final Color viewColor = Color.BLUE;
private final int priority = 1;
public FireFighter(Position position, Board<Square> b) {
this.position = position;
this.age = 0;
}
public FireFighter(Position position, Board<Square> b, int age) {
this.position = position;
this.age = age;
}
public List<Position> nextTurn(Board<Square> b) {
List<Position> positions = new ArrayList<>();
// Générer les positions adjacentes
List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, b);
// Vérifier s'il y a du feu dans une des positions adjacentes
boolean hasFire = adjacentPositions.stream()
.anyMatch(p -> b.doesSquareContainEntity(p, Fire.class));
if (hasFire) {
// Si du feu est trouvé, on éteint les feux adjacents
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
}
}
return positions;
}
private 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);
}
}
extinguishedPositions.add(p); // Ajouter la position où le feu a été éteint
}
return extinguishedPositions;
}
private Position getNextPositionTowards(Position currentPos, Position targetPos, Board<Square> b) {
// Générer les 8 positions adjacentes possibles
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
if (possibleMoves.isEmpty()) {
return null;
}
// Calculer la distance actuelle vers la cible
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;
for (Position move : possibleMoves) {
int distance = PositionUtil.getManhattanDistance(move, targetPos);
if (distance < minDistance) {
minDistance = distance;
bestMove = move;
}
}
// Si aucun déplacement ne réduit la distance, annuler le déplacement
if (bestMove == null) {
return null;
}
return bestMove;
}
@Override
public void setPosition(Position p) {
this.position = p;
}
@Override
public Position getPosition() {
return this.position;
}
public Color getViewColor() {
return this.viewColor;
}
@Override
public int getAge() {
return this.age;
}
@Override
public void incrementAge() {
this.age = age + 1;
}
@Override
public void setAge(int age) {
this.age = age;
}
public int getPriority(){ return this.priority;}
}
package model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Random;
import util.Matrix;
import util.Position;
import util.PositionUtil;
import util.PositionUtil;
public class FireFighterScenario extends EntityScenario implements Board<Square> {
private Matrix<Square> matrix;
private int step;
private int initialFireCount;
private int initialFireFightersCount;
private int intialCloudCount;
public FireFighterScenario(int columns, int rows, int initialFireCount, int initialFireFightersCount, int initialCloudCount) {
this.matrix = new Matrix<Square>(columns, rows);
this.initialFireCount = initialFireCount;
this.initialFireFightersCount = initialFireFightersCount;
this.intialCloudCount = initialCloudCount;
initScenario(matrix);
placeInitialActors(initialFireCount, initialFireFightersCount, initialCloudCount);
this.step = 0;
}
private void placeInitialActors(int initialFireCount, int initialFireFightersCount, int initialCloudCount) {
int fireCount = 0;
int fireFighterCount = 0;
int cloudCount = 0;
int chance = 5; // Chance initiale en pourcentage
Random random = new Random();
List<Position> positions = new ArrayList<>();
for (int x = 0; x < matrix.getRows(); x++) {
for (int y = 0; y < matrix.getColumns(); y++) {
positions.add(new Position(x, y));
}
}
while (fireCount < initialFireCount || fireFighterCount < initialFireFightersCount || cloudCount < intialCloudCount) {
Collections.shuffle(positions); // Mélange les positions pour un parcours aléatoire
for (Position pos : positions) {
if (getStates(pos).isEmpty()) {
if (fireCount < initialFireCount && random.nextInt(100) < chance) {
setSquare(new Square(pos, new Fire(pos, this, 1)));
fireCount++;
if (fireCount == initialFireCount && fireFighterCount == initialFireFightersCount && cloudCount == initialCloudCount) {
return;
}
continue;
}
if (fireFighterCount < initialFireFightersCount && random.nextInt(100) < chance) {
setSquare(new Square(pos, new FireFighter(pos, this, 1)));
fireFighterCount++;
if (fireCount == initialFireCount && fireFighterCount == initialFireFightersCount && cloudCount == initialCloudCount) {
return;
}
}
if (cloudCount < intialCloudCount && random.nextInt(100) < chance) {
setSquare(new Square(pos, new Cloud(pos, this, 1)));
cloudCount++;
if (fireCount == initialFireCount && fireFighterCount == initialFireFightersCount && cloudCount == initialCloudCount) {
return;
}
}
}
}
// Augmente la chance de placement après chaque parcours complet
chance = Math.min(chance + 5, 100); // Ne dépasse pas 100%
}
}
public Square getStates(Position position) {
if (position.x() > matrix.size() || position.y() > matrix.size()) {
throw new IllegalArgumentException(
"The position x:" + position.x() + " y:" + position.y() + " is out of the board.");
}
return matrix.get(position.x(), position.y());
}
public void setSquare(Square square) {
Position position = square.getPosition();
if (!(getStates(position).isEmpty())) {
return;
}
if (doesPositionExist(position)) {
matrix.set(position.x(), position.y(), square);
}
}
public void setSquare(Square square, boolean replaceStates) {
Position position = square.getPosition();
if (!(getStates(position).isEmpty()) && !replaceStates) {
return;
}
matrix.set(position.x(), position.y(), square);
}
public void addEntityAtSquare(Entity entity, Position position) {
if (!(getStates(position).isEmpty())) {
return;
}
if (doesPositionExist(position)) {
matrix.get(position.x(), position.y()).addEntity(entity);
;
}
}
public void addEntityAtSquare(Entity entity, Position position, boolean replaceStates) {
if (!(getStates(position).isEmpty()) && !replaceStates) {
return;
}
matrix.get(position.x(), position.y()).addEntity(entity);
;
}
public int rowCount() {
return matrix.getRows();
}
public int columnCount() {
return matrix.getColumns();
}
@Override
public void clearCaseFrom(Entity entity, Position position) {
matrix.get(position.x(), position.y()).getEntities().removeIf(element -> element.equals(entity));
}
public List<Position> updateToNextGeneration() {
ArrayList<Position> changedPositions = new ArrayList<>();
Iterator<Square> iterator = matrix.iterator();
while (iterator.hasNext()) {
Square s = iterator.next();
if (s.isEmpty())
continue;
if (s.getMaxAge() == 0) {
s.incrementAllAges();
continue;
}
if (s.getMaxAge() == step + 1) {
continue;
}
List<Entity> entities = new ArrayList<>(s.getEntities());
for (Entity e : entities) {
List<Position> entityUpdatedPositions = e.nextTurn(this);
e.incrementAge();
changedPositions.addAll(entityUpdatedPositions);
}
}
this.step = this.step + 1;
// matrix.displayMatrix();
return changedPositions;
}
public Position getNearestEntity(Position fromPos, Class<?> entityType) {
int rows = matrix.getRows();
int cols = matrix.getColumns();
Position nearestPosition = fromPos;
// Définir la distance maximale possible
int maxDistance = rows + cols;
// Parcourir les distances croissantes à partir de 1
for (int distance = 1; distance < maxDistance; distance++) {
List<Position> positionsAtDistance = PositionUtil.getPositionsAtManhattanDistance(fromPos, distance, rows, cols);
for (Position currentPos : positionsAtDistance) {
Square currentSquare = matrix.get(currentPos.x(), currentPos.y());
for (Entity currentEntity : currentSquare.getEntities()) {
if (entityType.isInstance(currentEntity)) {
// Dès qu'une entité est trouvée à cette distance, elle est la plus proche
// possible
return currentPos;
}
}
}
}
return nearestPosition; // Retourne null si aucune entité n'est trouvée
}
public void reset() {
step = 0;
matrix.clear();
initScenario(matrix);
placeInitialActors(initialFireCount, initialFireFightersCount, intialCloudCount);
}
public int stepNumber() {
return this.step;
}
@Override
public boolean doesPositionExist(Position position) {
return matrix.validateIndex(position);
}
@Override
public int getStepNumber() {
return step;
}
@Override
public boolean doesSquareContainEntity(Position squarePos, Class<?> entityType) {
return getStates(squarePos).getEntities().stream().anyMatch(entityType::isInstance);
}
@Override
public boolean isPositionEmpty(Position position) {
return getStates(position).isEmpty();
}
}
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
}
package model;
import util.Matrix;
public interface Scenario {
public void initScenario(Matrix<Square> matrix);
}
\ No newline at end of file
package model;
import java.util.ArrayList;
import java.util.List;
import javafx.scene.paint.Color;
import util.Position;
public class Square {
private List<Entity> entities;
private Position position;
public Square(Position position){
this.entities = new ArrayList<Entity>();
this.position = position;
}
public Square(Position position, Entity entity){
this.entities = new ArrayList<Entity>();
this.entities.add(entity);
this.position = position;
}
public List<Entity> getEntities(){
return this.entities;
}
public Position getPosition(){
return this.position;
}
public void addEntity(Entity entity){
entities.add(entity);
}
public void removeEntity(Entity entity){
entities.remove(entity);
}
public void setEntities(List<Entity> entities){
this.entities = entities;
}
public boolean isEmpty(){
return entities.isEmpty() ||(entities.size() == 1 && entities.get(0) instanceof EmptyEntity);
}
public int getMinimalAge(){
int minimalAge = 0;
for(Entity e : entities){
if(e.getAge() < minimalAge){
minimalAge = e.getAge();
}
}
return minimalAge;
}
public int getMaxAge(){
int maxAge = 0;
for(Entity e : entities){
if(e.getAge() > maxAge){
maxAge = e.getAge();
}
}
return maxAge;
}
public void incrementAllAges(){
for(Entity e : entities){
e.incrementAge();
}
}
public Color getViewColor(){
if (entities.isEmpty()) {
return Color.WHITE;
} else {
int sumRed = 0, sumGreen = 0, sumBlue = 0;
for (Entity e : entities) {
Color color = e.getViewColor();
if (color != null) {
sumRed += color.getRed();
sumGreen += color.getGreen();
sumBlue += color.getBlue();
}
}
int count = entities.size();
sumRed /= count;
sumGreen /= count;
sumBlue /= count;
Color color = new Color((double)(sumRed),(double)(sumGreen),(double)(sumBlue), 1.0);
return color;
}
}
}