diff options
Diffstat (limited to 'src')
6 files changed, 191 insertions, 54 deletions
diff --git a/src/main/java/org/luxons/sevenwonders/game/Game.java b/src/main/java/org/luxons/sevenwonders/game/Game.java index 389ef844..9023a80f 100644 --- a/src/main/java/org/luxons/sevenwonders/game/Game.java +++ b/src/main/java/org/luxons/sevenwonders/game/Game.java @@ -5,13 +5,14 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import java.util.stream.IntStream; -import org.luxons.sevenwonders.game.api.HandCard; import org.luxons.sevenwonders.game.api.PlayerTurnInfo; import org.luxons.sevenwonders.game.api.Table; import org.luxons.sevenwonders.game.boards.Board; import org.luxons.sevenwonders.game.cards.Card; import org.luxons.sevenwonders.game.cards.Decks; +import org.luxons.sevenwonders.game.cards.Hands; public class Game { @@ -29,7 +30,7 @@ public class Game { private final Map<Integer, Move> preparedMoves; - private Map<Integer, List<Card>> hands; + private Hands hands; private int currentAge = 0; @@ -40,7 +41,6 @@ public class Game { this.table = new Table(boards); this.decks = decks; this.discardedCards = new ArrayList<>(); - this.hands = new HashMap<>(); this.preparedMoves = new HashMap<>(); startNewAge(); } @@ -59,21 +59,16 @@ public class Game { } public List<PlayerTurnInfo> getTurnInfo() { - return hands.entrySet().stream().map(e -> createPlayerTurnInfo(e.getKey(), e.getValue())) - .collect(Collectors.toList()); + return IntStream.range(0, players.size()).mapToObj(this::createPlayerTurnInfo).collect(Collectors.toList()); } - private PlayerTurnInfo createPlayerTurnInfo(int playerIndex, List<Card> cards) { + private PlayerTurnInfo createPlayerTurnInfo(int playerIndex) { PlayerTurnInfo pti = new PlayerTurnInfo(playerIndex, table); - pti.setHand(createHand(playerIndex, cards)); + pti.setHand(hands.createHand(table, playerIndex)); pti.setCurrentAge(currentAge); return pti; } - private List<HandCard> createHand(int playerIndex, List<Card> cards) { - return cards.stream().map(c -> new HandCard(c, table, playerIndex)).collect(Collectors.toList()); - } - public void prepareCard(Move move) throws InvalidMoveException { validate(move); preparedMoves.put(move.getPlayerIndex(), move); @@ -110,7 +105,7 @@ public class Game { if (endOfAgeReached()) { startNewAge(); } else { - rotateHands(); + hands.rotate(getHandRotationOffset()); } } @@ -170,16 +165,6 @@ public class Game { return hands.get(0).size() == 1; } - private void rotateHands() { - int offset = getHandRotationOffset(); - Map<Integer, List<Card>> newHands = new HashMap<>(hands.size()); - for (int i = 0; i < players.size(); i++) { - int newIndex = Math.floorMod(i + offset, players.size()); - newHands.put(newIndex, hands.get(i)); - } - hands = newHands; - } - private int getHandRotationOffset() { // clockwise at age 1, and alternating return currentAge % 2 == 0 ? -1 : 1; diff --git a/src/main/java/org/luxons/sevenwonders/game/cards/Decks.java b/src/main/java/org/luxons/sevenwonders/game/cards/Decks.java index b798b035..aa2b00bf 100644 --- a/src/main/java/org/luxons/sevenwonders/game/cards/Decks.java +++ b/src/main/java/org/luxons/sevenwonders/game/cards/Decks.java @@ -22,7 +22,7 @@ public class Decks { .orElseThrow(() -> new CardNotFoundException(cardName)); } - public Map<Integer, List<Card>> deal(int age, int nbPlayers) { + public Hands deal(int age, int nbPlayers) { List<Card> deck = getDeck(age); validateNbCards(deck, nbPlayers); return deal(deck, nbPlayers); @@ -46,13 +46,15 @@ public class Decks { } } - private Map<Integer, List<Card>> deal(List<Card> deck, int nbPlayers) { + private Hands deal(List<Card> deck, int nbPlayers) { Map<Integer, List<Card>> hands = new HashMap<>(nbPlayers); + for (int i = 0; i < nbPlayers; i++) { + hands.put(i, new ArrayList<>()); + } for (int i = 0; i < deck.size(); i++) { - hands.putIfAbsent(i % nbPlayers, new ArrayList<>()); hands.get(i % nbPlayers).add(deck.get(i)); } - return hands; + return new Hands(hands, nbPlayers); } class CardNotFoundException extends RuntimeException { diff --git a/src/main/java/org/luxons/sevenwonders/game/cards/Hands.java b/src/main/java/org/luxons/sevenwonders/game/cards/Hands.java new file mode 100644 index 00000000..4a5588c9 --- /dev/null +++ b/src/main/java/org/luxons/sevenwonders/game/cards/Hands.java @@ -0,0 +1,50 @@ +package org.luxons.sevenwonders.game.cards; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.luxons.sevenwonders.game.api.HandCard; +import org.luxons.sevenwonders.game.api.Table; + +public class Hands { + + private final int nbPlayers; + + private Map<Integer, List<Card>> hands; + + Hands(Map<Integer, List<Card>> hands, int nbPlayers) { + this.hands = hands; + this.nbPlayers = nbPlayers; + } + + public List<Card> get(int playerIndex) { + if (!hands.containsKey(playerIndex)) { + throw new PlayerIndexOutOfBoundsException(playerIndex); + } + return hands.get(playerIndex); + } + + public List<HandCard> createHand(Table table, int playerIndex) { + return hands.get(playerIndex) + .stream() + .map(c -> new HandCard(c, table, playerIndex)) + .collect(Collectors.toList()); + } + + public Hands rotate(int offset) { + Map<Integer, List<Card>> newHands = new HashMap<>(hands.size()); + for (int i = 0; i < nbPlayers; i++) { + int newIndex = Math.floorMod(i + offset, nbPlayers); + newHands.put(newIndex, hands.get(i)); + } + return new Hands(newHands, nbPlayers); + } + + class PlayerIndexOutOfBoundsException extends ArrayIndexOutOfBoundsException { + PlayerIndexOutOfBoundsException(int index) { + super(index); + } + } +} diff --git a/src/test/java/org/luxons/sevenwonders/game/cards/DecksTest.java b/src/test/java/org/luxons/sevenwonders/game/cards/DecksTest.java index b7fad970..06060f16 100644 --- a/src/test/java/org/luxons/sevenwonders/game/cards/DecksTest.java +++ b/src/test/java/org/luxons/sevenwonders/game/cards/DecksTest.java @@ -1,34 +1,42 @@ package org.luxons.sevenwonders.game.cards; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.junit.Rule; import org.junit.Test; +import org.junit.experimental.theories.DataPoints; +import org.junit.experimental.theories.Theories; +import org.junit.experimental.theories.Theory; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; import org.luxons.sevenwonders.game.cards.Decks.CardNotFoundException; +import org.luxons.sevenwonders.game.test.TestUtils; import static org.junit.Assert.*; +import static org.junit.Assume.*; +@RunWith(Theories.class) public class DecksTest { + @DataPoints + public static int[] dataPoints() { + return new int[] {1, 2, 3, 5, 10}; + } + + @Rule + public ExpectedException thrown = ExpectedException.none(); + private static Decks createDecks(int nbAges, int nbCardsPerAge) { Map<Integer, List<Card>> cardsPerAge = new HashMap<>(); for (int age = 1; age <= nbAges; age++) { int firstCardNumber = (age - 1) * nbCardsPerAge; - cardsPerAge.put(age, createSampleCards(firstCardNumber, nbCardsPerAge)); + cardsPerAge.put(age, TestUtils.createSampleCards(firstCardNumber, nbCardsPerAge)); } return new Decks(cardsPerAge); } - private static List<Card> createSampleCards(int fromIndex, int nbCards) { - List<Card> sampleCards = new ArrayList<>(); - for (int i = fromIndex; i < fromIndex + nbCards; i++) { - sampleCards.add(new Card("Test Card " + i, Color.BLUE, null, null, null, null, null)); - } - return sampleCards; - } - @Test(expected = CardNotFoundException.class) public void getCard_failsOnNullNameWhenDeckIsEmpty() { Decks decks = createDecks(0, 0); @@ -72,29 +80,31 @@ public class DecksTest { decks.deal(4, 10); } - @Test(expected = IllegalArgumentException.class) - public void deal_failsWhenTooFewPlayers() { - Decks decks = createDecks(3, 28); - decks.deal(1, 3); + @Theory + public void deal_failsWhenTooFewPlayers(int nbPlayers, int nbCards) { + assumeTrue(nbCards % nbPlayers != 0); + thrown.expect(IllegalArgumentException.class); + Decks decks = createDecks(1, nbCards); + decks.deal(1, nbPlayers); } - @Test - public void deal_succeedsOnZeroCards() { - Decks decks = createDecks(3, 0); - Map<Integer, List<Card>> hands = decks.deal(1, 10); - for (List<Card> hand : hands.values()) { - assertTrue(hand.isEmpty()); + @Theory + public void deal_succeedsOnZeroCards(int nbPlayers) { + Decks decks = createDecks(1, 0); + Hands hands = decks.deal(1, nbPlayers); + for (int i = 0; i < nbPlayers; i++) { + assertNotNull(hands.get(i)); + assertTrue(hands.get(i).isEmpty()); } } - @Test - public void deal_evenDistribution() { - int nbCardsPerAge = 12; - int nbPlayers = 4; - Decks decks = createDecks(3, nbCardsPerAge); - Map<Integer, List<Card>> hands = decks.deal(1, nbPlayers); - for (List<Card> hand : hands.values()) { - assertEquals(nbCardsPerAge / nbPlayers, hand.size()); + @Theory + public void deal_evenDistribution(int nbPlayers, int nbCardsPerPlayer) { + int nbCardsPerAge = nbPlayers * nbCardsPerPlayer; + Decks decks = createDecks(1, nbCardsPerAge); + Hands hands = decks.deal(1, nbPlayers); + for (int i = 0; i < nbPlayers; i++) { + assertEquals(nbCardsPerPlayer, hands.get(i).size()); } } }
\ No newline at end of file diff --git a/src/test/java/org/luxons/sevenwonders/game/cards/HandsTest.java b/src/test/java/org/luxons/sevenwonders/game/cards/HandsTest.java new file mode 100644 index 00000000..97cb4625 --- /dev/null +++ b/src/test/java/org/luxons/sevenwonders/game/cards/HandsTest.java @@ -0,0 +1,77 @@ +package org.luxons.sevenwonders.game.cards; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Test; +import org.luxons.sevenwonders.game.cards.Hands.PlayerIndexOutOfBoundsException; +import org.luxons.sevenwonders.game.test.TestUtils; + +import static org.junit.Assert.*; + +public class HandsTest { + + private static Hands createHands(int nbPlayers, int nbCardsPerPlayer) { + Map<Integer, List<Card>> hands = new HashMap<>(); + for (int p = 0; p < nbPlayers; p++) { + int firstCardNumber = (p - 1) * nbCardsPerPlayer; + hands.put(p, TestUtils.createSampleCards(firstCardNumber, nbCardsPerPlayer)); + } + return new Hands(hands, nbPlayers); + } + + @Test(expected = PlayerIndexOutOfBoundsException.class) + public void get_failsOnMissingPlayer() { + Hands hands = createHands(4, 7); + hands.get(5); + } + + @Test + public void get_retrievesCorrectCards() { + List<Card> hand0 = TestUtils.createSampleCards(0, 5); + List<Card> hand1 = TestUtils.createSampleCards(5, 10); + Map<Integer, List<Card>> handsMap = new HashMap<>(); + handsMap.put(0, hand0); + handsMap.put(1, hand1); + Hands hands = new Hands(handsMap, 2); + assertEquals(hand0, hands.get(0)); + assertEquals(hand1, hands.get(1)); + } + + @Test + public void rotate_doesNotMoveWhenOffsetIsZero() { + Hands hands = createHands(3, 7); + Hands rotated = hands.rotate(0); + assertEquals(rotated.get(0), hands.get(0)); + assertEquals(rotated.get(1), hands.get(1)); + assertEquals(rotated.get(2), hands.get(2)); + } + + @Test + public void rotate_movesOfCorrectOffset_positive() { + Hands hands = createHands(3, 7); + Hands rotated = hands.rotate(1); + assertEquals(rotated.get(1), hands.get(0)); + assertEquals(rotated.get(2), hands.get(1)); + assertEquals(rotated.get(0), hands.get(2)); + } + + @Test + public void rotate_movesOfCorrectOffset_negative() { + Hands hands = createHands(3, 7); + Hands rotated = hands.rotate(-1); + assertEquals(rotated.get(2), hands.get(0)); + assertEquals(rotated.get(0), hands.get(1)); + assertEquals(rotated.get(1), hands.get(2)); + } + + @Test + public void rotate_movesOfCorrectOffset_negative2() { + Hands hands = createHands(3, 7); + Hands rotated = hands.rotate(-2); + assertEquals(rotated.get(1), hands.get(0)); + assertEquals(rotated.get(2), hands.get(1)); + assertEquals(rotated.get(0), hands.get(2)); + } +}
\ No newline at end of file diff --git a/src/test/java/org/luxons/sevenwonders/game/test/TestUtils.java b/src/test/java/org/luxons/sevenwonders/game/test/TestUtils.java index 2a0292cd..2a3bc379 100644 --- a/src/test/java/org/luxons/sevenwonders/game/test/TestUtils.java +++ b/src/test/java/org/luxons/sevenwonders/game/test/TestUtils.java @@ -1,7 +1,12 @@ package org.luxons.sevenwonders.game.test; +import java.util.ArrayList; +import java.util.List; + import org.luxons.sevenwonders.game.Settings; import org.luxons.sevenwonders.game.boards.Board; +import org.luxons.sevenwonders.game.cards.Card; +import org.luxons.sevenwonders.game.cards.Color; import org.luxons.sevenwonders.game.resources.Production; import org.luxons.sevenwonders.game.resources.ResourceType; import org.luxons.sevenwonders.game.resources.Resources; @@ -49,4 +54,12 @@ public class TestUtils { } return resources; } + + public static List<Card> createSampleCards(int fromIndex, int nbCards) { + List<Card> sampleCards = new ArrayList<>(); + for (int i = fromIndex; i < fromIndex + nbCards; i++) { + sampleCards.add(new Card("Test Card " + i, Color.BLUE, null, null, null, null, null)); + } + return sampleCards; + } } |