diff --git a/src/main/java/app/SimulatorApplication.java b/src/main/java/app/SimulatorApplication.java index 6b009e4114f78b4f406f2a3954cb94be05354e80..d20a636d44bff5a0dde7772cfcc0f10d27a264fc 100644 --- a/src/main/java/app/SimulatorApplication.java +++ b/src/main/java/app/SimulatorApplication.java @@ -18,7 +18,8 @@ public class SimulatorApplication extends javafx.application.Application { private static final int SQUARE_WIDTH = 50; private static final int SQUARE_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 = 10; + public static final int INITIAL_CLOUD_COUNT=10; private Stage primaryStage; private Parent view; diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java index 2a60897c6eb8ba847cb8589840c16a0f175ce0a3..3291416ce093e7e302361b4aa2d7ae26d064851e 100644 --- a/src/main/java/controller/Controller.java +++ b/src/main/java/controller/Controller.java @@ -13,7 +13,9 @@ import javafx.scene.control.ToggleGroup; import javafx.util.Duration; import javafx.util.Pair; import model.Board; -import model.ModelElement; +import model.Element.Fire; +import model.Element.FireFigther; +import model.Element.ModelElement; import model.FirefighterBoard; import util.Position; import view.Grid; @@ -21,6 +23,7 @@ import view.ViewElement; import java.util.ArrayList; import java.util.List; +import java.util.Map; import static java.util.Objects.requireNonNull; @@ -59,9 +62,9 @@ public class Controller { } private void updateBoard(){ - List<Position> updatedPositions = board.updateToNextGeneration(); + Map<Position,List<ModelElement>> updatedPositions = board.updateToNextGeneration(); List<Pair<Position, ViewElement>> updatedSquares = new ArrayList<>(); - for(Position updatedPosition : updatedPositions){ + for(Position updatedPosition : updatedPositions.keySet()){ List<ModelElement> squareState = board.getState(updatedPosition); ViewElement viewElement = getViewElement(squareState); updatedSquares.add(new Pair<>(updatedPosition, viewElement)); @@ -80,17 +83,20 @@ public class Controller { grid.repaint(viewElements); updateGenerationLabel(board.stepNumber()); } - private ViewElement getViewElement(List<ModelElement> squareState) { - if(squareState.contains(ModelElement.FIREFIGHTER)){ - return ViewElement.FIREFIGHTER; + if (squareState == null) { + return ViewElement.EMPTY; } - if (squareState.contains(ModelElement.FIRE)){ - return ViewElement.FIRE; + if (squareState.isEmpty()) { + return ViewElement.EMPTY; } - return ViewElement.EMPTY; + return squareState.get(0).getViewElement(); + } + + + private void initializeTimeline() { Duration duration = new Duration(Controller.PERIOD_IN_MILLISECONDS); EventHandler<ActionEvent> eventHandler = diff --git a/src/main/java/model/Board.java b/src/main/java/model/Board.java index bb089a41406d57b0b2fe3d43b3c040cbd640b6b9..0f6bab6874dd4149b6af00c3c908ce9f19c67d56 100644 --- a/src/main/java/model/Board.java +++ b/src/main/java/model/Board.java @@ -1,8 +1,10 @@ package model; +import model.Element.ModelElement; import util.Position; import java.util.List; +import java.util.Map; /** * This interface represents a generic board for modeling various state-based systems. @@ -48,7 +50,7 @@ public interface Board<S> { * * @return A list of positions that have changed during the update. */ - List<Position> updateToNextGeneration(); + Map<Position, List<ModelElement>> updateToNextGeneration(); /** * Reset the board to its initial state. diff --git a/src/main/java/model/Element/Cloud.java b/src/main/java/model/Element/Cloud.java new file mode 100644 index 0000000000000000000000000000000000000000..b5eb6db0d4684ac395d3f58fcedbab20e69f7d33 --- /dev/null +++ b/src/main/java/model/Element/Cloud.java @@ -0,0 +1,33 @@ +package model.Element; + +import util.Position; +import view.ViewElement; + +import java.util.List; +import java.util.Map; +import java.util.Random; + +import static util.Tools.*; + + +public class Cloud implements ModelElement { + + @Override + public boolean equals(Object obj) { + return obj instanceof Cloud; + } + + @Override + public void update(Position position, Map<Position, List<ModelElement>> board, int step, int columnCount, int rowCount) { + Random nextCloud =new Random() ; + addElement(neighbors(position, rowCount, columnCount).get(nextCloud.nextInt()),board, new Cloud()); + removeElement(position,board,new Cloud()); + + } + + + @Override + public ViewElement getViewElement() { + return ViewElement.Cloud; + } +} diff --git a/src/main/java/model/Element/Fire.java b/src/main/java/model/Element/Fire.java new file mode 100644 index 0000000000000000000000000000000000000000..b67356cc27f9fe03d4a3cbacbca8d55310e08889 --- /dev/null +++ b/src/main/java/model/Element/Fire.java @@ -0,0 +1,53 @@ +package model.Element; + +import model.FirefighterBoard; +import util.Position; +import view.ViewElement; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +import static util.Tools.addElement; +import static util.Tools.neighbors; + +public class Fire implements ModelElement { + int fireWasCreate; + + public void setFireWasCreate(int fireWasCreate) { + this.fireWasCreate = fireWasCreate; + } + + @Override + public void update(Position position, Map<Position, List<ModelElement>> board,int step, int columnCount, int rowCount) { + if (step%2==0){ + Fire nextFire = new Fire(); + nextFire.setFireWasCreate(step); + for (Position position1 : neighbors(position, rowCount, columnCount)) { + + if (!board.containsKey(position1)){ + addElement(position1, board, new Fire()); + } else if (board.get(position1).isEmpty()) { + addElement(position1, board, new Fire()); + } + if (board.get(position1).contains(new Rockerie()) && (step - fireWasCreate)%4 ==0){ + if (!(board.get(position1).contains(new Mountain())||board.get(position1).contains(new FireFigther())||board.get(position1).contains(new MotorisedFirefigther())||board.get(position1).contains(new Cloud())||(board.get(position1).contains(new FireFigther())))){ + addElement(position1, board, new Fire()); + } + } + } + } + } + + + + @Override + public ViewElement getViewElement() { + return ViewElement.FIRE; + } + @Override + public boolean equals(Object obj) { + return obj instanceof Fire; + } +} diff --git a/src/main/java/model/Element/ModelElement.java b/src/main/java/model/Element/ModelElement.java new file mode 100644 index 0000000000000000000000000000000000000000..9e88284ae9262c65f89740cf63d7f659b2efce6c --- /dev/null +++ b/src/main/java/model/Element/ModelElement.java @@ -0,0 +1,15 @@ +package model.Element; + +import util.Position; +import view.ViewElement; + +import java.util.List; +import java.util.Map; + +public interface ModelElement { + void update (Position position,Map<Position,List<ModelElement>>board,int step,int columnCount, int rowCount); + + + + ViewElement getViewElement(); +} diff --git a/src/main/java/model/Element/MotorisedFirefigther.java b/src/main/java/model/Element/MotorisedFirefigther.java new file mode 100644 index 0000000000000000000000000000000000000000..94bc962bc927f699954ea2543b720ed6c02c19ff --- /dev/null +++ b/src/main/java/model/Element/MotorisedFirefigther.java @@ -0,0 +1,42 @@ +package model.Element; + +import util.Position; +import view.ViewElement; + +import java.util.List; +import java.util.Map; + +import static util.Tools.*; +import static util.Tools.removeElement; + +public class MotorisedFirefigther implements ModelElement{ + @Override + public void update(Position position, Map<Position, List<ModelElement>> board, int step, int columnCount, int rowCount) { + for (Position position1 : neighbors(position, rowCount, columnCount)) { + if (board.containsKey(position1)) { + if (board.get(position1).contains(new Fire())) { + extinguish(position,board); + return; + } + + } + + } + Position newPositionStep = neighborClosestToFire(position,board,rowCount,columnCount); + Position newPositionTwoStep=neighborClosestToFire(newPositionStep,board,rowCount,columnCount); + extinguish(newPositionTwoStep,board); + addElement(newPositionTwoStep,board,new MotorisedFirefigther()); + removeElement(position,board,new MotorisedFirefigther()); + + + } + + @Override + public ViewElement getViewElement() { + return ViewElement.MotorisedFirefigther; + } + @Override + public boolean equals(Object obj) { + return obj instanceof Mountain; + } +} diff --git a/src/main/java/model/Element/Mountain.java b/src/main/java/model/Element/Mountain.java new file mode 100644 index 0000000000000000000000000000000000000000..8d363c09591e42ac74965f72d8dba23e634e6ccb --- /dev/null +++ b/src/main/java/model/Element/Mountain.java @@ -0,0 +1,25 @@ +package model.Element; + +import util.Position; +import view.ViewElement; + +import java.util.List; +import java.util.Map; + +public class Mountain implements ModelElement{ + + + @Override + public void update(Position position, Map<Position, List<ModelElement>> board, int step, int columnCount, int rowCount) { + + } + + @Override + public ViewElement getViewElement() { + return ViewElement.Mountain; + } + @Override + public boolean equals(Object obj) { + return obj instanceof Mountain; + } +} diff --git a/src/main/java/model/Element/Road.java b/src/main/java/model/Element/Road.java new file mode 100644 index 0000000000000000000000000000000000000000..e455f73916f96d47d72ea7536178edfc38389da5 --- /dev/null +++ b/src/main/java/model/Element/Road.java @@ -0,0 +1,25 @@ +package model.Element; + +import util.Position; +import view.ViewElement; + +import java.util.List; +import java.util.Map; + +public class Road implements ModelElement{ + + + @Override + public void update(Position position, Map<Position, List<ModelElement>> board, int step, int columnCount, int rowCount) { + + } + + @Override + public ViewElement getViewElement() { + return ViewElement.Road; + } + @Override + public boolean equals(Object obj) { + return obj instanceof Road; + } +} diff --git a/src/main/java/model/Element/Rockerie.java b/src/main/java/model/Element/Rockerie.java new file mode 100644 index 0000000000000000000000000000000000000000..cd296f2b93d34477091cadc1771293ea7a16d926 --- /dev/null +++ b/src/main/java/model/Element/Rockerie.java @@ -0,0 +1,26 @@ +package model.Element; + +import util.Position; +import view.ViewElement; + +import java.util.List; +import java.util.Map; + +public class Rockerie implements ModelElement{ + + + @Override + public void update(Position position, Map<Position, List<ModelElement>> board, int step, int columnCount, int rowCount) { + + } + + @Override + public ViewElement getViewElement() { + return ViewElement.Rockerie; + } + @Override + public boolean equals(Object obj) { + + return obj instanceof Rockerie; + } +} diff --git a/src/main/java/model/FirefighterBoard.java b/src/main/java/model/FirefighterBoard.java index 3251952ea90ec5ea59fc3a3630f3d2a4e4e96f01..16f8b2f6d0cfeb6e2477ee676e064e25da835606 100644 --- a/src/main/java/model/FirefighterBoard.java +++ b/src/main/java/model/FirefighterBoard.java @@ -1,9 +1,14 @@ package model; +import model.Element.Fire; +import model.Element.FireFigther; +import model.Element.ModelElement; import util.Position; import java.util.*; +import static util.Tools.addElement; + public class FirefighterBoard implements Board<List<ModelElement>> { private final int columnCount; @@ -12,6 +17,7 @@ public class FirefighterBoard implements Board<List<ModelElement>> { private final int initialFirefighterCount; private List<Position> firefighterPositions; private Set<Position> firePositions; + private Map<Position,List<ModelElement>>board; private int step = 0; private final Random randomGenerator = new Random(); @@ -20,16 +26,29 @@ public class FirefighterBoard implements Board<List<ModelElement>> { this.rowCount = rowCount; this.initialFireCount = initialFireCount; this.initialFirefighterCount = initialFirefighterCount; + board=new HashMap<>(); 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()); + for (Position firefighterPosition:firefighterPositions + ) { + addElement(firefighterPosition, board, new FireFigther()); + + } + for (Position firePosition:firePositions + ) { + addElement(firePosition, board, new Fire()); + + } + } private Position randomPosition() { @@ -38,13 +57,7 @@ public class FirefighterBoard implements Board<List<ModelElement>> { @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; + return board.get(position); } @Override @@ -57,101 +70,49 @@ public class FirefighterBoard implements Board<List<ModelElement>> { return columnCount; } - public List<Position> updateToNextGeneration() { - List<Position> result = updateFirefighters(); - result.addAll(updateFires()); - step++; - return result; - } + public Map<Position, List<ModelElement>> updateToNextGeneration() { + Map<Position, List<ModelElement>> copieBord=new HashMap<>(); + for (Position positionCopie:board.keySet() + ) { + copieBord.put(positionCopie, board.get(positionCopie)); + } - private List<Position> updateFires() { - List<Position> result = new ArrayList<>(); - if (step % 2 == 0) { - List<Position> newFirePositions = new ArrayList<>(); - for (Position fire : firePositions) { - newFirePositions.addAll(neighbors(fire)); + + for (Position position:copieBord.keySet() + ) { + for (ModelElement element:copieBord.get(position) + ) { + element.update(position,board,step,columnCount,rowCount); } - firePositions.addAll(newFirePositions); - result.addAll(newFirePositions); + } - return result; + step++; + return board; + } + + @Override public int stepNumber() { return step; } - - private List<Position> updateFirefighters() { - List<Position> result = new ArrayList<>(); - List<Position> firefighterNewPositions = new ArrayList<>(); - for (Position firefighterPosition : firefighterPositions) { - Position newFirefighterPosition = neighborClosestToFire(firefighterPosition); - firefighterNewPositions.add(newFirefighterPosition); - extinguish(newFirefighterPosition); - result.add(firefighterPosition); - result.add(newFirefighterPosition); - List<Position> neighborFirePositions = neighbors(newFirefighterPosition).stream() - .filter(firePositions::contains).toList(); - for(Position firePosition : neighborFirePositions) - extinguish(firePosition); - result.addAll(neighborFirePositions); - } - firefighterPositions = firefighterNewPositions; - return result; - } - + @Override public void reset() { step = 0; initializeElements(); } - private void extinguish(Position position) { - firePositions.remove(position); - } - - private List<Position> neighbors(Position position) { - List<Position> list = new ArrayList<>(); - if (position.row() > 0) list.add(new Position(position.row() - 1, position.column())); - if (position.column() > 0) list.add(new Position(position.row(), position.column() - 1)); - if (position.row() < rowCount - 1) list.add(new Position(position.row() + 1, position.column())); - if (position.column() < columnCount - 1) list.add(new Position(position.row(), position.column() + 1)); - return list; - } - - private Position neighborClosestToFire(Position position) { - Set<Position> seen = new HashSet<>(); - HashMap<Position, Position> firstMove = new HashMap<>(); - Queue<Position> toVisit = new LinkedList<>(neighbors(position)); - for (Position initialMove : toVisit) - firstMove.put(initialMove, initialMove); - while (!toVisit.isEmpty()) { - Position current = toVisit.poll(); - if (firePositions.contains(current)) - return firstMove.get(current); - for (Position adjacent : neighbors(current)) { - if (seen.contains(adjacent)) continue; - toVisit.add(adjacent); - seen.add(adjacent); - firstMove.put(adjacent, firstMove.get(current)); - } - } - return 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); - } + if (position != null) { + board.put(position, state); + } else { + System.err.println("La position spécifiée est null."); } } + + } \ No newline at end of file diff --git a/src/main/java/model/ModelElement.java b/src/main/java/model/ModelElement.java deleted file mode 100644 index 759eee5e54c3a39472d8f7defbbbe6a2b67b8f00..0000000000000000000000000000000000000000 --- a/src/main/java/model/ModelElement.java +++ /dev/null @@ -1,5 +0,0 @@ -package model; - -public enum ModelElement { - FIREFIGHTER, FIRE -} diff --git a/src/main/java/util/Tools.java b/src/main/java/util/Tools.java new file mode 100644 index 0000000000000000000000000000000000000000..1005a294026ad8f6b479a68b8b2cdad6765fed52 --- /dev/null +++ b/src/main/java/util/Tools.java @@ -0,0 +1,66 @@ +package util; + +import model.Element.Fire; +import model.Element.FireFigther; +import model.Element.ModelElement; +import model.Element.Mountain; + +import java.util.*; + +public class Tools { + public static List<Position> neighbors(Position position , int rowCount , int columnCount) { + List<Position> list = new ArrayList<>(); + if (position.row() > 0) list.add(new Position(position.row() - 1, position.column())); + if (position.column() > 0) list.add(new Position(position.row(), position.column() - 1)); + if (position.row() < rowCount - 1) list.add(new Position(position.row() + 1, position.column())); + if (position.column() < columnCount - 1) list.add(new Position(position.row(), position.column() + 1)); + return list; + } + public static Position neighborClosestToFire(Position position,Map<Position, List<ModelElement>> board,int rowCount , int columnCount) { + Set<Position> seen = new HashSet<>(); + HashMap<Position, Position> firstMove = new HashMap<>(); + Queue<Position> toVisit = new LinkedList<>(neighbors(position,rowCount,columnCount)); + for (Position initialMove : toVisit) + firstMove.put(initialMove, initialMove); + while (!toVisit.isEmpty()) { + Position current = toVisit.poll(); + if (board.containsKey(current)) { + if (board.get(current).contains(new Fire())){ + return firstMove.get(current); + } + for (Position adjacent : neighbors(current, rowCount, columnCount)) { + if (seen.contains(adjacent)) { + continue; + } + toVisit.add(adjacent); + seen.add(adjacent); + firstMove.put(adjacent, firstMove.get(current)); + + } + + } + } + return position; + } + public static void extinguish(Position position,Map<Position, List<ModelElement>> board) { + board.remove(position); + } + + public static void addElement(Position position, Map<Position, List<ModelElement>> board, ModelElement element) { + List<ModelElement> elements = new ArrayList<>(); + if (board.containsKey(position)) { + elements.addAll(board.get(position)); + } + elements.add(element); + board.put(position,elements); + } + public static void removeElement(Position position,Map<Position, List<ModelElement>> board,ModelElement element){ + List<ModelElement> elements = new ArrayList<>(); + if (board.containsKey(position)) { + elements.addAll(board.get(position)); + } + elements.remove(element); + board.put(position,elements); + } + +} diff --git a/src/main/java/view/ViewElement.java b/src/main/java/view/ViewElement.java index ffb76112e1af543df5af41fa906082ef11be9967..a5b26b5fd7a80708445db2fafc2b6448c474faf9 100644 --- a/src/main/java/view/ViewElement.java +++ b/src/main/java/view/ViewElement.java @@ -3,9 +3,11 @@ 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),Cloud(Color.GRAY),Rockerie(Color.LIGHTGREY),MotorisedFirefigther(Color.ALICEBLUE),Road(Color.BLACK),Mountain(Color.BROWN), EMPTY(Color.WHITE); final Color color; ViewElement(Color color) { this.color = color; } + + } diff --git a/src/test/java/model/FirefighterBoardTest.java b/src/test/java/model/FirefighterBoardTest.java index 25cc8dbca8acea698879df68a5006a179f281ecc..4feb1d1d4dc8fead78109ae758d521aa91797c25 100644 --- a/src/test/java/model/FirefighterBoardTest.java +++ b/src/test/java/model/FirefighterBoardTest.java @@ -1,5 +1,6 @@ package model; +import model.Element.ModelElement; import org.junit.jupiter.api.Test; import util.Position;