For example, if a method existed that accepted an Automobile object as a parameter: public void doSomethingAutomobile auto { … } You can pass in a BigTruckobject, because it is an Automo
Trang 1toString() method in the BigTruck class overrides this method to include whether or not a trailer is attached First you used what you learned about the
superkeyword to call Automobile’s version of the method, and then you simply appended the trailervalue
Polymorphism
Polymorphism is another complicated word for a simple concept It simply means
that an instance of a subclass is also an instance of its superclass A BigTruck
instance is an Automobiletoo All classes inherit from the Objectclass defined in the Java language, so every instance of Automobile and BigTruck is also an instance of Object For example, if a method existed that accepted an Automobile
object as a parameter:
public void doSomething(Automobile auto) { … }
You can pass in a BigTruckobject, because it is an Automobile:
BigTruck truck = new BigTruck();
doSomething(truck);
Back to the BlackJack Game
You’ve learned a great deal about object-oriented programming in this chapter Now you put this knowledge to good use by creating a text-based version of a blackjack game In this section you subclass the CardDeckclass, to create Random-CardDeck, a randomized deck of cards so the game isn’t predictable You also learn about the java.util.Vector class, which will help in creating the final game Finally, you write the actual BlackJackapplication
The RandomCardDeck Class
You’ve already written a class that represents a deck of cards, the CardDeckclass Now you just need to override it so that the Cards stored in the deck are random-ized To do this, you import the java.util.Randomclass In the constructor, you call the superclass’s constructor to build a regular CardDeck, and then you call the new shuffle() method to rearrange the Cards randomly One other thing you need to do is override the reset()method so that when you reset the top card, you also shuffle the deck Here is the source listing for RandomCardDeck.java:
/*
* RandomCardDeck
* Simulates a shuffled deck of cards
*/
158
J a
s o
l ut
n e
Trang 2import java.util.Random;
public class RandomCardDeck extends CardDeck { public RandomCardDeck () {
super();
shuffle();
} public void shuffle() { Card[] shuffled = new Card[cards.length];
Random rand = new Random();
int cIndex;
boolean placed;
for (int c=0; c < cards.length; c++) {
do { placed = false;
cIndex = rand.nextInt(cards.length);
if (shuffled[cIndex] == null) { shuffled[cIndex] = cards[c];
placed = true;
} } while (!placed);
} cards = shuffled;
top = 0;
} public void reset() { super.reset();
shuffle();
} }
The shuffle()method deserves some elaboration A new Cardarray, shuffled, is declared locally in this method Its purpose is to be a temporary placeholder for the deck of cards as it is being shuffled It is initialized to the same size as the
cards array instance variable This initializes the Cardobjects in the shuffled
array to null The forloop loops on all the Cards in the existing cardsarray, one
at a time Then a random index for the shuffledarray is created If a card has not already been placed at this index, stored in cIndex(you can tell because the Card
object there is null), the card is placed there; if it is already occupied by another
Card, it continues to look for vacancies until it finds one
So, the cards in the cardsarray are copied, one by one, randomly into the shuf-fledarray, and then the shuffledarray is assigned to the cardsinstance variable, causing it to be shuffled, and then the topvariable is reset to 0 The RandomCard-DeckTest program tests to make sure that the RandomCardDeckclass works the way you expect it to The output is shown in Figure 5.11 Here is the source code:
159
l a
j a
j e
i e
i n
Trang 3* RandomCardDeckTest
* Tests the RandomCardDeck class
*/
public class RandomCardDeckTest { public static void main(String args[]) { RandomCardDeck deck = new RandomCardDeck();
System.out.println(“Deck list:”);
deck.list();
Card card = deck.deal();
System.out.println(“Dealt “ + card);
System.out.println(“Shuffling ”);
deck.shuffle();
System.out.println(“Deck list:”);
deck.list();
} }
The Vector Class
The java.utilpackage contains many useful classes, including the Random and
Vectorclasses The Vectorclass implements a growable array of objects It acts similarly to an array except that the size automatically grows and shrinks as objects are added and removed It is of interest here because you use the Vector
class to represent the dealer’s and the player’s hand in the BlackJackgame Table 5.1 contains some useful Vectormethods Remember that because of polymor-phism, any object can be passed to the methods that accept an Objectinstance The VectorVictorapplication demonstrates simple use of the Vectorclass The source code for VectorVictor.javais as follows:
160
J a
s o
l ut
n e
FIGURE 5.11
The RandomCardDeck class represents a random deck of playing cards.
Trang 4* VectorVictor
* Demonstrates the Vector class
*/
import java.util.Vector;
public class VectorVictor { public static void main(String args[]) { //initialize a vector of capacity 5 and increment 5 Vector v = new Vector(5, 5);
System.out.println(“size, capacity”);
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“Fuzzy”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“Wuzzy”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“was”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“a”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“bear”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“Fuzzy”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“Wuzzy”));
System.out.println(v.size() + “, “ + v.capacity());
161
l a
j a
j e
i e
i n
Method Description
void add(int index, Object element) Insertselementat the specified index, shifting
the remaining indices by adding 1
boolean add(Object element) Appendselementto the end; returns true int capacity() Returns the capacity (current maximum size).
void copyInto(Object[] anArray) Copies the Vector ’s elements into the given
array.
Object elementAt(int index) Returns the element at the given index.
Object remove(int index) Removes and returns the object at the given
index.
boolean remove(Object element) Removes the first occurrence of element void trimToSize() Sets the capacity of the Vector to its current
size.
TA B L E 5 1 V E C T O R ME T H O D S
Trang 5v.add(new String(“had”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“no”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“hair”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“Fuzzy”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“Wuzzy”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“wasn’t”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“fuzzy”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“was”));
System.out.println(v.size() + “, “ + v.capacity());
v.add(new String(“he”));
System.out.println(v.size() + “, “ + v.capacity());
v.trimToSize();
System.out.println(v.size() + “, “ + v.capacity());
//copy into an array String[] str = new String[v.size()];
v.copyInto(str);
for (int s=0; s < str.length; s++) { System.out.print(str[s] + “ “);
} } }
The constructor accepts two int arguments The first argument is the initial capacity of the Vectorand the second one is the capacity increment The capac-ity increment is the amount by which the capaccapac-ity increases any time adding an element to the Vectorcauses the size to be greater than its capacity As you can see in the output shown in Figure 5.12, anytime the size of the Vectorexceeds
162
J a
s o
l ut
n e
FIGURE 5.12
What’s your Vector , Victor?
Trang 6the capacity, it grows by a factor of 5 This program also demonstrates copying the elements of the Vectorinto an array
The BlackJack Program
Okay, here it is, the final project source code listing for BlackJack.java:
/*
* BlackJack
* A simple BlackJack card game simulation
*/
import java.util.Vector;
import java.io.*;
public class BlackJack { protected RandomCardDeck deck;
protected Vector dealerHand, playerHand;
protected int dealerPoints, playerPoints;
protected final static char HIT = ‘H’, STAND = ‘S’;
public BlackJack() { Card card;
dealerHand = new Vector();
playerHand = new Vector();
deck = new RandomCardDeck();
for (int c=0; c < deck.getNumCards(); c++) { card = deck.getCard(c);
if (card.isPictureCard()) { card.setValue(10);
} else if (card.getFaceValue() == Card.ACE) { card.setValue(1);
} } } public static void main(String args[]) { BufferedReader reader;
char input;
BlackJack bj = new BlackJack();
reader = new BufferedReader(new InputStreamReader(System.in));
do { bj.play();
System.out.print(“Play Again (Y/N)? “);
try { input = Character.toUpperCase(reader.readLine().charAt(0));
} catch (IOException ioe) { input = ‘?’; } } while (input == ‘Y’);
}
163
l a
j a
j e
i e
i n
Trang 7J a
s o
l ut
n e
public void play() { int input;
dealerHand.clear();
playerHand.clear();
if (deck.getNumCardsLeft() <= 15) { System.out.println(“Shuffling deck ”);
deck.shuffle();
} deal();
output();
if (playerBlackJack()) { System.out.println(“Player has BlackJack!!!”);
((Card)dealerHand.elementAt(0)).setVisible(true);
output();
if (dealerBlackJack()) { System.out.println(“Dealer also has BlackJack.”);
System.out.println(“Game is a PUSH.”);
} else { System.out.println(“Player wins!”);
} } else if (dealerBlackJack()) { ((Card)dealerHand.elementAt(0)).setVisible(true);
System.out.println(“Dealer has BlackJack.”);
output();
System.out.println(“Player loses.”);
} else { // hit or stand loop.
do { try { input = getUserInput();
} catch (IOException ioe) { input = STAND; }
if (input == HIT) { System.out.println(“Dealt “ + hitPlayer());
output();
}
if (playerPoints > 21) { System.out.println(“Player BUSTS!”);
((Card)dealerHand.elementAt(0)).setVisible(true);
output();
System.out.println(“Player loses.”);
} } while (input == HIT && playerPoints < 21);
if (playerPoints <= 21) { System.out.println(“Dealer’s turn”);
((Card)dealerHand.elementAt(0)).setVisible(true);
output();
while (dealerPoints <= 16) { System.out.println(“Dealer gets “ + hitDealer());
output();
}
Trang 8if (dealerPoints > 21) { System.out.println(“Dealer BUSTS!”);
System.out.println(“Player wins!”);
} else if (dealerBlackJack()) { System.out.println(“Dealer has BlackJack.”);
System.out.println(“Player loses.”);
} else if (dealerPoints == playerPoints) { System.out.println(“The game is a PUSH.”);
} else if (dealerPoints > playerPoints) { System.out.println(“Player loses.”);
} else { System.out.println(“Player wins!”);
} } } } protected void deal() { Card card;
playerHand.add(deck.deal());
playerHand.add(deck.deal());
card = deck.deal();
card.setVisible(false);
dealerHand.add(card);
dealerHand.add(deck.deal());
updatePoints();
} protected void output() { String d = “Dealer’s Hand: “;
String p = “Your Hand : “;
for (int c=0; c < dealerHand.size(); c++) {
d += (Card)dealerHand.elementAt(c) + “ “;
} for (int c=0; c < playerHand.size(); c++) {
p += (Card)playerHand.elementAt(c) + “ “;
}
if (d.indexOf(‘?’) == -1) {
d += “ (“ + dealerPoints +”)”;
}
p += “ (“ + playerPoints +”)”;
System.out.println(d);
System.out.println(p);
} protected Card hitPlayer() { return hit(playerHand);
}
165
l a
j a
j e
i e
i n
Trang 9protected Card hitDealer() { return hit(dealerHand);
} protected char getUserInput() throws IOException { BufferedReader reader;
char input;
reader = new BufferedReader(new InputStreamReader(System.in));
do { System.out.print(“(H)it or (S)tand? “);
input = Character.toUpperCase(reader.readLine().charAt(0));
} while (input != HIT && input != STAND);
return input;
} protected boolean dealerBlackJack() {
if (dealerHand.size() == 2) {
if (((Card)dealerHand.elementAt(1)).getFaceValue() == Card.ACE
|| ((Card)dealerHand.elementAt(0)).getVisible()) { return dealerPoints == 21;
} } return false;
} protected boolean playerBlackJack() {
if (playerHand.size() == 2) { return playerPoints == 21;
} return false;
} private Card hit(Vector hand) { Card card = deck.deal();
hand.add(card);
updatePoints();
return card;
} protected void updatePoints() { playerPoints = addUpPoints(playerHand);
dealerPoints = addUpPoints(dealerHand);
} private int addUpPoints(Vector hand) { int points = 0;
int nAces = 0;
Card[] cards = new Card[hand.size()];
hand.copyInto(cards);
for (int c=0; c < cards.length; c++) { points += cards[c].getValue();
if (cards[c].getFaceValue() == Card.ACE) nAces++;
}
166
J a
s o
l ut
n e
Trang 10if (points <= 11 && nAces > 0) { points += 10;
} return points;
} }
This class defines five instance variables deck is a RandomCardDeckobject that stores the deck of cards dealerHandand playerHandare Vectorobjects that rep-resent the dealer’s cards and the player’s cards, respectively dealerPointsand
playerPointsstore the dealer’s points and the player’s points There are also two class variable charconstants, HITand STAND They are used as flags that are com-pared to user input in order to determine whether the user wants to hit or stand
The constructor initializes the game for playing The most notable thing in the game is where it calls the isPictureCard()method defined in the Cardclass You
do this so that you can set the value of all picture cards to 10 Also, it references the Card.ACEconstant to find the Aces and set their initial values to 1
The main() method creates a new BlackJack instance and calls the play()
method in a do-whileloop It continues to call play()while the users enter Yto continue playing Aside from the main()method, play()is the only other public
method In this implementation of the BlackJackgame, it is not necessary to give everyone access to any other method You allow instances to only call the play()
method, which defines one hand of blackjack If you decide to create a new ver-sion of the game, you can always subclass or redefine the BlackJackclass itself
The play() Method: BlackJack Driver
The play() method is the driver for the game First it clears the dealer’s and player’s hands Then it shuffles the deck if the number of remaining cards is run-ning low (15 or fewer) It deals the cards by calling the deal() method, which basically deals the cards to the dealer (one face down and one face up) and the player (both cards visible) When it prints the cards, it calls the output()method, which builds a Stringrepresentation of the hands Note that when the Vector’s
elementAt()method is called, the return value must be cast to a Cardobject in order to get its Stringrepresentation:
p += (Card)playerHand.elementAt(c) + “ “;
If after the cards are dealt, either the dealer or the player has blackjack, the hand
is over; otherwise the player is prompted to hit or stand The getUserInput()
method prompts the users It will accept only an Hor an Sand will continue to prompt the user until it gets one of those responses This method throws an
IOException, which is caught back in play(), where if it does occur, in order to
167
l a
j a
j e
i e
i n