patternjavaMinor
OOP implementation of BlackJack in Java
Viewed 0 times
javaimplementationoopblackjack
Problem
This code is not done, but still fully functional.
But, before I continue I'd really appreciate some input on the code-structure as is.
AbstractHand.java
Deck.java
Rankable.java
Suitable.java
Card.java
```
package com.tn.blackjack;
import com.tn.deck.Rankable;
import com.tn.deck.Suitable;
public class Card implements Suitable, Rankable, Comparable {
private final Suit suit;
private final Rank rank;
Card(Suit suit, Rank rank) {
this.suit = suit;
this.rank = rank;
}
public Suit getSuit() {
return suit;
}
public Rank getRank() {
return rank;
}
public void print() {
System.out.printf("%s%s ", suit.getIcon(), rank.getName());
}
@Override
public boolean isConsecutive(Card other) {
return 1 + rank.ordinal() == other.rank.ordinal() ||
rank.ordinal() - 1 == other.rank.ordinal();
}
@Override
public boolean isSameSuit(Card other) {
return suit.equals(other.suit);
}
@Override
public int compareTo(Card other) {
if(rank.getValue() == other.getRank().getValue() &&
suit.getIcon().equals(other.getSuit().getIcon())) {
return 0;
} else if(rank.getValue() < other.getRank()
But, before I continue I'd really appreciate some input on the code-structure as is.
AbstractHand.java
package com.tn.deck;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public abstract class AbstractHand {
protected List hand = new ArrayList<>();
public void drawCard(T o) {
hand.add(o);
}
public void drawCards(T[] o) {
hand.addAll(Arrays.asList(o));
}
public abstract void status();
public abstract int calculateScore();
}Deck.java
package com.tn.deck;
public interface Deck {
T dealCard();
T[] dealCards(int n);
void shuffle();
}Rankable.java
package com.tn.deck;
public interface Rankable> {
boolean isConsecutive(T other);
}Suitable.java
package com.tn.deck;
public interface Suitable> {
boolean isSameSuit(T other);
}Card.java
```
package com.tn.blackjack;
import com.tn.deck.Rankable;
import com.tn.deck.Suitable;
public class Card implements Suitable, Rankable, Comparable {
private final Suit suit;
private final Rank rank;
Card(Suit suit, Rank rank) {
this.suit = suit;
this.rank = rank;
}
public Suit getSuit() {
return suit;
}
public Rank getRank() {
return rank;
}
public void print() {
System.out.printf("%s%s ", suit.getIcon(), rank.getName());
}
@Override
public boolean isConsecutive(Card other) {
return 1 + rank.ordinal() == other.rank.ordinal() ||
rank.ordinal() - 1 == other.rank.ordinal();
}
@Override
public boolean isSameSuit(Card other) {
return suit.equals(other.suit);
}
@Override
public int compareTo(Card other) {
if(rank.getValue() == other.getRank().getValue() &&
suit.getIcon().equals(other.getSuit().getIcon())) {
return 0;
} else if(rank.getValue() < other.getRank()
Solution
Overall your code looks pretty good. Nice formatting, nice split of responsibilities (so far), ...
There's only 1 thing that bothers me with your interfaces. And that's the YAGNI principle. That's short for "You Aren't Going to Need It".
Since you're modelling a game of blackjack, you're never really going to need to compare suits, so why provide an interface to do so?
Same for the
It's usually best to not write code that you don't expect to need any time soon. It will just distract you from doing the actual requirements.
Another thing that might be tricky later is the value of an ACE. It could actually be 11 or 1 depending on the total value of your hand. Not that your enum is wrong, but remember that you might have to substract 10 at some point. Alternatively you could give it value 1 in the enum and add 10 when the total hand value is less than 12.
The last thing I want to point out is that the
edit: Just remembered the hidden enum functions. Instead of providing
If you want to keep them for better readability you could also just change their implemenation to this:
There's only 1 thing that bothers me with your interfaces. And that's the YAGNI principle. That's short for "You Aren't Going to Need It".
Since you're modelling a game of blackjack, you're never really going to need to compare suits, so why provide an interface to do so?
Same for the
Rankable interface. When would you need this in a blackjack game?It's usually best to not write code that you don't expect to need any time soon. It will just distract you from doing the actual requirements.
Another thing that might be tricky later is the value of an ACE. It could actually be 11 or 1 depending on the total value of your hand. Not that your enum is wrong, but remember that you might have to substract 10 at some point. Alternatively you could give it value 1 in the enum and add 10 when the total hand value is less than 12.
The last thing I want to point out is that the
calculateScore should be the same for a dealer or a normal player. So you should implement it in the abstract class and drop the abstract keyword. That way you Don't Repeat Yourself (DRY principle).edit: Just remembered the hidden enum functions. Instead of providing
public static Suit[] getSuits() { you could just call Suit.values() which gives you the exact same result. Same for the public static Rank[] getRanks() { method.If you want to keep them for better readability you could also just change their implemenation to this:
public static Rank[] getRanks() {
return Rank.values();
}Code Snippets
public static Rank[] getRanks() {
return Rank.values();
}Context
StackExchange Code Review Q#162728, answer score: 2
Revisions (0)
No revisions yet.