diff options
Diffstat (limited to 'domain/src')
| -rw-r--r-- | domain/src/main/java/mancala/domain/Bowl.java | 29 | ||||
| -rw-r--r-- | domain/src/main/java/mancala/domain/Foo.java | 11 | ||||
| -rw-r--r-- | domain/src/main/java/mancala/domain/Kalaha.java | 29 | ||||
| -rw-r--r-- | domain/src/main/java/mancala/domain/Player.java | 37 | ||||
| -rw-r--r-- | domain/src/main/java/mancala/domain/SmallBowl.java | 111 | ||||
| -rw-r--r-- | domain/src/main/main.iml | 11 | ||||
| -rw-r--r-- | domain/src/test/java/mancala/domain/BowlTest.java | 208 | ||||
| -rw-r--r-- | domain/src/test/java/mancala/domain/FooTest.java | 23 | ||||
| -rw-r--r-- | domain/src/test/java/mancala/domain/PlayerTest.java | 35 | ||||
| -rw-r--r-- | domain/src/test/test.iml | 28 |
10 files changed, 488 insertions, 34 deletions
diff --git a/domain/src/main/java/mancala/domain/Bowl.java b/domain/src/main/java/mancala/domain/Bowl.java new file mode 100644 index 0000000..9da4f3b --- /dev/null +++ b/domain/src/main/java/mancala/domain/Bowl.java @@ -0,0 +1,29 @@ +package mancala.domain; + +abstract class Bowl { + protected int myRocks; + protected Player playerThatOwnsMe; + protected Bowl nextBowl; + + protected int calculateBoardPosition(int startPosition, int addedBowlsCount) { + if ((startPosition + addedBowlsCount) > 14) { + return ((addedBowlsCount + startPosition) - 14); + } + return startPosition + addedBowlsCount; + } + + protected void printStateDuringConstruction(int startPosition, int addedBowlsCount) { + System.out.println("Board position: " + calculateBoardPosition(startPosition, addedBowlsCount)+ " type of bowl: " + this.getClass().toString() + ", Player pointer:" + this.playerThatOwnsMe); + } + + Bowl getNextBowl() { + return nextBowl; + } + Player getPlayerThatOwnsMe() { + return playerThatOwnsMe; + } + + int getMyRocks() { + return myRocks; + } +} diff --git a/domain/src/main/java/mancala/domain/Foo.java b/domain/src/main/java/mancala/domain/Foo.java deleted file mode 100644 index bcce6fa..0000000 --- a/domain/src/main/java/mancala/domain/Foo.java +++ /dev/null @@ -1,11 +0,0 @@ -package mancala.domain; - -// Make your own mancala implementation using your design. -// You can take this stub as an example how to make a -// class inside a package and how to test it. -public class Foo { - - public int theAnswerToLifeTheUniverseAndEverything() { - return 41; - } -}
\ No newline at end of file diff --git a/domain/src/main/java/mancala/domain/Kalaha.java b/domain/src/main/java/mancala/domain/Kalaha.java new file mode 100644 index 0000000..13e8273 --- /dev/null +++ b/domain/src/main/java/mancala/domain/Kalaha.java @@ -0,0 +1,29 @@ +package mancala.domain; + +public class Kalaha extends Bowl { + + public Kalaha() { + this.myRocks = 0; + this.playerThatOwnsMe = new Player(); + this.nextBowl = new SmallBowl(14, 1, this, this.playerThatOwnsMe.getOpponent()); + } + + Kalaha(int startPosition, int addedBowlsCount, Bowl startBowl, Player playerOwningThisSide) { + this.myRocks = 0; + this.playerThatOwnsMe = playerOwningThisSide; + + int boardPosition = calculateBoardPosition(startPosition, addedBowlsCount); + + try { + if (!(boardPosition == 7 || boardPosition == 14)) + throw new Exception("Kalaha in wrong position"); + else if (addedBowlsCount == 13) + this.nextBowl = startBowl; + else { + this.nextBowl = new SmallBowl(startPosition, ++addedBowlsCount, startBowl, playerOwningThisSide.getOpponent()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/domain/src/main/java/mancala/domain/Player.java b/domain/src/main/java/mancala/domain/Player.java new file mode 100644 index 0000000..130308e --- /dev/null +++ b/domain/src/main/java/mancala/domain/Player.java @@ -0,0 +1,37 @@ +package mancala.domain; + +public class Player { + private boolean hasTheTurn; + private Player opponent; + + public Player() { + // player has the turn when created + this.hasTheTurn = true; + + this.opponent = new Player(this); + } + + private Player(Player opponent) { + this.hasTheTurn = false; + + this.opponent = opponent; + } + + public Player getOpponent() { + return opponent; + } + + public boolean hasTheTurn() { + return hasTheTurn; + } + + public void switchTurn() { + if (this.hasTheTurn == true) { + this.hasTheTurn = false; + this.opponent.hasTheTurn = true; + } else { + this.hasTheTurn = true; + this.opponent.hasTheTurn = false; + } + } +} diff --git a/domain/src/main/java/mancala/domain/SmallBowl.java b/domain/src/main/java/mancala/domain/SmallBowl.java new file mode 100644 index 0000000..8d0b059 --- /dev/null +++ b/domain/src/main/java/mancala/domain/SmallBowl.java @@ -0,0 +1,111 @@ +package mancala.domain; + +// Make your own mancala implementation using your design. +// You can take this stub as an example how to make a +// class inside a package and how to test it. +public class SmallBowl extends Bowl { + + public SmallBowl() { + constructorHelper(1); + } + + public SmallBowl(int position) { + // constructs board by recursively calling either kalaha or smallbowl constructors + constructorHelper(position); + } + + SmallBowl getNextSmallBowlRepeat(int i) { + Recursive recursive = new Recursive(); + SmallBowl next = recursive.getNextSmallBowl(i, this); + return next; + } + + SmallBowl getOpposite() { + Bowl kalaha = this.getNextBowl(); + Recursive recursive = new Recursive(); + int i = 0; + while (kalaha.getClass() != Kalaha.class) { + i++; + kalaha.getNextBowl(); + } + return (SmallBowl) recursive.getNextSmallBowl(i-1, (SmallBowl) kalaha.getNextBowl()); + } + + Kalaha getKalaha() { + Bowl kalaha = this.getNextBowl(); + while (kalaha.getClass() != Kalaha.class) + kalaha = kalaha.getNextBowl(); + return (Kalaha) kalaha; + } + + public void play() { + if ((!this.playerThatOwnsMe.hasTheTurn()) || (this.myRocks == 0)); + else { + Recursive recursive = new Recursive(); + Bowl playEndedInThisBowl = recursive.distributeAntiClockWise(this.myRocks, this.getNextBowl()); + this.myRocks = 0; + if (!(playEndedInThisBowl.getClass() == Kalaha.class&&playEndedInThisBowl.getPlayerThatOwnsMe().equals(this.getPlayerThatOwnsMe()))) { + this.playerThatOwnsMe.switchTurn(); + } + } + } + + private class Recursive { + Bowl distributeAntiClockWise(int remainingRocks, Bowl currentBowl) { + Boolean opponentKalahaCondition = (currentBowl.getClass() == Kalaha.class)&&!(currentBowl.getPlayerThatOwnsMe().equals(SmallBowl.this.getPlayerThatOwnsMe())); + if (remainingRocks > 1&&!opponentKalahaCondition) { + currentBowl.myRocks++; + return distributeAntiClockWise(--remainingRocks, currentBowl.getNextBowl()); + } else if (opponentKalahaCondition) { + return distributeAntiClockWise(remainingRocks, currentBowl.getNextBowl()); + } else { + currentBowl.myRocks++; + return currentBowl; + } + } + + SmallBowl getNextSmallBowl(int remainingNexts, Bowl currentBowl) { + if (remainingNexts > 0) + return getNextSmallBowl(--remainingNexts, currentBowl.getNextBowl()); + else if (currentBowl.getClass() == Kalaha.class) + return getNextSmallBowl(remainingNexts, currentBowl.getNextBowl()); + else + return (SmallBowl) currentBowl; + + } + } + + // Recurses through board positions until connected again to startBowl + SmallBowl(int startPosition, int addedBowlsCount, Bowl startBowl, Player playerOwningThisSide) { + this.myRocks = 4; + this.playerThatOwnsMe = playerOwningThisSide; + + int boardPosition = calculateBoardPosition(startPosition, addedBowlsCount); + + if (addedBowlsCount == 13) + this.nextBowl = startBowl; + + else if (boardPosition < 6 || (7 < boardPosition && boardPosition < 13)) + this.nextBowl = new SmallBowl(startPosition, ++addedBowlsCount, startBowl, playerOwningThisSide); + + else if (boardPosition == 6 || boardPosition == 13) + this.nextBowl = new Kalaha(startPosition, ++addedBowlsCount, startBowl, playerOwningThisSide); + } + + private void constructorHelper(int position) { + this.myRocks = 4; + this.playerThatOwnsMe = new Player(); + + if (position < 6 || (7 < position && position < 13)) + this.nextBowl = new SmallBowl(position, 1, this, this.playerThatOwnsMe); + else if (position == 6 || position == 13) + this.nextBowl = new Kalaha(position, 1, this, this.playerThatOwnsMe); + else if (position == 7) { + this.nextBowl = new SmallBowl(1, 1, this, this.playerThatOwnsMe); + } else if (position == 14) { + this.nextBowl = new SmallBowl(8, 1, this, this.playerThatOwnsMe); + } + } + + +}
\ No newline at end of file diff --git a/domain/src/main/main.iml b/domain/src/main/main.iml new file mode 100644 index 0000000..908ad4f --- /dev/null +++ b/domain/src/main/main.iml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/java" isTestSource="false" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module>
\ No newline at end of file diff --git a/domain/src/test/java/mancala/domain/BowlTest.java b/domain/src/test/java/mancala/domain/BowlTest.java new file mode 100644 index 0000000..5863784 --- /dev/null +++ b/domain/src/test/java/mancala/domain/BowlTest.java @@ -0,0 +1,208 @@ +package mancala.domain; + +// Your test class should be in the same +// package as the class you're testing. +// Usually the test directory mirrors the +// main directory 1:1. So for each class in src/main, +// there is a class in src/test. + +// Import our test dependencies. We import the Test-attribute +// and a set of assertions. + +import org.junit.jupiter.api.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.junit.jupiter.api.Assertions.*; + + +class BowlTest { + // Define a test starting with @Test. The test is like + // a small main method - you need to setup everything + // and you can write any arbitrary Java code in it. + + protected void traverseAndCheckBoard(Bowl currentBowl, int position) { + Bowl initialBowl = currentBowl; + int traversedCount = 0; + int currentPosition = 0; + for (int i = 0; i < 14; i++) { + + if ((position + traversedCount) > 14) { + // if looping around the board, position = ((start+traversed) - total) + // in other words the amount of bowls that the absolute position is greater than the board's total bowls + currentPosition = ((traversedCount + position) - 14); + } else + // Or just use normal position + currentPosition = position + traversedCount; + + // check for kalaha's, and check for smallbowl otherwise + if (currentPosition == 7 || currentPosition == 14) + assertEquals(currentBowl.getClass(), Kalaha.class); + else + assertEquals(currentBowl.getClass(), SmallBowl.class); + + currentBowl = currentBowl.getNextBowl(); + assertNotNull(currentBowl); + traversedCount++; + } + assertSame(initialBowl, currentBowl); + } + + @Nested + @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) + class For_a_normal_mancala_bowl{ + SmallBowl firstSmallBowlPlayer; + + @BeforeEach + public void makeASmallBowlInMancala() { + firstSmallBowlPlayer = new SmallBowl(); + } + + @ParameterizedTest + @ValueSource(ints = {1,2,3,4,5,6,8,9,10,11,12,13}) + public void given_always_when_created_it_exists_in_a_mancala_board(int position) { + traverseAndCheckBoard(new SmallBowl(position), position); + traverseAndCheckBoard(new SmallBowl(), 1); + } + + @Nested + class given_its_the_start_of_the_game { + @Test + public void When_created_Then_has_four_rocks() { + Bowl current = firstSmallBowlPlayer; + for (int i = 0; i < 14; i++) { + current = current.getNextBowl(); + if (current.getClass() == SmallBowl.class) + assertEquals(current.getMyRocks(), 4); + } + assertSame(current, firstSmallBowlPlayer); + } + + @Test + public void When_chosen_by_the_player_that_has_the_turn_Then_distribute_its_rocks_anti_clockwise() { + int initialRocks = firstSmallBowlPlayer.getMyRocks(); + firstSmallBowlPlayer.play(); + Bowl neighbour = firstSmallBowlPlayer.getNextBowl(); + for (int i = 0; i < initialRocks; i++) { + assertEquals(5, neighbour.getMyRocks()); + neighbour = neighbour.getNextBowl(); + } + } + + } + + @Nested + class given_the_game_is_in_a_state_where { + + @Test + public void its_not_the_players_turn_When_played_by_the_player_Then_nothing_happens() { + firstSmallBowlPlayer.getPlayerThatOwnsMe().switchTurn(); + int initialRocks = firstSmallBowlPlayer.getMyRocks(); + firstSmallBowlPlayer.play(); + Bowl neighbour = firstSmallBowlPlayer.getNextBowl(); + for (int i = 0; i < initialRocks; i++) { + assertEquals(4, neighbour.getMyRocks()); + neighbour = neighbour.getNextBowl(); + } + } + + @Test + public void play_can_reach_opponents_kalaha_When_player_plays_Then_opponents_kalaha_is_skipped() { + SmallBowl playWillSkipFromThisBowl = goToSkippableState(); + int opponentKalahaRocksBefore = firstSmallBowlPlayer.getNextSmallBowlRepeat(6).getKalaha().getMyRocks(); + playWillSkipFromThisBowl.play(); + int opponentKalahaRocksAfter = firstSmallBowlPlayer.getNextSmallBowlRepeat(6).getKalaha().getMyRocks(); + assertEquals(opponentKalahaRocksBefore, opponentKalahaRocksAfter); + } + + @Test + public void the_bowl_is_empty_When_player_plays_the_bowl_Then_nothing_happens() { + firstSmallBowlPlayer.play(); + firstSmallBowlPlayer.getPlayerThatOwnsMe().switchTurn(); + assertTrue(firstSmallBowlPlayer.getPlayerThatOwnsMe().hasTheTurn()); + firstSmallBowlPlayer.play(); + assertTrue(firstSmallBowlPlayer.getPlayerThatOwnsMe().hasTheTurn()); + assertEquals(5, firstSmallBowlPlayer.getNextBowl().getMyRocks()); + } + + private SmallBowl goToSkippableState() { + SmallBowl firstSmallBowlOpponent = firstSmallBowlPlayer.getNextSmallBowlRepeat(6); + + firstSmallBowlPlayer.getNextSmallBowlRepeat(2).play(); + firstSmallBowlPlayer.getNextSmallBowlRepeat(3).play(); + + firstSmallBowlOpponent.getNextSmallBowlRepeat(2).play(); + firstSmallBowlOpponent.getNextSmallBowlRepeat(3).play(); + + firstSmallBowlPlayer.play(); + firstSmallBowlOpponent.play(); + + firstSmallBowlPlayer.getNextSmallBowlRepeat(4).play(); + firstSmallBowlOpponent.getNextSmallBowlRepeat(4).play(); + + // Playing this bowl should give a skip! + assertTrue(firstSmallBowlPlayer.getNextSmallBowlRepeat(5).getMyRocks() >= 8); + return firstSmallBowlPlayer.getNextSmallBowlRepeat(5); + } + } + + @Nested + class given_the_play_ends{ + + @Test + public void in_own_kalaha_When_player_plays_this_bowl_Then_turn_is_not_switched() { + firstSmallBowlPlayer.getNextSmallBowlRepeat(2).play(); + assertTrue(firstSmallBowlPlayer.getPlayerThatOwnsMe().hasTheTurn()); + } + + @Test + public void in_own_small_bowl_When_player_plays_this_bowl_Then_turn_is_switched() { + firstSmallBowlPlayer.play(); + assertFalse(firstSmallBowlPlayer.getPlayerThatOwnsMe().hasTheTurn()); + } + + @Test + public void in_opponents_small_bowl_When_player_plays_this_bowl_Then_turn_is_switched() { + firstSmallBowlPlayer.getNextSmallBowlRepeat(5).play(); + assertFalse(firstSmallBowlPlayer.getPlayerThatOwnsMe().hasTheTurn()); + } + + } + + + } + + @Nested + @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) + class a_kalaha { + + Kalaha kalaha; + + @BeforeEach + public void makeKalahaInBoard() { + kalaha = new Kalaha(); + } + + @Test + public void exists_in_a_mancala_board() { + traverseAndCheckBoard(kalaha, 14); + } + + @Test + public void has_zero_rocks_when_created() { + Bowl current = kalaha; + for (int i = 0; i < 14; i++) { + current = current.getNextBowl(); + if (current.getClass() == Kalaha.class) + assertEquals(current.getMyRocks(), 0); + } + } + } + + + @Nested + @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) + class in_a_game_of_mancala { + + } +}
\ No newline at end of file diff --git a/domain/src/test/java/mancala/domain/FooTest.java b/domain/src/test/java/mancala/domain/FooTest.java deleted file mode 100644 index fa784d3..0000000 --- a/domain/src/test/java/mancala/domain/FooTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package mancala.domain; - -// Your test class should be in the same -// package as the class you're testing. -// Usually the test directory mirrors the -// main directory 1:1. So for each class in src/main, -// there is a class in src/test. - -// Import our test dependencies. We import the Test-attribute -// and a set of assertions. -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - -public class FooTest { - // Define a test starting with @Test. The test is like - // a small main method - you need to setup everything - // and you can write any arbitrary Java code in it. - @Test - public void aNormalBorlStartsWith4Stones() { - Foo foo = new Foo(); - assertEquals(42, foo.theAnswerToLifeTheUniverseAndEverything()); - } -}
\ No newline at end of file diff --git a/domain/src/test/java/mancala/domain/PlayerTest.java b/domain/src/test/java/mancala/domain/PlayerTest.java new file mode 100644 index 0000000..3538ec5 --- /dev/null +++ b/domain/src/test/java/mancala/domain/PlayerTest.java @@ -0,0 +1,35 @@ +package mancala.domain; + +import org.junit.jupiter.api.*; + +import static org.junit.jupiter.api.Assertions.*; + +@DisplayName("A player model ") +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class PlayerTest { + Player player; + Player opponent; + + @BeforeEach + public void let_player_and_oppenent_exist() { + player = new Player(); + opponent = player.getOpponent(); + } + + @Test + public void has_turn_when_created() { + assertTrue(player.hasTheTurn()); + } + + @Test + public void opponent_does_not_have_turn_when_player_models_are_created() { + assertFalse(player.getOpponent().hasTheTurn()); + } + + @Test + public void can_change_turn_when_necessary() { + player.switchTurn(); + assertFalse(player.hasTheTurn()); + assertTrue(player.getOpponent().hasTheTurn()); + } +}
\ No newline at end of file diff --git a/domain/src/test/test.iml b/domain/src/test/test.iml new file mode 100644 index 0000000..8cc6e96 --- /dev/null +++ b/domain/src/test/test.iml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/java" isTestSource="true" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="module-library" scope="TEST"> + <library name="JUnit5.7.0"> + <CLASSES> + <root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter/5.7.0/junit-jupiter-5.7.0.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-api/5.7.0/junit-jupiter-api-5.7.0.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/apiguardian/apiguardian-api/1.1.0/apiguardian-api-1.1.0.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-commons/1.7.0/junit-platform-commons-1.7.0.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-params/5.7.0/junit-jupiter-params-5.7.0.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-engine/5.7.0/junit-jupiter-engine-5.7.0.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-engine/1.7.0/junit-platform-engine-1.7.0.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + </library> + </orderEntry> + <orderEntry type="module" module-name="main" scope="TEST" /> + </component> +</module>
\ No newline at end of file |
