diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java index 2a60897c6eb8ba847cb8589840c16a0f175ce0a3..9920daeeaacd1c2d2fd18501a218b4dfef39aa82 100644 --- a/src/main/java/controller/Controller.java +++ b/src/main/java/controller/Controller.java @@ -13,8 +13,9 @@ import javafx.scene.control.ToggleGroup; import javafx.util.Duration; import javafx.util.Pair; import model.Board; +import model.Firefighters; +import model.Fire; import model.ModelElement; -import model.FirefighterBoard; import util.Position; import view.Grid; import view.ViewElement; @@ -41,6 +42,7 @@ public class Controller { private Grid<ViewElement> grid; private Timeline timeline; private Board<List<ModelElement>> board; + private Board<List<ModelElement>> fire; @FXML private void initialize() { @@ -54,10 +56,13 @@ public class Controller { pauseToggleButton.setSelected(true); } - private void setModel(FirefighterBoard firefighterBoard) { - this.board = requireNonNull(firefighterBoard, "firefighter.model is null"); + private void setModel(Firefighters firefighters , Fire fire ) { + this.board = requireNonNull(firefighters, "firefighter.model is null"); + this.board = requireNonNull(fire, "fire.model is null"); } + + private void updateBoard(){ List<Position> updatedPositions = board.updateToNextGeneration(); List<Pair<Position, ViewElement>> updatedSquares = new ArrayList<>(); @@ -126,10 +131,15 @@ public class Controller { public void initialize(int squareWidth, int squareHeight, int columnCount, int rowCount, int initialFireCount, int initialFirefighterCount) { grid.setDimensions(columnCount, rowCount, squareWidth, squareHeight); - this.setModel(new FirefighterBoard(columnCount, rowCount, initialFireCount, initialFirefighterCount)); + this.setModel(new Firefighters(columnCount, rowCount, initialFirefighterCount , initialFireCount)); repaintGrid(); } + private void setModel(Firefighters firefighters) { + this.board=firefighters + ; + } + public void oneStepButtonAction() { this.pause(); updateBoard(); diff --git a/src/main/java/model/Fire.java b/src/main/java/model/Fire.java new file mode 100644 index 0000000000000000000000000000000000000000..87f15b2b8ea02e069c00dd4ddeb0f6e45f5d0a21 --- /dev/null +++ b/src/main/java/model/Fire.java @@ -0,0 +1,135 @@ +package model; + +import util.Position; + +import java.util.*; + +public class Fire implements Board<List<ModelElement>> { + private final int columnCount; + private final int rowCount; + private final int initialFireCount; + + private List<Position> firefighterPositions; + private Set<Position> firePositions; + private int step = 0; + private final Random randomGenerator = new Random(); + + public Fire(int columnCount , int rowCount , int initialFireCount) { + this.columnCount = columnCount; + this.rowCount= rowCount; + this.initialFireCount=initialFireCount; + this.firePositions = new HashSet<>(); + initializeElements(); + } + public void initializeElements() { + firePositions = new HashSet<>(); + for (int index = 0; index < initialFireCount; index++) + firePositions.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 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); + } + } + + + } + + @Override + public int rowCount() { + return rowCount; + } + + @Override + public int columnCount() { + return columnCount; + } + + @Override + public List<Position> updateToNextGeneration() { + List<Position> modifiedPositions = 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(fire)); + } + firePositions.addAll(newFirePositions); + modifiedPositions.addAll(newFirePositions); + } + return modifiedPositions; + + } + + 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 reset() { + step= 0; + initializeElements(); + + } + + @Override + public int stepNumber() { + return step; + } +} diff --git a/src/main/java/model/FirefighterBoard.java b/src/main/java/model/FirefighterBoard.java index 97abb90182242c43b0dea173a4b0f853b93922b0..5b2e21ae87624dfc95ad4d394181b88eeb90103a 100644 --- a/src/main/java/model/FirefighterBoard.java +++ b/src/main/java/model/FirefighterBoard.java @@ -5,7 +5,7 @@ import util.Position; import java.util.*; -public class FirefighterBoard implements Board<List<ModelElement>> { +/*public class FirefighterBoard implements Board<List<ModelElement>> { private final int columnCount; private final int rowCount; private final int initialFireCount; @@ -154,4 +154,4 @@ public class FirefighterBoard implements Board<List<ModelElement>> { } } } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/main/java/model/Firefighters.java b/src/main/java/model/Firefighters.java new file mode 100644 index 0000000000000000000000000000000000000000..9be24f00f036eb06c5a42671cdb2afce01cf93a4 --- /dev/null +++ b/src/main/java/model/Firefighters.java @@ -0,0 +1,142 @@ +package model; + +import util.Position; + +import java.util.*; + +public class Firefighters implements Board<List<ModelElement>> { + private final int columnCount; + + private final int initialFireCount; + private final int initialFirefighterCount; + private final int rowCount; + private List<Position> firefighterPositions; + private Set<Position> firePositions; + + private int step = 0; + private final Random randomGenerator = new Random(); + + public Firefighters(int columnCount, int rowCount, int initialFirefighterCount, int initialFireCount) { + this.columnCount = columnCount; + this.rowCount = rowCount; + this.initialFireCount = initialFireCount; + this.initialFirefighterCount=initialFirefighterCount; + this.firePositions = new HashSet<>(); + initializeElements(); + } + + private void initializeElements() { + firefighterPositions = new ArrayList<>(); + for (int index = 0; index < initialFirefighterCount; index++) + firefighterPositions.add(randomPosition()); + } + private Position randomPosition() { + return new Position(randomGenerator.nextInt(), 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 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); + } + } + + } + + @Override + public int rowCount() { + return rowCount; + } + + @Override + public int columnCount() { + return columnCount; + } + + @Override + public List<Position> updateToNextGeneration() { + List<Position> modifiedPositions = updateFirefighters(); + + step++; + return modifiedPositions; + } + private List<Position> updateFirefighters() { + List<Position> modifiedPosition = new ArrayList<>(); + List<Position> firefighterNewPositions = new ArrayList<>(); + for (Position firefighterPosition : firefighterPositions) { + Position newFirefighterPosition = neighborClosestToFire(firefighterPosition); + firefighterNewPositions.add(newFirefighterPosition); + extinguish(newFirefighterPosition); + modifiedPosition.add(firefighterPosition); + modifiedPosition.add(newFirefighterPosition); + List<Position> neighborFirePositions = neighbors(newFirefighterPosition).stream() + .filter(firePositions::contains).toList(); + for(Position firePosition : neighborFirePositions) + extinguish(firePosition); + modifiedPosition.addAll(neighborFirePositions); + } + firefighterPositions = firefighterNewPositions; + return modifiedPosition; + } + 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 reset() { + step = 0; + initializeElements(); + + } + + @Override + public int stepNumber() { + return step; + } +}