diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java index 154a1b81d01ae5805d59c55456aa57465a1e6b38..f6c0bdffa732d36aec0fe2b895cfcda1fc587948 100644 --- a/src/main/java/controller/Controller.java +++ b/src/main/java/controller/Controller.java @@ -18,8 +18,8 @@ import javafx.scene.control.ToggleGroup; import javafx.util.Duration; import javafx.util.Pair; import model.Board; -import model.Entity; import model.FireFighterScenario; +import model.Square; import util.Position; import view.Grid; import view.ViewElement; @@ -40,7 +40,7 @@ public class Controller { @FXML private Grid<ViewElement> grid; private Timeline timeline; - private Board<Entity> board; + private Board<Square> board; @FXML private void initialize() { @@ -54,7 +54,7 @@ public class Controller { pauseToggleButton.setSelected(true); } - private void setModel(Board<Entity> board) { + private void setModel(Board<Square> board) { this.board = requireNonNull(board, "board is null"); } @@ -62,7 +62,7 @@ public class Controller { List<Position> updatedPositions = board.updateToNextGeneration(); List<Pair<Position, ViewElement>> updatedSquares = new ArrayList<>(); for(Position updatedPosition : updatedPositions){ - Entity squareState = board.getState(updatedPosition); + Square squareState = board.getStates(updatedPosition); ViewElement viewElement = getViewElement(squareState); updatedSquares.add(new Pair<>(updatedPosition, viewElement)); } @@ -76,13 +76,13 @@ 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(Entity entity) { - return new ViewElement(entity.getViewColor()); + private ViewElement getViewElement(Square square) { + return new ViewElement(square.getViewColor()); } private void initializeTimeline() { diff --git a/src/main/java/model/Board.java b/src/main/java/model/Board.java index 1326ce88c7878fd042329c66fe7cdaa66941452f..d88c8974006a6ac4778f9db7251e3dc9afe25e5c 100644 --- a/src/main/java/model/Board.java +++ b/src/main/java/model/Board.java @@ -17,7 +17,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 +25,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, Position position); /** * Get the number of rows in the board. @@ -64,12 +64,20 @@ public interface Board<S> { public int getStepNumber(); // Le booléen replaceState permet de forcer le remplacement des cases vides - public void setState(Entity state, Position position, boolean replaceStates); + public void setSquare(S square, Position position, boolean replaceStates); public boolean doesPositionExist(Position position); public void clearCase(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); } diff --git a/src/main/java/model/EmptySquare.java b/src/main/java/model/EmptySquare.java deleted file mode 100644 index 113ea0a394870345e6520690e083b03c9bb70a7c..0000000000000000000000000000000000000000 --- a/src/main/java/model/EmptySquare.java +++ /dev/null @@ -1,49 +0,0 @@ -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<Entity> 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; - } -} diff --git a/src/main/java/model/Entity.java b/src/main/java/model/Entity.java index 5569aa5ced37576d3776bd79bb3bb58ba675237b..e45030ae6260b4dd91228ff15670c1dd4aeb6692 100644 --- a/src/main/java/model/Entity.java +++ b/src/main/java/model/Entity.java @@ -12,7 +12,7 @@ public interface Entity { * @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<Entity> board); + public List<Position> nextTurn(Board<Square> board); public Position getPosition(); public void setPosition(Position p); public int getAge(); diff --git a/src/main/java/model/EntityScenario.java b/src/main/java/model/EntityScenario.java index 094862a46b940eeefeacb5d0582d5c5a6d250fc8..3845fb55eb1db8a948ab2a9228c597d8637c99f3 100644 --- a/src/main/java/model/EntityScenario.java +++ b/src/main/java/model/EntityScenario.java @@ -4,10 +4,10 @@ import util.Matrix; import util.Position; public abstract class EntityScenario implements Scenario{ - public void initScenario(Matrix<Entity> matrix){ + public void initScenario(Matrix<Square> matrix){ for(int x = 0; x < matrix.getRows(); x++){ for(int y = 0; y < matrix.getColumns(); y++){ - matrix.set(x,y, new EmptySquare(new Position(x, y))); + matrix.set(x,y, new Square(new Position(x, y))); } } } diff --git a/src/main/java/model/Fire.java b/src/main/java/model/Fire.java index 019137ed7268f5d7ff88db50ca42d89afdda1fb2..5019b7b3974c781493530a9ab41b603e612b977d 100644 --- a/src/main/java/model/Fire.java +++ b/src/main/java/model/Fire.java @@ -7,29 +7,29 @@ import util.Position; import util.PositionUtil; public class Fire implements Entity{ - Board<Entity> b; + Board<Square> b; private Position position; private final Color viewColor = Color.RED; private int age; - public Fire(Position position, Board<Entity> b){ + public Fire(Position position, Board<Square> b){ this.b = b; this.position = position; this.age = 0; } - public Fire(Position position, Board<Entity> b, int age){ + public Fire(Position position, Board<Square> b, int age){ this.b = b; this.position = position; this.age = age; } @Override - public List<Position> nextTurn(Board<Entity> board) { + 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.getState(p) instanceof EmptySquare){ - if(b.getState(p).getAge() < b.getStepNumber()){ - board.setState(new Fire(p, board), p); + if(b.getStates(p).isEmpty()){ + if(b.getStates(p).getMaxAge() < b.getStepNumber()){ + board.addEntityAtSquare(new Fire(p, board), p); } } if(!b.doesPositionExist(p)){ diff --git a/src/main/java/model/FireFighter.java b/src/main/java/model/FireFighter.java index e9f2afb2c450b85727fea9a8fba26778a4439fea..0816e5605e727fc83199cc5fb1c9781023299761 100644 --- a/src/main/java/model/FireFighter.java +++ b/src/main/java/model/FireFighter.java @@ -12,16 +12,16 @@ public class FireFighter implements Entity{ private final Color viewColor = Color.BLUE; - public FireFighter(Position position, Board<Entity> b){ + public FireFighter(Position position, Board<Square> b){ this.position = position; this.age = 0; } - public FireFighter(Position position, Board<Entity> b, int age){ + public FireFighter(Position position, Board<Square> b, int age){ this.position = position; this.age = age; } - public List<Position> nextTurn(Board<Entity> b) { + public List<Position> nextTurn(Board<Square> b) { List<Position> positions = new ArrayList<>(); // Générer les positions adjacentes @@ -29,7 +29,7 @@ public class FireFighter implements Entity{ // Vérifier s'il y a du feu dans une des positions adjacentes boolean hasFire = adjacentPositions.stream() - .anyMatch(p -> b.getState(p) instanceof Fire); + .anyMatch(p -> b.doesSquareContainEntity(p, Fire.class)); if (hasFire) { // Si du feu est trouvé, on éteint les feux adjacents @@ -47,7 +47,7 @@ public class FireFighter implements Entity{ b.clearCase(position); // Vider l'ancienne case positions.add(new Position(position.x(), position.y())); this.position = nextPos; - b.setState(this, nextPos); // Mettre à jour la nouvelle case + b.addEntityAtSquare(this, nextPos); // Mettre à jour la nouvelle case positions.add(nextPos); adjacentPositions = PositionUtil.generateAdjacentPositions(nextPos, b); positions.addAll(extinguish(adjacentPositions, b)); @@ -59,10 +59,11 @@ public class FireFighter implements Entity{ return positions; } - private List<Position> extinguish(List<Position> adjacentPositions, Board<Entity> b) { + private List<Position> extinguish(List<Position> adjacentPositions, Board<Square> b) { List<Position> extinguishedPositions = new ArrayList<>(); for (Position p : adjacentPositions) { - if (b.getState(p) instanceof Fire) { + Square s = (Square)b.getStates(p); + if (s.getEntities().stream().anyMatch(e -> e instanceof Fire)) { b.clearCase(p); extinguishedPositions.add(p); // Ajouter la position où le feu a été éteint } @@ -70,12 +71,12 @@ public class FireFighter implements Entity{ return extinguishedPositions; } - private Position getNextPositionTowards(Position currentPos, Position targetPos, Board<Entity> b) { + 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.getState(p) instanceof EmptySquare)); + possibleMoves.removeIf(p -> !(b.isPositionEmpty(p))); // Si aucune position libre n'est disponible, retourner null if (possibleMoves.isEmpty()) { diff --git a/src/main/java/model/FireFighterScenario.java b/src/main/java/model/FireFighterScenario.java index ff4d8d870836c8a5a5b7dfd772adf1319f22662e..987ceda1997e612c3ac2c7a4a930c926cf0a77e9 100644 --- a/src/main/java/model/FireFighterScenario.java +++ b/src/main/java/model/FireFighterScenario.java @@ -10,15 +10,16 @@ import util.Matrix; import util.Position; import util.PositionUtil; -public class FireFighterScenario extends EntityScenario implements Board<Entity> { +public class FireFighterScenario extends EntityScenario implements Board<Square> { - private Matrix<Entity> matrix; + private Matrix<Square> matrix; private int step; private int initialFireCount; private int initialFireFightersCount; + public FireFighterScenario(int columns, int rows, int initialFireCount, int initialFireFightersCount) { - this.matrix = new Matrix<Entity>(columns, rows); + this.matrix = new Matrix<Square>(columns, rows); this.initialFireCount = initialFireCount; this.initialFireFightersCount = initialFireFightersCount; initScenario(matrix); @@ -43,9 +44,9 @@ public class FireFighterScenario extends EntityScenario implements Board<Entity> Collections.shuffle(positions); // Mélange les positions pour un parcours aléatoire for (Position pos : positions) { - if (getState(pos) instanceof EmptySquare) { + if (getStates(pos).isEmpty()) { if (fireCount < initialFireCount && random.nextInt(100) < chance) { - setState(new Fire(pos, this, 1), pos); + setSquare(new Square(pos, new Fire(pos, this, 1)), pos); fireCount++; if (fireCount == initialFireCount && fireFighterCount == initialFireFightersCount) { return; @@ -54,7 +55,7 @@ public class FireFighterScenario extends EntityScenario implements Board<Entity> } if (fireFighterCount < initialFireFightersCount && random.nextInt(100) < chance) { - setState(new FireFighter(pos, this, 1), pos); + setSquare(new Square(pos, new FireFighter(pos, this, 1)), pos); fireFighterCount++; if (fireCount == initialFireCount && fireFighterCount == initialFireFightersCount) { return; @@ -68,7 +69,7 @@ public class FireFighterScenario extends EntityScenario implements Board<Entity> } } - public Entity getState(Position position) { + 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."); @@ -76,20 +77,38 @@ public class FireFighterScenario extends EntityScenario implements Board<Entity> return matrix.get(position.x(), position.y()); } - public void setState(Entity state, Position position) { - if (!(getState(position) instanceof EmptySquare)) { + public void setSquare(Square square, Position position) { + if (!(getStates(position).isEmpty())) { + return; + } + if (doesPositionExist(position)) { + matrix.set(position.x(), position.y(), square); + } + } + + public void setSquare(Square square, Position position, boolean replaceStates) { + 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.set(position.x(), position.y(), state); + matrix.get(position.x(), position.y()).addEntity(entity); + ; } } - public void setState(Entity state, Position position, boolean replaceStates) { - if (!(getState(position) instanceof EmptySquare) && !replaceStates) { + public void addEntityAtSquare(Entity entity, Position position, boolean replaceStates) { + if (!(getStates(position).isEmpty()) && !replaceStates) { return; } - matrix.set(position.x(), position.y(), state); + matrix.get(position.x(), position.y()).addEntity(entity); + ; } public int rowCount() { @@ -99,28 +118,32 @@ public class FireFighterScenario extends EntityScenario implements Board<Entity> public int columnCount() { return matrix.getColumns(); } + @Override - public void clearCase(Position position){ - setState(new EmptySquare(position, step+1), position, true); + public void clearCase(Position position) { + setSquare(new Square(position), position, true); } public List<Position> updateToNextGeneration() { ArrayList<Position> changedPositions = new ArrayList<>(); - Iterator<Entity> iterator = matrix.iterator(); + Iterator<Square> iterator = matrix.iterator(); while (iterator.hasNext()) { - Entity e = iterator.next(); - if (e instanceof EmptySquare) + Square s = iterator.next(); + if (s.isEmpty()) continue; - if (e.getAge() == 0) { - e.incrementAge(); + if (s.getMaxAge() == 0) { + s.incrementAllAges(); continue; } - if(e.getAge() == step+1){ + if (s.getMaxAge() == step + 1) { continue; } - List<Position> entityUpdatedPositions = e.nextTurn(this); - e.incrementAge(); - changedPositions.addAll(entityUpdatedPositions); + for (Entity e : s.getEntities()) { + List<Position> entityUpdatedPositions = e.nextTurn(this); + e.incrementAge(); + changedPositions.addAll(entityUpdatedPositions); + } + } return changedPositions; } @@ -138,11 +161,13 @@ public class FireFighterScenario extends EntityScenario implements Board<Entity> List<Position> positionsAtDistance = PositionUtil.getPositionsAtManhattanDistance(fromPos, distance, rows, cols); for (Position currentPos : positionsAtDistance) { - Entity currentEntity = matrix.get(currentPos.x(), currentPos.y()); - if (entityType.isInstance(currentEntity)) { - // Dès qu'une entité est trouvée à cette distance, elle est la plus proche - // possible - return currentPos; + 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; + } } } } @@ -150,7 +175,6 @@ public class FireFighterScenario extends EntityScenario implements Board<Entity> return nearestPosition; // Retourne null si aucune entité n'est trouvée } - public void reset() { step = 0; matrix.clear(); @@ -172,4 +196,14 @@ public class FireFighterScenario extends EntityScenario implements Board<Entity> 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(); + } } diff --git a/src/main/java/model/Scenario.java b/src/main/java/model/Scenario.java index f4dfc48efe42a5c6945132194a404f757996beba..d491a6542975411890741666160ca88246e544ea 100644 --- a/src/main/java/model/Scenario.java +++ b/src/main/java/model/Scenario.java @@ -3,5 +3,5 @@ package model; import util.Matrix; public interface Scenario { - public void initScenario(Matrix<Entity> matrix); + public void initScenario(Matrix<Square> matrix); } diff --git a/src/main/java/model/Square.java b/src/main/java/model/Square.java index 23acc13a405eaa2c9f290c1d0a79c37a7651909c..98c37e2f40dcf128b79719cd5cbc839484191895 100644 --- a/src/main/java/model/Square.java +++ b/src/main/java/model/Square.java @@ -3,6 +3,7 @@ package model; import java.util.ArrayList; import java.util.List; +import javafx.scene.paint.Color; import util.Position; public class Square { @@ -10,7 +11,6 @@ public class Square { private Position position; public Square(Position position){ this.entities = new ArrayList<Entity>(); - this.entities.add(new EmptySquare(position)); this.position = position; } public Square(Position position, Entity entity){ @@ -38,5 +38,60 @@ public class Square { public void setEntities(List<Entity> entities){ this.entities = entities; } + + public boolean isEmpty(){ + return entities.isEmpty(); + } + + 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); + System.out.println(color.toString()); + return color; + + } + } + } diff --git a/src/main/java/util/PositionUtil.java b/src/main/java/util/PositionUtil.java index 48f5436d9856cd14eb84baf631f8391e8b26bdfe..ce415d5dd41791b18dfaca170f9df06700de521c 100644 --- a/src/main/java/util/PositionUtil.java +++ b/src/main/java/util/PositionUtil.java @@ -6,7 +6,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import model.Board; -import model.Entity; +import model.Square; public class PositionUtil { /** @@ -61,7 +61,7 @@ public class PositionUtil { * si une position existe. * @return une liste des positions adjacentes valides. */ - public static List<Position> generateAdjacentPositions(Position position, Board<Entity> board) { + public static List<Position> generateAdjacentPositions(Position position, Board<Square> board) { int x = position.x(); int y = position.y(); @@ -76,7 +76,7 @@ public class PositionUtil { // Méthode pour générer toutes les positions adjacentes (y compris les // diagonales) - public static List<Position> generateAllAdjacentPositions(Position position, Board<Entity> board) { + public static List<Position> generateAllAdjacentPositions(Position position, Board<Square> board) { int x = position.x(); int y = position.y();