I've put together two separate programs which play a card game called 'Crazy Eights'.
The classes I've written for this program are based on a default 'card' package which provides playing card objects and some generic methods for playing cards.
I've taken two separate approaches to achieve this which are both functional in their own right.
Here are two UML class diagrams which depict the two approaches:
Inherited subclass 'conversion' method
Composed subclass with similar methods
As you can see in approach 1 the class EightsCard contains a method convert(Card) Here's the method:
/**
* Converts a Card into an EightsCard
* @param card The card to be converted
* @return The converted EightsCard
*/
public EightsCard convert(Card card) {
if (card != null) {
EightsCard result = new EightsCard(card.getRank(), card.getSuit());
return result;
}
return null;
}
}
This method allows you to call methods from CardCollection which otherwise wouldn't be legal. For example, in the play method from the EightsPlayer class shown below:
/**
* Removes and returns a legal card from the player's hand.
*/
public EightsCard play(Eights eights, EightsCard prev) {
EightsCard ecard = new EightsCard(0, 0);
ecard = ecard.convert(searchForMatch(prev));
if (ecard == null) {
ecard = drawForMatch(eights, prev);
return ecard;
}
return ecard;
}
Approach 2 doesn't require any conversions as the similar methods have been written in a new class EightsCardCollection which extends CardCollection. Now the play methods can be written like this:
public EightsCard play(Eights eights, EightsCard prev) {
EightsCard card = searchForMatch(prev);
if (card == null) {
card = drawForMatch(eights, prev);
}
return card;
}
This brings me to a couple of questions:
For example, might it be better to write 'similar' classes which are more specific1 and not use default classes2 at all.
1 labelled 'crazyeights.syd.jjj' or 'chaptwelvetofort' in the class diagrams.
2 labelled 'defaults.syd.jjj' or cards.syd.jjj' in the class diagrams.
Can an object be a subclass of another object? A. Yes—as long as single inheritance is followed.
Too many subclasses
Neither of these approaches is very good, as both of them have more subclasses than necessary. Why does EightsCard
extend Card
? What if you wanted to implement some other card game? (There are quite a few, you know...) Would you make one subclass for each card game? Please don't.
I would have these classes:
I wouldn't even have a Deck
class as it seems like it does nothing else than extend CardCollection
without providing any more functionality.
Then I would have one class for each game implementation, so one EightsController
class that handles the game logic for that game. No specific class for EightsCard, no specific class for EightsCardCollection, etc.
The reason is simple: You don't need anything more than this. A Card and a CardCollection is exactly the same no matter which card game you are playing. A Player is also the same thing in all games.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With