diff --git a/README.md b/README.md index 9871bab..cb41fb6 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ to be able to dominate your friends. #Rules 1. The min. Player amount is 2 and the max. Player amount is 4. -2. Each Player can build a road and a settlement free of cost at the beginning of -the game. +2. Each Player can build two roads and two settlements free of cost at the beginning of +the game. After the placement, each player gets resources from the field around the second settlement. 3. Every Player is being sorted into a faction. There cannot be two players in the same faction. 4. A player cannot build two settlements or cities right next one another. @@ -25,7 +25,7 @@ For a more detailed version of the rules please look here: https://www.catan.de/ #Usermanual First the program will ask how many players will be playing the game. The minimum amount of players is 2 and the maximum amount of players is 4. Each player will -be appointed to a faction. Now every player can build a settlement and a road +be appointed to a faction. In the next step, the program ask for the number of win points. The first player who reaches this number of win points, will win the game. Now every player can build a settlement and a road after every player has built a settlement and road, they can build a second settlement and road in reversed order. When the players build their second settlement they then receive the resources surrounding that specific settlement. diff --git a/src/ch/zhaw/catan/SiedlerGame.java b/src/ch/zhaw/catan/SiedlerGame.java index 23057fa..7e14467 100644 --- a/src/ch/zhaw/catan/SiedlerGame.java +++ b/src/ch/zhaw/catan/SiedlerGame.java @@ -30,8 +30,8 @@ public class SiedlerGame { * * @param winPoints the number of points required to win the game * @param numberOfPlayers the number of players - * @throws IllegalArgumentException if winPoints is lower than - * three or players is not between two and four + * @throws IllegalArgumentException if winPoints is lower than 3 + * or players is not between two and four */ public SiedlerGame(int winPoints, int numberOfPlayers) { if (winPoints < 3 || numberOfPlayers < Config.MIN_NUMBER_OF_PLAYERS || numberOfPlayers > 4) { diff --git a/test/ch/zhaw/catan/SiedlerBoardTest.java b/test/ch/zhaw/catan/SiedlerBoardTest.java new file mode 100644 index 0000000..f083917 --- /dev/null +++ b/test/ch/zhaw/catan/SiedlerBoardTest.java @@ -0,0 +1,57 @@ +package ch.zhaw.catan; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.awt.*; +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class SiedlerBoardTest { + + @Nested + class LongestRoadTest { + /** + * To Test getLongestRoad in SiedlerBoard + */ + + List factionList = Arrays.asList(Config.Faction.values()); + + SiedlerBoard board = new SiedlerBoard(); + + @BeforeEach + public void buildLongestRoad(){ + board.createFixGameField(); + board.setEdge(new Point(6, 6), new Point(5, 7), new Road(Config.Faction.BLUE, new Point(6, 6), new Point(5, 7))); + board.setEdge(new Point(4, 6), new Point(5, 7), new Road(Config.Faction.BLUE, new Point(4, 6), new Point(5, 7))); + board.setEdge(new Point(4, 6), new Point(4, 4), new Road(Config.Faction.BLUE, new Point(4, 6), new Point(4, 4))); + board.setEdge(new Point(4, 6), new Point(3, 7), new Road(Config.Faction.BLUE, new Point(4, 6), new Point(3, 7))); + board.setEdge(new Point(3, 7), new Point(3, 9), new Road(Config.Faction.BLUE, new Point(3, 7), new Point(3, 9))); + board.setEdge(new Point(3, 9), new Point(4, 10), new Road(Config.Faction.BLUE, new Point(3, 9), new Point(4, 10))); + board.setEdge(new Point(4, 10), new Point(5, 9), new Road(Config.Faction.BLUE, new Point(4, 10), new Point(5, 9))); + board.setCorner(new Point(3, 7), new Settlement(Config.Faction.BLUE, new Point(3, 7))); + + } + + @Test + public void testLongestRoadSimple() { + System.out.println(board.getTextView()); + + assertEquals(Config.Faction.BLUE, board.getLongestRoadFaction(factionList)); + assertEquals(6, board.getLongestRoadLenth()); + } + + @Test + public void testLongestRoadWithInterrupt() { + board.setCorner(new Point(4, 10), new Settlement(Config.Faction.RED, new Point(4, 10))); + System.out.println(board.getTextView()); + + assertEquals(Config.Faction.BLUE, board.getLongestRoadFaction(factionList)); + assertEquals(5, board.getLongestRoadLenth()); + } + } + +} diff --git a/test/ch/zhaw/catan/SiedlerGameTest.java b/test/ch/zhaw/catan/SiedlerGameTest.java index b9f2606..a1045e0 100644 --- a/test/ch/zhaw/catan/SiedlerGameTest.java +++ b/test/ch/zhaw/catan/SiedlerGameTest.java @@ -1,10 +1,11 @@ package ch.zhaw.catan; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; -import ch.zhaw.catan.games.ThreePlayerStandard; import org.junit.jupiter.api.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import java.awt.*; import java.util.*; @@ -25,52 +26,63 @@ public class SiedlerGameTest { private final static int DEFAULT_WINPOINTS = 5; private final static int DEFAULT_PLAYERAMOUNT = 4; + /** + * Property START_SETTLEMENT_POSITIONS + * + * Lists all positions of Settlement for every faction in the initialization phase. + * Each faction is assigned to a list of specific settlements, which represents as a list of points + */ + private final static Map> START_SETTLEMENT_POSITIONS = Map.of( + Config.Faction.BLUE, new ArrayList<>(List.of(new Point(4, 4), new Point(5, 7))), + Config.Faction.RED, new ArrayList<>(List.of(new Point(10, 4), new Point(9, 7))), + Config.Faction.GREEN, new ArrayList<>(List.of(new Point(4, 18), new Point(5, 15))), + Config.Faction.YELLOW, new ArrayList<>(List.of(new Point(10, 18), new Point(9, 15))) + ); + /** + * START_ROADS_POSITION + * + * Lists all endpoints of roads for every faction in the initialization phase. + * Each faction is assigned to a specific Road, which represents as a tuple of 2 points + */ + private final static Map>> START_ROADS_POSITIONS = Map.of( + Config.Faction.BLUE, new ArrayList<>(List.of( + new Tuple<>(new Point(4, 4), new Point(4, 6)), new Tuple<>(new Point(4, 6), new Point(5, 7)))), + Config.Faction.RED, new ArrayList<>(List.of( + new Tuple<>(new Point(10, 4), new Point(10, 6)), new Tuple<>(new Point(10, 6), new Point(9, 7)))), + Config.Faction.GREEN, new ArrayList<>(List.of( + new Tuple<>(new Point(4, 18), new Point(4, 16)), new Tuple<>(new Point(4, 16), new Point(5, 15)))), + Config.Faction.YELLOW, new ArrayList<>(List.of( + new Tuple<>(new Point(10, 18), new Point(10, 16)), new Tuple<>(new Point(10, 16), new Point(9, 15)))) + ); + /** + * This test class contains all positive test cases. + */ @Nested @DisplayName("Positive test cases") class PositiveTestcases { - @Nested - class LongestRoadTest { - /** - * To Test getLongestRoad in SiedlerBoard - */ + /** + * This test will check, if the game initializes with all 4 factions. + * All factions should have no resources + */ + @ParameterizedTest(name = "Test with {arguments} players") + @ValueSource(ints = {2, 3, 4}) + @DisplayName("Game initializing with different amount of players within the domain (Players have no resources), expected ok") + public void TestGameInitializationWithAllPlayercounts(int playerAmount) { + SiedlerGame game = new SiedlerGame(DEFAULT_WINPOINTS, playerAmount); - List factionList = Arrays.asList(Config.Faction.values()); + for (Config.Faction faction: game.getPlayerFactions()) { + HashMap resources = game.getCurrentPlayerResource(); - SiedlerBoard board = new SiedlerBoard(); + Assertions.assertEquals(0, resources.get(Config.Resource.BRICK)); + Assertions.assertEquals(0, resources.get(Config.Resource.GRAIN)); + Assertions.assertEquals(0, resources.get(Config.Resource.LUMBER)); + Assertions.assertEquals(0, resources.get(Config.Resource.ORE)); + Assertions.assertEquals(0, resources.get(Config.Resource.WOOL)); - - @BeforeEach - public void buildLongestRoad(){ - board.createFixGameField(); - board.setEdge(new Point(6, 6), new Point(5, 7), new Road(Config.Faction.BLUE, new Point(6, 6), new Point(5, 7))); - board.setEdge(new Point(4, 6), new Point(5, 7), new Road(Config.Faction.BLUE, new Point(4, 6), new Point(5, 7))); - board.setEdge(new Point(4, 6), new Point(4, 4), new Road(Config.Faction.BLUE, new Point(4, 6), new Point(4, 4))); - board.setEdge(new Point(4, 6), new Point(3, 7), new Road(Config.Faction.BLUE, new Point(4, 6), new Point(3, 7))); - board.setEdge(new Point(3, 7), new Point(3, 9), new Road(Config.Faction.BLUE, new Point(3, 7), new Point(3, 9))); - board.setEdge(new Point(3, 9), new Point(4, 10), new Road(Config.Faction.BLUE, new Point(3, 9), new Point(4, 10))); - board.setEdge(new Point(4, 10), new Point(5, 9), new Road(Config.Faction.BLUE, new Point(4, 10), new Point(5, 9))); - board.setCorner(new Point(3, 7), new Settlement(Config.Faction.BLUE, new Point(3, 7))); - - } - - @Test - public void testLongestRoadSimple() { - System.out.println(board.getTextView()); - - assertEquals(Config.Faction.BLUE, board.getLongestRoadFaction(factionList)); - assertEquals(6, board.getLongestRoadLenth()); - } - - @Test - public void testLongestRoadWithInterrupt() { - board.setCorner(new Point(4, 10), new Settlement(Config.Faction.RED, new Point(4, 10))); - System.out.println(board.getTextView()); - - assertEquals(Config.Faction.BLUE, board.getLongestRoadFaction(factionList)); - assertEquals(5, board.getLongestRoadLenth()); + game.switchToNextPlayer(); } } @@ -81,55 +93,90 @@ public class SiedlerGameTest { @DisplayName("Test") public void TestHandle7() { - SiedlerGame game = SystemTestcases.startGame(); + SiedlerGame game = startGame(); } } + /** + * @Class NegtiveTestcases + * + * This class contains all negative test cases + */ @Nested @DisplayName("Negative test cases") class NegativeTestcases { + /** - * Tests if the method will fail when given false Data - * {@link ThreePlayerStandard#getAfterSetupPhaseAlmostEmptyBank(int)} + * Tests if siedlergame will start with one or five players. + * 1 Player is below the minimum + * 5 Players are above the maximum */ - @Test - public void destructiveTestBuildCity() { - SiedlerGame model = ThreePlayerStandard.getAfterSetupPhaseAlmostEmptyBank(DEFAULT_WINPOINTS); + @ParameterizedTest(name = "Test with {arguments} players") + @ValueSource(ints = {1, 5}) + @DisplayName("Starting Siedler game with one player or 5 players, expects fail") + public void startSiedlerGameWithOnePlayerorMoreThanMaximum(int playerAmount) { + Exception exc = assertThrows(IllegalArgumentException.class, () -> { + new SiedlerGame(DEFAULT_WINPOINTS, playerAmount); + }); - //Too - Assertions.assertFalse(model.buildCity(new Point(50, 60))); - - //Factions wants to build a city on a city from another faction - Assertions.assertFalse(model.buildCity(new Point(3, 3))); + Assertions.assertEquals(IllegalArgumentException.class, exc.getClass()); } /** - * Tests if the method fails when given false Data - * {@link ThreePlayerStandard#getAfterSetupPhase(int)} + * Tests if the game crashes when passing an amount of points, that is below the minimum amount */ @Test - public void destructiveTestBuildRoad() { + @DisplayName("Starting Siedler game with one player, expects fail") + public void startSiedlerGameWithLowerThanMinimumWinPoints() { - SiedlerGame model = ThreePlayerStandard.getAfterSetupPhase(DEFAULT_WINPOINTS); + Exception exc = assertThrows(IllegalArgumentException.class, () -> { + SiedlerGame game = new SiedlerGame(1, 4); + }); + + Assertions.assertEquals(IllegalArgumentException.class, exc.getClass()); + } + + + /** + * This testcase will test, if the methods placeInitialRoad and placeInitialSettlement are overwritting + * already occupied positions if the same faction or any other faction are calling the method with the same positions + * + * Expected: Method placeInitialRoad placeInitialSettlement should return false, independent of the current faction playing + */ + @Test + @DisplayName("Test placeInitialRoad and placeInitialSettlement with already occupied positions") + public void testPlaceInitialStructuresInAlreadyOccupiedPositions() { + SiedlerGame game = startGame(); + + Point settlementPoint = START_SETTLEMENT_POSITIONS.get(Config.Faction.BLUE).get(1); + + Assertions.assertTrue(game.placeInitialSettlement(settlementPoint, false)); + Assertions.assertFalse(game.placeInitialSettlement(settlementPoint, false)); + + Tuple roadEndpoints = START_ROADS_POSITIONS.get(Config.Faction.BLUE).get(1); + + Assertions.assertTrue(game.placeInitialRoad(roadEndpoints.first, roadEndpoints.second)); + Assertions.assertFalse(game.placeInitialRoad(roadEndpoints.first, roadEndpoints.second)); + + // Switch to other player to see if the occupied fields can be overwritten, when switched to the next player/faction + game.switchToNextPlayer(); + + Assertions.assertFalse(game.placeInitialRoad(roadEndpoints.first, roadEndpoints.second)); + Assertions.assertFalse(game.placeInitialSettlement(settlementPoint, false)); - System.out.println(model.buildRoad(new Point(3, 7),new Point(3, 9))); } /** - * Tests if the method fails when trading material with the same material - * {@link ThreePlayerStandard#getAfterSetupPhaseAlmostEmptyBank(int)} + * This testcase will test, if the methods buildRoad, buildCity buildSettlement are overwritting + * already occupied positions if the same faction or any other faction are calling the method with the same positions + * + * Expected: Method placeInitialRoad placeInitialSettlement should return false, independent of the current faction playing */ @Test - public void destructiveTestTradeWithBank() { - SiedlerGame model = ThreePlayerStandard.getAfterSetupPhaseAlmostEmptyBank(DEFAULT_WINPOINTS); - model.switchToNextPlayer(); + @DisplayName("Test buildRoad, buildCity and buildSettlement with already occupied positions") + public void testBuildStructuresOnOccupiedFields() { - Map expectedResourceCards = ThreePlayerStandard.BANK_ALMOST_EMPTY_RESOURCE_CARD_STOCK.get(model.getCurrentPlayerFaction()); - assertEquals(expectedResourceCards.get(Config.Resource.WOOL), model.getCurrentPlayerResourceStock(Config.Resource.WOOL)); - assertEquals(expectedResourceCards.get(Config.Resource.LUMBER), model.getCurrentPlayerResourceStock(Config.Resource.LUMBER)); - - System.out.println(model.tradeWithBankFourToOne(Config.Resource.WOOL, Config.Resource.WOOL)); } } @@ -137,97 +184,55 @@ public class SiedlerGameTest { * @Class SystemTestCases * * This class simulates a running game and tests multiple sequences of this game. - * Those test cases will be - * */ @Nested @DisplayName("System test cases") class SystemTestcases { - private final static Map START_SETTLEMENT_POSITIONS = new HashMap<>( - Map.of( - Config.Faction.BLUE, new Point(4, 4), - Config.Faction.RED, new Point(10, 4), - Config.Faction.GREEN, new Point(4, 18), - Config.Faction.YELLOW, new Point(10, 18) - )); - /** - * @Datafield START_ROADS_POSITION - * - * This are a set of Roads, that have been - */ - private final static Map> START_ROADS_POSITIONS = new HashMap<>( - Map.of( - Config.Faction.BLUE, new Tuple<>(new Point(4, 4), new Point(4, 6)), - Config.Faction.RED, new Tuple<>(new Point(10, 4), new Point(10, 6)), - Config.Faction.GREEN, new Tuple<>(new Point(4, 18), new Point(4, 16)), - Config.Faction.YELLOW, new Tuple<>(new Point(10, 18), new Point(10, 16)) - )); - - private static SiedlerGame startGame() { - return new SiedlerGame(DEFAULT_WINPOINTS, DEFAULT_PLAYERAMOUNT); - } - - - @Test - @DisplayName("Game initializing") - public void TestGameInitialization() { - SiedlerGame game = startGame(); - - for (Config.Faction faction: game.getPlayerFactions()) { - HashMap resources = game.getCurrentPlayerResource(); - - Assertions.assertEquals(0, resources.get(Config.Resource.BRICK)); - Assertions.assertEquals(0, resources.get(Config.Resource.GRAIN)); - Assertions.assertEquals(0, resources.get(Config.Resource.LUMBER)); - Assertions.assertEquals(0, resources.get(Config.Resource.ORE)); - Assertions.assertEquals(0, resources.get(Config.Resource.WOOL)); - - game.switchToNextPlayer(); - } - } - - /** - * This will test when + * This will test if the players can place initial settlements and roads */ @Test + @DisplayName("2 Players initialize a settlement and position") public void TestGameInSetupPhase() { - SiedlerGame game = gameInSetupPhase(); - - for (Config.Faction faction: game.getPlayerFactions()) { - HashMap resources = game.getCurrentPlayerResource(); - - Assertions.assertEquals(0, resources.get(Config.Resource.BRICK)); - Assertions.assertEquals(0, resources.get(Config.Resource.GRAIN)); - Assertions.assertEquals(0, resources.get(Config.Resource.LUMBER)); - Assertions.assertEquals(0, resources.get(Config.Resource.ORE)); - Assertions.assertEquals(0, resources.get(Config.Resource.WOOL)); - - game.switchToNextPlayer(); - } - } - - private static SiedlerGame gameInSetupPhase() { SiedlerGame game = startGame(); - for (Config.Faction faction: game.getPlayerFactions()) { + Assertions.assertTrue(game.placeInitialSettlement(START_SETTLEMENT_POSITIONS.get(game.getCurrentPlayerFaction()).get(0), false)); + Tuple road1 = START_ROADS_POSITIONS.get(game.getCurrentPlayerFaction()).get(0); + Assertions.assertTrue(game.placeInitialRoad(road1.first, road1.second)); - game.placeInitialSettlement(START_SETTLEMENT_POSITIONS.get(faction), false); - game.placeInitialRoad(START_ROADS_POSITIONS.get(faction).first, START_ROADS_POSITIONS.get(faction).second); + game.switchToNextPlayer(); - game.switchToNextPlayer(); - } + Assertions.assertTrue(game.placeInitialSettlement(START_SETTLEMENT_POSITIONS.get(game.getCurrentPlayerFaction()).get(1), false)); + Tuple road2 = START_ROADS_POSITIONS.get(game.getCurrentPlayerFaction()).get(1); + Assertions.assertTrue(game.placeInitialRoad(road2.first, road2.second)); - return game; } + /** + * tests, if the players can do all pf the actions in the building phase + */ @Test public void TestGameAfterSetupPhase() { SiedlerGame game = gameAfterSetupPhase(); throwDiceSeveralTimes(game, 5, 5); + soutDistribution(game); + } + + + /** + * tests, if a player wins when reached the amount of points. + */ + @Test + @DisplayName("End of Game test") + public void TestGameEnd() { + + } + + //TEMPORARY METHOD, WILL BE REMOVED SOON + private static void soutDistribution(SiedlerGame game) { System.out.println("\n\nVerteilung \n\n"); for (Config.Faction faction: game.getPlayerFactions()) { HashMap resources = game.getCurrentPlayerResource(); @@ -241,35 +246,71 @@ public class SiedlerGameTest { game.switchToNextPlayer(); } } - - private static SiedlerGame gameAfterSetupPhase() { - SiedlerGame game = gameInSetupPhase(); - - - - return game; - } - - @Test - @DisplayName("End of Game test") - public void TestGameEnd() { - - } - - private static SiedlerGame gameNearEnd() { - SiedlerGame game = gameAfterSetupPhase(); - - return game; - - } - - private static void throwDiceSeveralTimes(SiedlerGame game, int dice, int amountDiceThrows) { - for (int i = 0; i < amountDiceThrows; i++) { - System.out.println(game.getCurrentPlayerFaction().toString()); - game.throwDice(dice); - } - } - - } + + /** + * Initializes a game with the default values of winning points and amount of player + * + * @return + */ + private static SiedlerGame startGame() { + return new SiedlerGame(DEFAULT_WINPOINTS, DEFAULT_PLAYERAMOUNT); + } + + /** + * This method will set the game to the timeline after the setup. + * Players have already set each 2 Settlements and 2 Roads. + * + * @return SiedlerGame The game after the setup phase + */ + private static SiedlerGame gameAfterSetupPhase() { + SiedlerGame game = startGame(); + + for (int i = 0; i < game.getPlayerFactions().size(); i++) { + Config.Faction f = game.getCurrentPlayerFaction(); + + game.placeInitialSettlement(START_SETTLEMENT_POSITIONS.get(f).get(0), false); + Tuple firstRoad = START_ROADS_POSITIONS.get(f).get(0); + game.placeInitialRoad(firstRoad.first, firstRoad.second); + + game.switchToNextPlayer(); + } + for (int i = 0; i < game.getPlayerFactions().size(); i++) { + game.switchToPreviousPlayer(); + Config.Faction f = game.getCurrentPlayerFaction(); + + game.placeInitialSettlement(START_SETTLEMENT_POSITIONS.get(f).get(1), false); + Tuple secondRoad = START_ROADS_POSITIONS.get(f).get(1); + game.placeInitialRoad(secondRoad.first, secondRoad.second); + } + + return game; + } + + /** + * This method will call the method "throwDice" multiple times and passes the set value of the dice + * + * @param game Type SiedlerGame, the game itself in a running state + * @param dice Type int, Set Value of dice + * @param amountDiceThrows Type int, The amount of dice throws + */ + private static void throwDiceSeveralTimes(SiedlerGame game, int dice, int amountDiceThrows) { + for (int i = 0; i < amountDiceThrows; i++) { + System.out.println(game.getCurrentPlayerFaction().toString()); + game.throwDice(dice); + } + } + + /** + * This method will setup a game to a state before a player has the points + * for being able to win the game + * + * @return SiedlerGame which is near the + */ + private static SiedlerGame gameNearEnd() { + SiedlerGame game = gameAfterSetupPhase(); + + return game; + } + } \ No newline at end of file