Update: Simple Blackjack implementation
I was playing Blackjack in a phone app and decided to try to do the game in Java, using the console for a start. So far I'd like to review the deck of cards implementation. I decided to use an OOP approach with the classes Value
, Suit
, Card
and Deck
.
First of all, I'd like to get some feedback and pieces of advice about how I decided to structure my code. Is there anything wrong? Should something be done differently?
import java.util.Stack;
import java.util.Random;
import java.util.Collections;
public class Blackjack {
public static String capitalizeFully(String str) {
String s = new String();
for (int i = 1; i < str.length(); i++) {
s += Character.toLowerCase(str.charAt(i));
}
return Character.toUpperCase(str.charAt(0)) + s;
}
public static class Value {
private int value;
private static final String[] string_values = {
"Ace",
"Two",
"Three",
"Four",
"Five",
"Six",
"Seven",
"Eight",
"Nine",
"Ten",
"Jack",
"Queen",
"King"
};
public Value(int value) throws IllegalArgumentException {
if (value < 1 || value > 13) {
throw new IllegalArgumentException("Invalid card value (must be between 1 and 13).");
}
this.value = value;
}
public Value(String value) throws IllegalArgumentException {
int i = 0;
String val = capitalizeFully(value);
while (i < string_values.length && !val.equals(string_values[i])) {
i++;
}
if (i == string_values.length) {
throw new IllegalArgumentException("Invalid card value.");
} else {
this.value = i + 1;
}
}
public String toString() {
return string_values[value - 1];
}
}
public static class Suit {
private String name;
private static final String[] string_names = {
"Hearts",
"Diamonds",
"Clubs",
"Spades"
};
public Suit(String name) throws IllegalArgumentException {
int i = 0;
String n = capitalizeFully(name);
while (i < string_names.length && !n.equals(string_names[i])) {
i++;
}
if (i == string_names.length) {
throw new IllegalArgumentException("Invalid suit name.");
} else {
this.name = n;
}
}
public String toString() {
return name;
}
}
public static class Card {
private Value value;
private Suit suit;
public Card(Value value, Suit suit) {
this.value = value;
this.suit = suit;
}
public Card(int value, Suit suit) {
this.value = new Value(value);
this.suit = suit;
}
public Card(String value, Suit suit) {
this.value = new Value(value);
this.suit = suit;
}
public Card(Value value, String suit) {
this.value = value;
this.suit = new Suit(suit);
}
public Card(int value, String suit) {
this.value = new Value(value);
this.suit = new Suit(suit);
}
public Card(String value, String suit) {
this.value = new Value(value);
this.suit = new Suit(suit);
}
public String toString() {
String str = value + " of " + suit;
return str;
}
}
public static class Deck {
private Stack<Card> deck;
private static final int number = 52;
public Deck() {
deck = new Stack<Card>();
Suit hearts, diamonds, clubs, spades;
hearts = new Suit("hearts");
diamonds = new Suit("diamonds");
clubs = new Suit("clubs");
spades = new Suit("spades");
Suit[] suits = { hearts, diamonds, clubs, spades };
for (int i = 0; i < suits.length; i++) {
for (int j = 1; j <= 13; j++) {
deck.push(new Card(j, suits[i]));
}
}
}
public void shuffle() {
long seed = System.nanoTime();
Collections.shuffle(deck, new Random(seed));
}
public void add(Card card) {
deck.push(card);
}
public Card draw() {
return deck.pop();
}
public String toString() {
String str = new String();
for (int i = 0; i < deck.size(); i++) {
str += deck.get(i) + "\n";
}
return str;
}
}
public static <T> void p(T output) {
System.out.println(output);
}
public static void main(String[] args) {
Deck deck = new Deck();
deck.shuffle();
p(deck);
}
}
However, this is an implementation for just the 52-card standard deck. How about different decks, with different suits and a different range of values? I thought maybe it'd be a good idea that instead of hardcoding these attributes, I could make an alternative implementation where the user can define his/her own set of suits and range of values, so the deck is constructed given these set of choices.
For example:
Value[] values = { new Value("As", 1), new Value("Dos", 2), ..., new Value("Rey", 12) };
Suit[] suits = { new Suit("Oros"), new Suit("Sotas"), new Suit("Espadas"), new Suit("Bastos") };
Deck spanish_deck = new Deck(suits, values);
Does this second alternative make sense? Is it a good approach?
Update: Simple Blackjack implementation