Skip to content

Commit a510e82

Browse files
committed
Implement solution
1 parent 3e04726 commit a510e82

File tree

6 files changed

+157
-447
lines changed

6 files changed

+157
-447
lines changed
Lines changed: 157 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,172 @@
1-
import java.util.*;
1+
import java.util.ArrayDeque;
2+
import java.util.Deque;
3+
import java.util.HashSet;
4+
import java.util.List;
5+
import java.util.Set;
26

3-
class Camicia {
7+
public class Camicia {
48

5-
private MatchResult matchResult;
9+
private Status status;
10+
private int cards;
11+
private int tricks;
612

7-
void simulateGame(List<String> playerAList, List<String> playerBList) {
8-
Turn initialTurn = new Turn(playerAList, playerBList);
9-
boolean win = initialTurn.playTurn();
10-
System.out.println(initialTurn);
11-
Turn turn = initialTurn;
13+
private enum Player {
14+
PLAYER_A, PLAYER_B
15+
}
16+
17+
private enum Status {
18+
FINISHED, LOOP
19+
}
20+
21+
private static int penaltyOf(String card) {
22+
return switch (card) {
23+
case "J" -> 1;
24+
case "Q" -> 2;
25+
case "K" -> 3;
26+
case "A" -> 4;
27+
default -> 0;
28+
};
29+
}
30+
31+
private static boolean isPaymentCard(String card) {
32+
return penaltyOf(card) > 0;
33+
}
34+
35+
/**
36+
* Return a snapshot of the current state
37+
*/
38+
private static String stateKey(Deque<String> deckA, Deque<String> deckB) {
39+
StringBuilder sb = new StringBuilder();
40+
41+
for (String card : deckA) {
42+
sb.append(isPaymentCard(card) ? card : "N");
43+
}
1244

13-
while (!win) {
14-
Turn newTurn = new Turn(turn);
15-
win = newTurn.playTurn();
16-
System.out.println(newTurn);
45+
sb.append('|');
1746

18-
turn = newTurn;
47+
for (String card : deckB) {
48+
sb.append(isPaymentCard(card) ? card : "N");
1949
}
2050

21-
matchResult = MatchResult.builder()
22-
.withStatus(MatchResult.Status.FINISHED)
23-
.withCards(turn.getPlayedCardCounter())
24-
.withTricks(turn.getTrick())
25-
.build();
51+
return sb.toString();
52+
}
53+
54+
private static Player otherPlayer(Player player) {
55+
return player == Player.PLAYER_A ? Player.PLAYER_B : Player.PLAYER_A;
56+
}
57+
58+
private static Deque<String> deckOf(Player player, Deque<String> deckA, Deque<String> deckB) {
59+
return player == Player.PLAYER_A ? deckA : deckB;
60+
}
61+
62+
public void simulateGame(List<String> playerA, List<String> playerB) {
63+
Deque<String> deckA = new ArrayDeque<>(playerA);
64+
Deque<String> deckB = new ArrayDeque<>(playerB);
65+
66+
int cardsPlayed = 0;
67+
int tricksCount = 0;
68+
Player current = Player.PLAYER_A;
69+
70+
Set<String> seenStates = new HashSet<>();
71+
72+
while (true) {
73+
String key = stateKey(deckA, deckB);
74+
// Key already exists, which means this is a loop
75+
if (!seenStates.add(key)) {
76+
finishGame(Status.LOOP, cardsPlayed, tricksCount);
77+
return;
78+
}
79+
80+
// Otherwise, play next round
81+
RoundResult result = playRound(deckA, deckB, current);
82+
83+
cardsPlayed += result.pileSize();
84+
tricksCount++;
85+
86+
// Check if someone wins and finish the game
87+
if (hasWinner(deckA, deckB)) {
88+
finishGame(Status.FINISHED, cardsPlayed, tricksCount);
89+
return;
90+
}
91+
92+
// Otherwise, play next round
93+
current = result.nextStarter();
94+
}
95+
}
96+
97+
private RoundResult playRound(Deque<String> deckA, Deque<String> deckB, Player startingPlayer) {
98+
Deque<String> pile = new ArrayDeque<>(); // cards played in this round
99+
Player currentPlayer = startingPlayer;
100+
int pendingPenalty = 0;
101+
102+
while (true) {
103+
Deque<String> currentPlayerDeck = deckOf(currentPlayer, deckA, deckB);
104+
Player opponent = otherPlayer(currentPlayer);
105+
Deque<String> opponentDeck = deckOf(opponent, deckA, deckB);
106+
107+
// Current player deck is empty, opponent collects all pile, end this round
108+
if (currentPlayerDeck.isEmpty()) {
109+
opponentDeck.addAll(pile);
110+
return new RoundResult(opponent, pile.size());
111+
}
112+
113+
// Otherwise, current player plays 1 card, add to pile
114+
String card = currentPlayerDeck.poll();
115+
pile.addLast(card);
116+
117+
// Current player must pay off pending penalty
118+
if (pendingPenalty > 0) {
119+
// And player reveals a payment card
120+
if (isPaymentCard(card)) {
121+
// reset penalty based on new card, switch turn
122+
pendingPenalty = penaltyOf(card);
123+
currentPlayer = opponent;
124+
} else {
125+
// Otherwise, deduct penalty
126+
pendingPenalty--;
127+
// No pending penalty
128+
if (pendingPenalty == 0) {
129+
// Opponent collects all pile and win the round
130+
deckOf(opponent, deckA, deckB).addAll(pile);
131+
return new RoundResult(opponent, pile.size());
132+
}
133+
}
134+
} else {
135+
// Normal gameplay, without pending penalty
136+
// If player reveals a payment card, update penalty
137+
if (isPaymentCard(card)) {
138+
pendingPenalty = penaltyOf(card);
139+
}
140+
currentPlayer = opponent;
141+
}
142+
}
143+
}
144+
145+
private void finishGame(Status status, int cardsPlayed, int tricksCount) {
146+
this.status = status;
147+
this.cards = cardsPlayed;
148+
this.tricks = tricksCount;
149+
}
150+
151+
private boolean hasWinner(Deque<String> deckA, Deque<String> deckB) {
152+
return deckA.isEmpty() || deckB.isEmpty();
153+
}
154+
155+
public String getStatus() {
156+
return status != null ? status.name().toLowerCase() : "";
26157
}
27158

28-
String getStatus() {
29-
return matchResult.getStatus().name().toLowerCase();
159+
public int getCards() {
160+
return cards;
30161
}
31162

32-
int getCards() {
33-
return matchResult.getCards();
163+
public int getTricks() {
164+
return tricks;
34165
}
35166

36-
int getTricks() {
37-
return matchResult.getTricks();
167+
/**
168+
* Immutable round result
169+
*/
170+
private record RoundResult(Player nextStarter, int pileSize) {
38171
}
39172
}

exercises/practice/camicia/src/main/java/Card.java

Lines changed: 0 additions & 40 deletions
This file was deleted.

exercises/practice/camicia/src/main/java/MatchResult.java

Lines changed: 0 additions & 75 deletions
This file was deleted.

exercises/practice/camicia/src/main/java/Penalty.java

Lines changed: 0 additions & 36 deletions
This file was deleted.

exercises/practice/camicia/src/main/java/Player.java

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)