I want to expand my personal projects portfolio, so I decided to make a card game. To be more precise, it's called Macau. I've read this answer on StackOverflow and tried to follow the steps from the first answer. I made a narrative in which I describe the general rules of the game and its particularities.
Macao game. The minimum number of players is 2. The deck of cards initially contains 52 cards. Each card has the following attributes:
- Suit (diamonds, clubs, hearts and spades)
- Rank (2, 3, 4, 5, 6, 7, 8, 9, A, J, Q, K, Joker)
Starting the game, the deck is shuffled and every player receives 5 cards from it. The first player that remains out of cards is the winner. Afterwards, a card is taken from the deck and put on the table with the face up.
The current player looks at the card that's been put on the table and decides whether he can put a card from his packet on the table or not. A player can put a card on the table if their card is compatible with the other one.
Two cards are compatible if they accomplish one of the following conditions: they have the same rank or the same suit. Expanding upon the cards domain, there exist several special cards. These have to obey the specified rules too, but they have an extra attribute: the special ability. They may have any suit, but these ranks qualify a card to be special: 2, 3, 4, 7, A, and Joker. The Joker is a wildcard as it doesn’t need to obey to the earlier specified rule. That is, the player can put it on the table at any time.
The next section gives a thorough description of the mentioned cards’ special abilities:
Rank: 7. When put on the table, this card requires the current player to specify a suit. The next player is obliged to put any card that has the earlier specified suit, otherwise he will receive a new card from the deck.
Rank: 2 and 3. This card obliges the next player to receive 2/3 (2 cards if the rank is 2, same rule for 3) cards from the deck. Now, if the next player also has a 2 or a 3 with the same suit, or a Joker, then he can put it on the table and the next player has to receive the total amount of cards. The same rules apply in a circular manner. If the next player has a 4 with the same suit, then he can stop the obligation injected by the previous player.
Rank: 4. Special ability: it can stop an obligation injected by the previous player. If it is put over a regular card (i.e. a card that has no special ability), then it acts like one.
- Rank: A (Ace). Special ability: it skips the next player's turn.
- Rank: Joker. It is a wildcard so it can be put on the table at almost all instances. The exception arises when the card that is on the top of the table is an A (Ace), then the current player's turn is skipped. Special ability: the same as the 2/3 card, except that the next player will have to receive 5 cards (for the Black Joker) or 10 (in case of the Red one).
Having the rules clarified, the game continues. If the current player owns such a compatible card (or more), then it's his choice whether to put one on the table or receive a new card from the deck. Also, while in game, there can appear the situation when the deck would be emptied. In that case, all the cards from the table that are located under the top one are taken, shuffled, and used to refill the deck. The card on the top is untouched.
Now it's the next player's turn, and the earlier described steps repeat until one of the players remains out of cards. That player is the winner.
From this narrative I extracted the following classes:
- Player (maybe Hand?)
- Table (that contains the Deck and the stack of already played cards)
Here come my problems.
- I'm not sure if I made the right abstractions.
- I wouldn't know how to design the special cards. Should there exist a separate (inherited from Card) class for every special card? Or should I use composition? Also, how should I implement the Joker cards? They don't really have a Suit, they just have the Rank.
- Should the Game class manage players' turns and the exceptional cases (those cases when the top card would be a special one)?
- Should Player be just an interface? This would leave space for additional features like an AI player (that implements Player).
This is my first medium-sized object-oriented project and I want to be sure that I'm on the right path.