diff --git a/.gradle/8.10.2/executionHistory/executionHistory.lock b/.gradle/8.10.2/executionHistory/executionHistory.lock index 866f8ac5e21dae56dd670743ad8f23dce3fa7855..889b68dfbe83f24c2d46202a32d877e29ef7e2a6 100644 Binary files a/.gradle/8.10.2/executionHistory/executionHistory.lock and b/.gradle/8.10.2/executionHistory/executionHistory.lock differ diff --git a/.gradle/8.10.2/fileHashes/fileHashes.lock b/.gradle/8.10.2/fileHashes/fileHashes.lock index d3e85847bd6f477176e3d0b79c7e5df5ba1f10a5..bca47fff210a99c9b2f0d26f0282decc5029a776 100644 Binary files a/.gradle/8.10.2/fileHashes/fileHashes.lock and b/.gradle/8.10.2/fileHashes/fileHashes.lock differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 9737a6e0e59ba50d3225d012aca741ce63966c10..d03f4645480ef42a4a935d004a2a6567ab21e501 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/src/main/java/app/SimulatorApplication.java b/src/main/java/app/SimulatorApplication.java index e88b0e9856086cc6f53f2782175393dca6365eb6..12878f7c6f4c083a7a742c397ecc44f355e33023 100644 --- a/src/main/java/app/SimulatorApplication.java +++ b/src/main/java/app/SimulatorApplication.java @@ -11,49 +11,51 @@ 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; - public static final int INITIAL_FIRE_COUNT = 3; - public static final int INITIAL_FIREFIGHTER_COUNT = 6; - - private Stage primaryStage; - private Parent view; - private void initializePrimaryStage(Stage primaryStage) { - this.primaryStage = primaryStage; - this.primaryStage.setTitle(APP_NAME); - this.primaryStage.setOnCloseRequest(event -> Platform.exit()); - this.primaryStage.setResizable(true); - this.primaryStage.sizeToScene(); - } - - @Override - public void start(Stage primaryStage) throws IOException { - initializePrimaryStage(primaryStage); - initializeView(); - showScene(); - } - - private void initializeView() throws IOException { - FXMLLoader loader = new FXMLLoader(); - URL location = SimulatorApplication.class.getResource(VIEW_RESOURCE_PATH); - loader.setLocation(location); - view = loader.load(); - Controller controller = loader.getController(); - controller.initialize(BOX_WIDTH, BOX_HEIGHT, COLUMN_COUNT, ROW_COUNT, - INITIAL_FIRE_COUNT, INITIAL_FIREFIGHTER_COUNT); - } - - private void showScene() { - Scene scene = new Scene(view); - primaryStage.setScene(scene); - primaryStage.show(); - } - - public static void main(String[] args) { - launch(args); - } + 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 = 30; + private static final int BOX_HEIGHT = 30; + public static final int INITIAL_FIRE_COUNT = 5; + public static final int INITIAL_FIREFIGHTER_COUNT = 4; + + private Stage primaryStage; + private Parent view; + + private void initializePrimaryStage(Stage primaryStage) { + this.primaryStage = primaryStage; + this.primaryStage.setTitle(APP_NAME); + this.primaryStage.setOnCloseRequest(event -> Platform.exit()); + this.primaryStage.setResizable(false); + this.primaryStage.sizeToScene(); + } + + @Override + public void start(Stage primaryStage) throws IOException { + initializePrimaryStage(primaryStage); + initializeView(); + showScene(); + } + + private void initializeView() throws IOException { + FXMLLoader loader = new FXMLLoader(); + URL location = SimulatorApplication.class.getResource(VIEW_RESOURCE_PATH); + loader.setLocation(location); + view = loader.load(); + + Controller controller = loader.getController(); + controller.initialize(BOX_WIDTH, BOX_HEIGHT, COLUMN_COUNT, ROW_COUNT, + INITIAL_FIRE_COUNT, INITIAL_FIREFIGHTER_COUNT); + } + + private void showScene() { + Scene scene = new Scene(view); + primaryStage.setScene(scene); + primaryStage.show(); + } + + public static void main(String[] args) { + launch(args); + } } diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java index 2a60897c6eb8ba847cb8589840c16a0f175ce0a3..7305525e8f61db2eae6c5ef7227f6dae1597365f 100644 --- a/src/main/java/controller/Controller.java +++ b/src/main/java/controller/Controller.java @@ -1,141 +1,91 @@ package controller; -import javafx.animation.Animation; import javafx.animation.KeyFrame; import javafx.animation.Timeline; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.Label; 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 util.Position; -import view.Grid; -import view.ViewElement; - -import java.util.ArrayList; -import java.util.List; - -import static java.util.Objects.requireNonNull; +import view.FirefighterGrid; public class Controller { - public static final int PERIOD_IN_MILLISECONDS = 50; - @FXML - public Button restartButton; + private FirefighterBoard board; + private Timeline timeline; + @FXML - public Button oneStepButton; + private Label generationNumberLabel; + @FXML - public Label generationNumberLabel; + private Button restartButton; + @FXML - private ToggleButton pauseToggleButton; + private Button oneStepButton; + @FXML private ToggleButton playToggleButton; - @FXML - private Grid<ViewElement> grid; - private Timeline timeline; - private Board<List<ModelElement>> board; @FXML - private void initialize() { - initializePlayAndPauseToggleButtons(); - initializeTimeline(); - } - - private void initializePlayAndPauseToggleButtons() { - ToggleGroup toggleGroup = new PersistentToggleGroup(); - toggleGroup.getToggles().addAll(playToggleButton, pauseToggleButton); - pauseToggleButton.setSelected(true); - } + private ToggleButton pauseToggleButton; - private void setModel(FirefighterBoard firefighterBoard) { - this.board = requireNonNull(firefighterBoard, "firefighter.model is null"); - } + @FXML + private FirefighterGrid grid; - 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); - ViewElement viewElement = getViewElement(squareState); - updatedSquares.add(new Pair<>(updatedPosition, viewElement)); - } - grid.repaint(updatedSquares); - updateGenerationLabel(board.stepNumber()); - } + public void initialize(int boxWidth, int boxHeight, int columns, int rows, int fireCount, int firefighterCount) { + // Initialize the simulation board and connect it to the grid + board = new FirefighterBoard(columns, rows, fireCount, firefighterCount); + grid.initialize(columns, rows, boxWidth, boxHeight, board); - private void repaintGrid(){ - int columnCount = board.columnCount(); - int rowCount = board.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()); - } + // Initialize timeline for automatic progression + timeline = new Timeline(new KeyFrame(Duration.seconds(1), event -> updateGame())); + timeline.setCycleCount(Timeline.INDEFINITE); - 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; + // Ensure initial UI state is consistent + updateGenerationLabel(); + pauseToggleButton.setSelected(true); } - private void initializeTimeline() { - Duration duration = new Duration(Controller.PERIOD_IN_MILLISECONDS); - EventHandler<ActionEvent> eventHandler = - event -> updateBoard(); - KeyFrame keyFrame = new KeyFrame(duration, eventHandler); - timeline = new Timeline(keyFrame); - timeline.setCycleCount(Animation.INDEFINITE); - } - public void play() { - timeline.play(); + @FXML + private void restartButtonAction() { + stopSimulation(); + board.reset(); + grid.repaint(); + updateGenerationLabel(); } - - public void pause() { - timeline.pause(); + @FXML + private void oneStepButtonAction() { + stopSimulation(); + updateGame(); } - public void pauseToggleButtonAction() { - this.pause(); + @FXML + private void playToggleButtonAction() { + startSimulation(); } - public void playToggleButtonAction() { - this.play(); + @FXML + private void pauseToggleButtonAction() { + stopSimulation(); } - public void restartButtonAction() { - this.pause(); - board.reset(); - pauseToggleButton.setSelected(true); - repaintGrid(); + private void startSimulation() { + timeline.play(); } - 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)); - repaintGrid(); + private void stopSimulation() { + timeline.stop(); } - public void oneStepButtonAction() { - this.pause(); - updateBoard(); + private void updateGame() { + board.updateToNextGeneration(); + grid.repaint(); + updateGenerationLabel(); } - private void updateGenerationLabel(int value){ - generationNumberLabel.setText(Integer.toString(value)); + private void updateGenerationLabel() { + generationNumberLabel.setText(String.valueOf(board.stepNumber())); } -} \ No newline at end of file +} diff --git a/src/main/java/model/FireManager.java b/src/main/java/model/FireManager.java index 7a8f0b4882120cf79969a55cd2023dfbc0aabfa0..c8d2f3d53b0fc8841c944838de216ce8b0a22424 100644 --- a/src/main/java/model/FireManager.java +++ b/src/main/java/model/FireManager.java @@ -5,26 +5,30 @@ import util.Position; import java.util.*; public class FireManager { - private Set<Position> firePositions = new HashSet<>(); + private Set<Position> firePositions; private FireSpreadStrategy fireSpreadStrategy; - public FireManager(FireSpreadStrategy fireSpread) { - this.fireSpreadStrategy = fireSpread; + public FireManager(FireSpreadStrategy fireSpreadStrategy) { + this.firePositions = new HashSet<>(); + this.fireSpreadStrategy = fireSpreadStrategy; } + public void initializeFires(int fireCount, int rowCount, int columnCount, Random random) { + // Initialize fire positions randomly on the grid for (int i = 0; i < fireCount; i++) { firePositions.add(new Position(random.nextInt(rowCount), random.nextInt(columnCount))); } } - public List<Position> fireSpread(Map<Position, List<Position>> neighbors){ - List<Position> newFirePositions = fireSpreadStrategy.spreadFire(firePositions, neighbors); - firePositions.addAll(newFirePositions); - return newFirePositions; - } - public void extinguish(Position position){ - firePositions.remove(position); - } + public Set<Position> getFirePositions() { return firePositions; } + + public List<Position> spreadFire(Map<Position, List<Position>> neighbors) { + return fireSpreadStrategy.spreadFire(firePositions, neighbors); + } + + public void extinguish(Position position) { + firePositions.remove(position); + } } diff --git a/src/main/java/model/FireSpreadStrategy.java b/src/main/java/model/FireSpreadStrategy.java index a775891351fe0a721567e1a33f99d43078cb151a..ef9f02549a5c6f0b67e6b86565710a82f37b5433 100644 --- a/src/main/java/model/FireSpreadStrategy.java +++ b/src/main/java/model/FireSpreadStrategy.java @@ -7,5 +7,5 @@ import java.util.Map; import java.util.Set; public interface FireSpreadStrategy { - List<Position> spreadFire(Set<Position> positions, Map<Position, List<Position>> neighbors); + List<Position> spreadFire(Set<Position> firePositions, Map<Position, List<Position>> neighbors); } diff --git a/src/main/java/model/FirefighterBoard.java b/src/main/java/model/FirefighterBoard.java index ea6f8034b0eeaac4c5c9e5ff81b8c67bfc808913..3bd737677b6eaa78fe6452f70b0dd4818ec4349b 100644 --- a/src/main/java/model/FirefighterBoard.java +++ b/src/main/java/model/FirefighterBoard.java @@ -1,61 +1,78 @@ package model; import util.Position; - +import javafx.util.Pair; 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 List<Position> firefighterPositions; + private Set<Position> firePositions; + private final Map<Position, List<Position>> neighbors; + private final Position[][] positions; - private int rowCount; - private int columnCount; - private final FireManager fireManager; - private final FirefighterManager firefighterManager; - private final NeighborManager neighborManager; - private int step; + private int step = 0; + // Constructor for FirefighterBoard public FirefighterBoard(int columnCount, int rowCount, int initialFireCount, int initialFirefighterCount) { this.columnCount = columnCount; this.rowCount = rowCount; - this.neighborManager = new NeighborManager(rowCount, columnCount); + this.initialFireCount = initialFireCount; + this.initialFirefighterCount = initialFirefighterCount; - this.fireManager = new FireManager(new SimpleFireSpreadStrategy()); - this.firefighterManager = new FirefighterManager(new SimpleFirefighterMovementStrategy()); + this.positions = new Position[rowCount][columnCount]; + this.firefighterPositions = new ArrayList<>(); + this.firePositions = new HashSet<>(); + this.neighbors = new HashMap<>(); - Random random = new Random(); - fireManager.initializeFires(initialFireCount, rowCount,columnCount, random); - firefighterManager.initializeFireFightersPositions(initialFirefighterCount,rowCount,columnCount,random); - this.step = 0; + initializeBoard(); } - @Override - public List<ModelElement> getState(Position position) { - List<ModelElement> elements = new ArrayList<>(); + private void initializeBoard() { + Random random = new Random(); - // Check if the position contains a fire - if (fireManager.getFirePositions().contains(position)) { - elements.add(ModelElement.FIRE); + // Initialize fire positions + for (int i = 0; i < initialFireCount; i++) { + firePositions.add(new Position(random.nextInt(rowCount), random.nextInt(columnCount))); } - // Check if the position contains a firefighter - if (firefighterManager.getFirefighterPositions().contains(position)) { - elements.add(ModelElement.FIREFIGHTER); + // Initialize firefighter positions + for (int i = 0; i < initialFirefighterCount; i++) { + firefighterPositions.add(new Position(random.nextInt(rowCount), random.nextInt(columnCount))); } - return elements; + // Initialize neighbors map + for (int row = 0; row < rowCount; row++) { + for (int col = 0; col < columnCount; col++) { + positions[row][col] = new Position(row, col); + neighbors.put(positions[row][col], calculateNeighbors(row, col)); + } + } } - @Override - public void setState(List<ModelElement> state, Position position) { - fireManager.extinguish(position); - firefighterManager.getFirefighterPositions().remove(position); + private List<Position> calculateNeighbors(int row, int col) { + List<Position> adjacentPositions = new ArrayList<>(); + if (row > 0) adjacentPositions.add(new Position(row - 1, col)); // Top neighbor + if (col > 0) adjacentPositions.add(new Position(row, col - 1)); // Left neighbor + if (row < rowCount - 1) adjacentPositions.add(new Position(row + 1, col)); // Bottom neighbor + if (col < columnCount - 1) adjacentPositions.add(new Position(row, col + 1)); // Right neighbor + return adjacentPositions; + } - // Add elements based on the new state - for (ModelElement element : state) { - switch (element) { - case FIRE -> fireManager.getFirePositions().add(position); - case FIREFIGHTER -> firefighterManager.getFirefighterPositions().add(position); - } + @Override + public List<ModelElement> getState(Position position) { + List<ModelElement> result = new ArrayList<>(); + if (firefighterPositions.contains(position)) { + result.add(ModelElement.FIREFIGHTER); + } + if (firePositions.contains(position)) { + result.add(ModelElement.FIRE); } + return result; } @Override @@ -69,59 +86,91 @@ public class FirefighterBoard implements Board<List<ModelElement>> { } @Override - public List<Position> updateToNextGeneration() { - List<Position> modifiedPositions = new ArrayList<>(); - - // Spread the fires and update affected positions - modifiedPositions.addAll(fireManager.fireSpread(neighborManager.getNeighbors())); - - // Move firefighters and update affected positions - modifiedPositions.addAll(firefighterManager.moveFireFighters( - fireManager.getFirePositions(), - neighborManager.getNeighbors() - )); - - // Increment the step count - step++; - - return modifiedPositions; + public int stepNumber() { + return step; } @Override public void reset() { - // Reset step and reinitialize managers - this.step = 0; - - Random random = new Random(); - fireManager.getFirePositions().clear(); - firefighterManager.getFirefighterPositions().clear(); + step = 0; + firefighterPositions.clear(); + firePositions.clear(); - fireManager.initializeFires(fireManager.getFirePositions().size(), rowCount, columnCount, random); - firefighterManager.initializeFireFightersPositions( - firefighterManager.getFirefighterPositions().size(), rowCount, columnCount, random - ); + initializeBoard(); // Reinitialize the board } @Override - public int stepNumber() { - return step; - } -} - - - + public void setState(List<ModelElement> state, Position position) { + firePositions.remove(position); + firefighterPositions.remove(position); + for (ModelElement element : state) { + switch (element) { + case FIRE -> firePositions.add(position); + case FIREFIGHTER -> firefighterPositions.add(position); + } + } + } + @Override + public List<Position> updateToNextGeneration() { + List<Position> modifiedPositions = new ArrayList<>(); + // Spread fire every two rounds + if (step % 2 == 0) { + firePositions.addAll(spreadFire()); + modifiedPositions.addAll(firePositions); + } + // Update firefighter positions + FirefighterManager firefighterManager = new FirefighterManager(new SimpleFirefighterMovementStrategy()); + List<Position> firefighterModified = firefighterManager.moveFireFighters(firePositions, neighbors); + modifiedPositions.addAll(firefighterModified); + firefighterPositions = firefighterManager.getFirefighterPositions(); + // After firefighters move, extinguish fire in the neighborhood + extinguishNearbyFire(modifiedPositions); + step++; + return modifiedPositions; + } + private Set<Position> spreadFire() { + Set<Position> newFirePositions = new HashSet<>(); + for (Position firePosition : firePositions) { + newFirePositions.addAll(neighbors.get(firePosition)); // Spread fire to neighbors + } + return newFirePositions; + } + private void extinguishNearbyFire(List<Position> modifiedPositions) { + for (Position firefighterPosition : firefighterPositions) { + List<Position> nearbyFires = neighbors.get(firefighterPosition); + for (Position neighbor : nearbyFires) { + if (firePositions.contains(neighbor)) { + firePositions.remove(neighbor); // Extinguish fire in neighboring positions + modifiedPositions.add(neighbor); + } + } + } + } + public List<Pair<Position, ModelElement>> getUpdatedElements() { + List<Pair<Position, ModelElement>> updatedElements = new ArrayList<>(); + // Add fire positions + for (Position firePosition : firePositions) { + updatedElements.add(new Pair<>(firePosition, ModelElement.FIRE)); + } + // Add firefighter positions + for (Position firefighterPosition : firefighterPositions) { + updatedElements.add(new Pair<>(firefighterPosition, ModelElement.FIREFIGHTER)); + } + return updatedElements; + } +} diff --git a/src/main/java/model/FirefighterManager.java b/src/main/java/model/FirefighterManager.java index b057e09ca466002a7e54b8ddbaa57ed2d6047b32..ec12a1350431a100df56266a7742ff841628f078 100644 --- a/src/main/java/model/FirefighterManager.java +++ b/src/main/java/model/FirefighterManager.java @@ -5,31 +5,50 @@ import util.Position; import java.util.*; public class FirefighterManager { - private List<Position> firefighterPositions = new ArrayList<>(); - private FirefighterMovementStrategy firefighterMovementStrategy; + private List<Position> firefighterPositions; + private FirefighterMovementStrategy movementStrategy; - public FirefighterManager(FirefighterMovementStrategy firefighterMovementStrategy) { - this.firefighterMovementStrategy = firefighterMovementStrategy; + public FirefighterManager(FirefighterMovementStrategy movementStrategy) { + this.movementStrategy = movementStrategy; + firefighterPositions = new ArrayList<>(); } + public void initializeFireFightersPositions(int count, int rowCount, int columnCount, Random random) { + // Initialize firefighter positions randomly on the grid for (int i = 0; i < count; i++) { firefighterPositions.add(new Position(random.nextInt(rowCount), random.nextInt(columnCount))); } } + public List<Position> moveFireFighters(Set<Position> firePositions, Map<Position, List<Position>> neighbors) { List<Position> modifiedPositions = new ArrayList<>(); List<Position> newPositions = new ArrayList<>(); - for( Position currentposition : firefighterPositions) { - Position newPosition = firefighterMovementStrategy.moveToClosestFire(currentposition, firePositions, neighbors); - modifiedPositions.add(currentposition); - modifiedPositions.add(newPosition); + for (Position firefighterPosition : firefighterPositions) { + // Move firefighters towards the nearest fire + Position newPosition = movementStrategy.moveToClosestFire(firefighterPosition, firePositions, neighbors); + + // Extinguish fire in the neighboring cells + List<Position> nearbyFires = neighbors.get(newPosition); + for (Position firePosition : nearbyFires) { + if (firePositions.contains(firePosition)) { + firePositions.remove(firePosition); // Extinguish the fire + modifiedPositions.add(firePosition); // Track the modified fire position + } + } + + // Update the firefighter's new position newPositions.add(newPosition); + modifiedPositions.add(firefighterPosition); // Track the original firefighter position + modifiedPositions.add(newPosition); // Track the new firefighter position } - firefighterPositions = newPositions; + + firefighterPositions = newPositions; // Update the firefighter positions list with new positions return modifiedPositions; } + public List<Position> getFirefighterPositions() { return firefighterPositions; } } + diff --git a/src/main/java/model/ModelElement.java b/src/main/java/model/ModelElement.java index 759eee5e54c3a39472d8f7defbbbe6a2b67b8f00..5212cc5dc358e893318e4c01fb2926782f07b496 100644 --- a/src/main/java/model/ModelElement.java +++ b/src/main/java/model/ModelElement.java @@ -1,5 +1,16 @@ package model; + public enum ModelElement { - FIREFIGHTER, FIRE + FIREFIGHTER("blue"), FIRE("red"); + + private final String color; + + ModelElement(String color) { + this.color = color; + } + + public String getColor() { + return color; + } } diff --git a/src/main/java/model/SimpleFireSpreadStrategy.java b/src/main/java/model/SimpleFireSpreadStrategy.java index af5438d7a352124c299e18111432dc2e9ceb2fd6..b03eb0f16bdbd7388f91de5d64a5bb2e680ad432 100644 --- a/src/main/java/model/SimpleFireSpreadStrategy.java +++ b/src/main/java/model/SimpleFireSpreadStrategy.java @@ -1,18 +1,15 @@ package model; import util.Position; - -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.ArrayList; +import java.util.*; public class SimpleFireSpreadStrategy implements FireSpreadStrategy { + @Override - public List<Position> spreadFire(Set<Position> positions, Map<Position, List<Position>> neighbors) { + public List<Position> spreadFire(Set<Position> firePositions, Map<Position, List<Position>> neighbors) { List<Position> newFirePositions = new ArrayList<>(); - for (Position fire : positions) { - newFirePositions.addAll(neighbors.get(fire)); + for (Position fire : firePositions) { + newFirePositions.addAll(neighbors.getOrDefault(fire, List.of())); } return newFirePositions; } diff --git a/src/main/java/model/SimpleFirefighterMovementStrategy.java b/src/main/java/model/SimpleFirefighterMovementStrategy.java index b76d2c13562c958d9cf44d7ad0e7fc042cb076d2..8257204d68738111737056180309f5632b67fe23 100644 --- a/src/main/java/model/SimpleFirefighterMovementStrategy.java +++ b/src/main/java/model/SimpleFirefighterMovementStrategy.java @@ -2,9 +2,7 @@ package model; import util.Position; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public class SimpleFirefighterMovementStrategy implements FirefighterMovementStrategy { @Override @@ -24,8 +22,8 @@ public class SimpleFirefighterMovementStrategy implements FirefighterMovementStr } private int calculateDistance(Position a, Position b) { + // Use Manhattan distance return Math.abs(a.getRow() - b.getRow()) + Math.abs(a.getCol() - b.getCol()); - - } } + diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 4c36d97709b342e457203c75d081fc5cc1955c0f..60722c4f2d818d7d53a64a6dce509fa6eb0a48a3 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -5,4 +5,5 @@ module firefighter { opens controller to javafx.fxml; exports app; opens app to javafx.fxml; + opens view to javafx.fxml; } diff --git a/src/main/java/view/FirefighterGrid.java b/src/main/java/view/FirefighterGrid.java index 4c9041f034ec9a4eb07ce4334de237f1e99ccdc9..ab926abfa39a23b8fdf3fb818e03f25bd1f78c53 100644 --- a/src/main/java/view/FirefighterGrid.java +++ b/src/main/java/view/FirefighterGrid.java @@ -1,99 +1,70 @@ package view; import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; import javafx.scene.paint.Color; import javafx.util.Pair; +import model.ModelElement; +import model.FirefighterBoard; import util.Position; -import java.util.List; +public class FirefighterGrid extends Canvas { -public class FirefighterGrid extends Canvas implements Grid<ViewElement>{ - - private void paintElementAtPosition(ViewElement element, Position position) { - paintBox(position.row(), position.column(), element.color); - } + private int columns; + private int rows; private int boxWidth; private int boxHeight; - private int columnCount; - private int rowCount; - - @Override - public void repaint(List<Pair<Position, ViewElement>> positionedElements) { - clear(positionedElements); - paint(positionedElements); - paintLines(); - } + private FirefighterBoard board; - private void clear(List<Pair<Position, ViewElement>> positionedElements) { - for (Pair<Position, ViewElement> positionElement : positionedElements) { - Position position = positionElement.getKey(); - clearBox(position.row(), position.column()); - } - } - - private void paint(List<Pair<Position, ViewElement>> positionedElements) { - for(Pair<Position, ViewElement> pair : positionedElements){ - paintElementAtPosition(pair.getValue(), pair.getKey()); - } - } - - @Override - public void repaint(ViewElement[][] elements) { - clear(); - paint(elements); - paintLines(); - } - - private void clear() { - getGraphicsContext2D().clearRect(0,0,getWidth(), getHeight()); - } - - private void paint(ViewElement[][] elements) { - for(int column = 0; column < columnCount; column++) - for(int row = 0; row < rowCount; row++){ - paintElementAtPosition(elements[row][column], new Position(row, column)); - } - } - - public int columnCount() { - return columnCount; - } - - public int rowCount() { - return rowCount; - } - - @Override - public void setDimensions(int columnCount, int rowCount, int boxWidth, int boxHeight) { + // Initialize the grid dimensions and board reference + public void initialize(int columns, int rows, int boxWidth, int boxHeight, FirefighterBoard board) { + this.columns = columns; + this.rows = rows; this.boxWidth = boxWidth; this.boxHeight = boxHeight; - this.columnCount = columnCount; - this.rowCount = rowCount; - super.setWidth(boxWidth * columnCount); - super.setHeight(boxHeight * rowCount); - } - - private void paintLines(){ - paintHorizontalLines(); - paintVerticalLines(); + this.board = board; + setWidth(columns * boxWidth); // Set canvas width based on grid size + setHeight(rows * boxHeight); // Set canvas height based on grid size } - private void paintVerticalLines() { - for(int column = 0; column < columnCount; column++) - getGraphicsContext2D().strokeLine(column * boxWidth, 0,column * boxWidth, getHeight()); - } + // Repaint the grid and all elements (fire and firefighter) + public void repaint() { + if (board == null) return; // Exit if board is not set + GraphicsContext gc = getGraphicsContext2D(); + gc.clearRect(0, 0, getWidth(), getHeight()); // Clear the canvas before drawing + + // Iterate over the list of updated elements (positions and elements like fire or firefighter) + for (Pair<Position, ModelElement> pair : board.getUpdatedElements()) { + Position position = pair.getKey(); // Get the Position from the Pair + ModelElement element = pair.getValue(); // Get the ModelElement (either FIRE or FIREFIGHTER) + + // Set the color based on the element type + if (element == ModelElement.FIRE) { + gc.setFill(Color.RED); // Fire is red + } else if (element == ModelElement.FIREFIGHTER) { + gc.setFill(Color.BLUE); // Firefighter is blue + } else { + gc.setFill(Color.WHITE); // Empty space is white + } - private void paintHorizontalLines() { - for(int row = 0; row < rowCount; row++) - getGraphicsContext2D().strokeLine(0, row * boxHeight, getWidth(), row * boxHeight); - } + // Draw the element on the grid at the appropriate position + gc.fillRect(position.getCol() * boxWidth, position.getRow() * boxHeight, boxWidth, boxHeight); + gc.setStroke(Color.LIGHTGRAY); // Grid border color + gc.strokeRect(position.getCol() * boxWidth, position.getRow() * boxHeight, boxWidth, boxHeight); + } - private void paintBox(int row, int column, Color color){ - getGraphicsContext2D().setFill(color); - getGraphicsContext2D().fillRect(column * boxWidth,row * boxHeight, boxWidth, boxHeight); + // Optionally, draw the grid lines on top of the elements + drawGridLines(gc); } - private void clearBox(int row, int column){ - getGraphicsContext2D().clearRect(column * boxWidth,row * boxHeight, boxWidth, boxHeight); + // Helper method to draw the grid lines + private void drawGridLines(GraphicsContext gc) { + gc.setStroke(Color.GRAY); + for (int col = 0; col < columns; col++) { + gc.strokeLine(col * boxWidth, 0, col * boxWidth, getHeight()); // Vertical lines + } + for (int row = 0; row < rows; row++) { + gc.strokeLine(0, row * boxHeight, getWidth(), row * boxHeight); // Horizontal lines + } } -} \ No newline at end of file +} diff --git a/src/main/java/view/ViewElement.java b/src/main/java/view/ViewElement.java index ffb76112e1af543df5af41fa906082ef11be9967..f0a7922c36e72b5c7419e01f27d5845f770e9b9e 100644 --- a/src/main/java/view/ViewElement.java +++ b/src/main/java/view/ViewElement.java @@ -4,7 +4,9 @@ import javafx.scene.paint.Color; public enum ViewElement { FIREFIGHTER(Color.BLUE), FIRE(Color.RED), EMPTY(Color.WHITE); + final Color color; + ViewElement(Color color) { this.color = color; }