diff --git a/oolab/src/main/java/agh/ics/oop/OptionsParser.java b/oolab/src/main/java/agh/ics/oop/OptionsParser.java index b4e6d4e..9bc49a9 100644 --- a/oolab/src/main/java/agh/ics/oop/OptionsParser.java +++ b/oolab/src/main/java/agh/ics/oop/OptionsParser.java @@ -19,6 +19,8 @@ public static List Parser(String[] args) { MoveDirectionList.add(MoveDirection.LEFT); } else if (Objects.equals(args[i], "r")) { MoveDirectionList.add(MoveDirection.RIGHT); + } else { + throw new IllegalArgumentException(args[i] + " " + "is not legal move"); } } return MoveDirectionList; diff --git a/oolab/src/main/java/agh/ics/oop/Simulation.java b/oolab/src/main/java/agh/ics/oop/Simulation.java index 563b2f8..8c4ba9f 100644 --- a/oolab/src/main/java/agh/ics/oop/Simulation.java +++ b/oolab/src/main/java/agh/ics/oop/Simulation.java @@ -14,24 +14,28 @@ public Simulation(List positions, List moves, WorldMap this.Map = map; for(Vector2d position : positions) { Animal new_animal = new Animal(position.getX(), position.getY()); - if(map.place(new_animal)) { + try { + map.place(new_animal); Animals.add(new_animal); + } catch (PositionAlreadyOccupiedException e) { + e.printStackTrace(); } + + } } public void run() { - System.out.println(Map); int animal_count = Animals.size(); int cnt = 0; for(MoveDirection currentMove : Moves) { Animal current_animal = Animals.get(0); Animals.remove(0); - Map.move(current_animal, currentMove); System.out.println("Zwierze " + ((cnt % animal_count) + 1) + " " + current_animal.toString()); - System.out.println(Map); + Map.move(current_animal, currentMove); + cnt += 1; Animals.add(current_animal); } diff --git a/oolab/src/main/java/agh/ics/oop/World.java b/oolab/src/main/java/agh/ics/oop/World.java index d383d44..4f11d45 100644 --- a/oolab/src/main/java/agh/ics/oop/World.java +++ b/oolab/src/main/java/agh/ics/oop/World.java @@ -28,13 +28,21 @@ public static void run(List directions) { } } public static void main(String[] args) { - String[] args1 = {"f", "b", "l", "r", "r", "f", "l", "b", "b"}; - List directions = OptionsParser.Parser(args1); - List positions = List.of(new Vector2d(2,2), new Vector2d(3,4), new Vector2d(0,0)); + List directions = new ArrayList<>(); + + String[] args1 = {"f", "f","f","f","f","f","f","f","f","f","f","f","f","f","f","f","f","f","f","f","f"}; + try { + directions = OptionsParser.Parser(args1); + List positions = List.of(new Vector2d(2,2), new Vector2d(3,4), new Vector2d(0,0)); + GrassField map = new GrassField(10); + map.addListener(new ConsoleMapDisplay()); + Simulation sim = new Simulation(positions, directions, map); + sim.run(); + } catch (IllegalArgumentException e){ + e.printStackTrace(); + } + - GrassField map = new GrassField(10); - Simulation sim = new Simulation(positions, directions, map); - sim.run(); } diff --git a/oolab/src/main/java/agh/ics/oop/model/AbstractWorldMap.java b/oolab/src/main/java/agh/ics/oop/model/AbstractWorldMap.java index 6c08af6..de16d73 100644 --- a/oolab/src/main/java/agh/ics/oop/model/AbstractWorldMap.java +++ b/oolab/src/main/java/agh/ics/oop/model/AbstractWorldMap.java @@ -2,6 +2,7 @@ import agh.ics.oop.model.util.MapVisualizer; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -12,14 +13,21 @@ public abstract class AbstractWorldMap implements WorldMap { Vector2d MAP_LEFT_BOTTOM = new Vector2d(0,0); Vector2d MAP_RIGHT_TOP = new Vector2d(0,0); + protected ArrayList listeners = new ArrayList<>(); + + public AbstractWorldMap() { + listeners = new ArrayList<>(); + } + @Override - public boolean place(Animal animal) { + public void place(Animal animal) throws PositionAlreadyOccupiedException{ if (canMoveTo(animal.getPosition())){ animals.put(animal.getPosition(), animal); - return true; + } else { + throw new PositionAlreadyOccupiedException(animal.getPosition()); } - return false; + } @Override @@ -49,6 +57,7 @@ public void move(Animal animal, MoveDirection direction) { int y = animal.getPosition().getY(); Vector2d vec = new Vector2d(x, y); calculateMapSize(vec); + mapChanged(animal, position, animal.getPosition()); } } } @@ -68,4 +77,29 @@ public Map getElements(){ return all_elements; } + + public Boundary getCurrentBounds(){ + return new Boundary(MAP_LEFT_BOTTOM, MAP_RIGHT_TOP); + } + + public String toString() { + return mapVisualizer.draw(getCurrentBounds().MAP_LEFT_BOTTOM(), getCurrentBounds().MAP_RIGHT_TOP()); + } + + public void addListener(MapChangeListener listener) { + listeners.add(listener); + } + + public String mapChanged( Animal animal, Vector2d oldPosition, Vector2d newPosition){ + String result = ""; + if (oldPosition == null){ + result = "New animal placed on the map at " + newPosition.toString(); + } + else{ + result = "Animal moved from " + oldPosition.toString() + " to " + newPosition.toString(); + } + for (MapChangeListener listener : listeners) + listener.mapChanged((WorldMap) this,result); + return result; + } } diff --git a/oolab/src/main/java/agh/ics/oop/model/Boundary.java b/oolab/src/main/java/agh/ics/oop/model/Boundary.java new file mode 100644 index 0000000..8cfba46 --- /dev/null +++ b/oolab/src/main/java/agh/ics/oop/model/Boundary.java @@ -0,0 +1,4 @@ +package agh.ics.oop.model; + +public record Boundary(Vector2d MAP_LEFT_BOTTOM, Vector2d MAP_RIGHT_TOP) { +} diff --git a/oolab/src/main/java/agh/ics/oop/model/ConsoleMapDisplay.java b/oolab/src/main/java/agh/ics/oop/model/ConsoleMapDisplay.java new file mode 100644 index 0000000..cb6f393 --- /dev/null +++ b/oolab/src/main/java/agh/ics/oop/model/ConsoleMapDisplay.java @@ -0,0 +1,16 @@ +package agh.ics.oop.model; + +public class ConsoleMapDisplay implements MapChangeListener{ + private int changescount; + + public ConsoleMapDisplay() { + this.changescount = 0; + } + @Override + public void mapChanged(WorldMap worldMap, String message) { + changescount++; + System.out.println(message); + System.out.println(worldMap.toString()); + System.out.println("Number of changes: " + changescount + "\n\n\n"); + } +} diff --git a/oolab/src/main/java/agh/ics/oop/model/GrassField.java b/oolab/src/main/java/agh/ics/oop/model/GrassField.java index 100b0a6..1007451 100644 --- a/oolab/src/main/java/agh/ics/oop/model/GrassField.java +++ b/oolab/src/main/java/agh/ics/oop/model/GrassField.java @@ -29,12 +29,6 @@ public void generatePositions() { grass.put(position, new Grass(position)); } } - @Override - public String toString() { - return mapVisualizer.draw(MAP_LEFT_BOTTOM, MAP_RIGHT_TOP); - } - - @Override public boolean isOccupied(Vector2d position) { return (super.isOccupied(position) || grass.containsKey(position)); diff --git a/oolab/src/main/java/agh/ics/oop/model/MapChangeListener.java b/oolab/src/main/java/agh/ics/oop/model/MapChangeListener.java new file mode 100644 index 0000000..e0215f8 --- /dev/null +++ b/oolab/src/main/java/agh/ics/oop/model/MapChangeListener.java @@ -0,0 +1,5 @@ +package agh.ics.oop.model; + +public interface MapChangeListener { + void mapChanged(WorldMap worldMap, String message); +} diff --git a/oolab/src/main/java/agh/ics/oop/model/PositionAlreadyOccupiedException.java b/oolab/src/main/java/agh/ics/oop/model/PositionAlreadyOccupiedException.java new file mode 100644 index 0000000..5fc2036 --- /dev/null +++ b/oolab/src/main/java/agh/ics/oop/model/PositionAlreadyOccupiedException.java @@ -0,0 +1,7 @@ +package agh.ics.oop.model; + +public class PositionAlreadyOccupiedException extends Exception { + public PositionAlreadyOccupiedException(Vector2d vec) { + super("Position: " + vec.toString() + " is already occupied"); + } +} diff --git a/oolab/src/main/java/agh/ics/oop/model/RectangularMap.java b/oolab/src/main/java/agh/ics/oop/model/RectangularMap.java index 77b4377..cca8167 100644 --- a/oolab/src/main/java/agh/ics/oop/model/RectangularMap.java +++ b/oolab/src/main/java/agh/ics/oop/model/RectangularMap.java @@ -27,8 +27,4 @@ public Vector2d getMAP_RIGHT_TOP() { public Vector2d getMAP_LEFT_BOTTOM() { return MAP_LEFT_BOTTOM; } - @Override - public String toString(){ - return mapVisualizer.draw(MAP_LEFT_BOTTOM, MAP_RIGHT_TOP); - } } \ No newline at end of file diff --git a/oolab/src/main/java/agh/ics/oop/model/WorldMap.java b/oolab/src/main/java/agh/ics/oop/model/WorldMap.java index 7592b70..bccdd79 100644 --- a/oolab/src/main/java/agh/ics/oop/model/WorldMap.java +++ b/oolab/src/main/java/agh/ics/oop/model/WorldMap.java @@ -17,7 +17,7 @@ public interface WorldMap extends MoveValidator { * @param animal The animal to place on the map. * @return True if the animal was placed. The animal cannot be placed if the move is not valid. */ - boolean place(Animal animal); + void place(Animal animal) throws PositionAlreadyOccupiedException; /** * Moves an animal (if it is present on the map) according to specified direction. diff --git a/oolab/src/test/java/agh/ics/oop/model/GrassFieldTest.java b/oolab/src/test/java/agh/ics/oop/model/GrassFieldTest.java index a80f787..74632d6 100644 --- a/oolab/src/test/java/agh/ics/oop/model/GrassFieldTest.java +++ b/oolab/src/test/java/agh/ics/oop/model/GrassFieldTest.java @@ -17,10 +17,15 @@ public void placeTest() { GrassField map = new GrassField(10); Map finalAnimals = map.getAnimals(); - for(Vector2d position : positions) { - map.place(new Animal(position.getX(), position.getY())); + for (Vector2d position : positions) { + try { + map.place(new Animal(position.getX(), position.getY())); + } catch (PositionAlreadyOccupiedException e){ + e.printStackTrace(); + } } + assertTrue(finalAnimals.containsKey(new Vector2d(3,4))); assertTrue(finalAnimals.containsKey(new Vector2d(0,0))); assertTrue(finalAnimals.containsKey(new Vector2d(2,2))); @@ -32,8 +37,12 @@ public void isOccupiedTest() { List positions = List.of(new Vector2d(2,2), new Vector2d(5,7), new Vector2d(-4,0)); GrassField map = new GrassField(10); - for(Vector2d position : positions) { - map.place(new Animal(position.getX(), position.getY())); + for (Vector2d position : positions) { + try { + map.place(new Animal(position.getX(), position.getY())); + } catch (PositionAlreadyOccupiedException e){ + e.printStackTrace(); + } } assertTrue(map.isOccupied(new Vector2d(2,2))); @@ -46,8 +55,12 @@ public void objectAtTest() { List positions = List.of(new Vector2d(2,2)); GrassField map = new GrassField(10); - for(Vector2d position : positions) { - map.place(new Animal(position.getX(), position.getY())); + for (Vector2d position : positions) { + try { + map.place(new Animal(position.getX(), position.getY())); + } catch (PositionAlreadyOccupiedException e){ + e.printStackTrace(); + } } Animal animal = (Animal) map.objectAt(new Vector2d(2,2)); diff --git a/oolab/src/test/java/agh/ics/oop/model/RectangularMapTest.java b/oolab/src/test/java/agh/ics/oop/model/RectangularMapTest.java index 5cecff2..5a10ed9 100644 --- a/oolab/src/test/java/agh/ics/oop/model/RectangularMapTest.java +++ b/oolab/src/test/java/agh/ics/oop/model/RectangularMapTest.java @@ -17,24 +17,26 @@ public void testCanMoveToBasic(){ assertFalse(rectangularMap.canMoveTo(new Vector2d(5,5))); } @Test - public void testPlace(){ - RectangularMap rectangularMap = new RectangularMap(4,4); - assertTrue(rectangularMap.place(ANIMAL1)); - assertTrue(rectangularMap.place(ANIMAL2)); - assertFalse(rectangularMap.place(new Animal())); - } - @Test public void testIsOccupied(){ RectangularMap rectangularMap = new RectangularMap(4,4); - rectangularMap.place(ANIMAL1); - rectangularMap.place(ANIMAL2); + try { + rectangularMap.place(ANIMAL1); + rectangularMap.place(ANIMAL2); + } catch (PositionAlreadyOccupiedException e) { + e.printStackTrace(); + } + assertFalse(rectangularMap.isOccupied(new Vector2d(0,0))); assertTrue(rectangularMap.isOccupied(VEC11)); } @Test public void testObjectAt(){ RectangularMap rectangularMap = new RectangularMap(4,4); - rectangularMap.place(ANIMAL1); + try { + rectangularMap.place(ANIMAL1); + } catch (PositionAlreadyOccupiedException e) { + e.printStackTrace(); + } assertNull(rectangularMap.objectAt(new Vector2d(0, 0))); assertEquals(ANIMAL1, rectangularMap.objectAt(VEC11)); }