Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Java Game Programming For Dummies - W. Holder, D. Bell

.pdf
Скачиваний:
60
Добавлен:
24.05.2014
Размер:
4.92 Mб
Скачать

Chapter 6: Blackjack 125

import java.awt.*;

i mport java.util.StringTokenizer;

public class BlackjackApplet extends java.applet.Applet

i mplements Runnable

 

private Deck

deck;

private BlackjackHand

dealer, lastActive;

private BlackjackPlayer[] players;

private int

curPlayer;

private Button

newdeal, stand, hit, doubledown,

 

split;

private ThreadGroup

appTG;

private Panel

dpan, ppan, bpan;

public void init () {

int

numPlayers = 1, deckSize = l, bankroll = 0;

String

param;

String[]

names = null;

Thread curT = Thread.currentThread(); appTG = curT.getThreadGroup(); curT.setPriority(curT.getPriority() - 1); setLayout(new BorderLayout());

(continued)

11 load the card images

126 Part 11: Up to Speed

(continued)

if ((param = getParameter( PLAYERS )) != null) StringTokenizer st = new StringTokenizer(param, names = new String[st.countTokens()];

for (numPlayers = 0; st,hasMoreTokens(); numPlayers++) names[numPlayers] = st.nextToken();

Card.initGraphics(this); deck = new Deck(deckSize);

players = new BlackjackPlayer[numPlayers];

Bpan = new Panel();

dpan.add(dealer = new BlackjackHand());

add( North , dpan);

 

bpan = new Panel();

 

add( Center , bpan);

 

bpan.add(newdeal

= new Button( Deal ));

bpan.add(new Label(

)):

bpan.add(stand

= new Button( Stand )):

bpan.add(hit

= new Button( Hit ));

bpan.add(doubledown = new Button( Double Down ));

bpan.add(split

= new Button( Split ));

setButtons(null);

 

ppan = new Panel(); add( South , ppan);

for (int ii = 0; ii < numPlayers; ii++) players[ii] = new BlackjackPlayer(ppan,

names == null ? null : names[ii], bankroll);

public boolean action (Event evt, Object what) I i f (evt.target == newdeal)

new Thread(appTG, this).start(); else I

BlackjackPlayer player = getPlayert); i f (evt target == stand)

nextHand(false); else

BlackjackPlayerHand hand = player.getHand(); i f (evt.target == hit) i

hand.deal(deal());

if (hand.value() > 21) nextHand(false);

else setButtons(player);

Chapter 6: Blackjack 127

else if (evt.target == doubledown) I hand.deal(dea1()); player.addToBankroll(-hand.bet): hand.bet <<= 1;

nextHand(false);

else if (evt.target == split) { BlackjackPlayerHand splitHand =

player.newHand(hand.bet);

hand.split(splitHand);

hand.deal(deal());

splltHand.deal(deal()):

setButtons(player);

I else

return super.action(evt, what):

public synchronized void run () { newDeal():

newdeal.disable();

try I

BlackjackPlayerHand hand;

for (int card = 2; --card 7= 0: )

for (int pp = 0; pp < players.length; pp++)

i f ((hand = players[ppl.getHand()) != null) l hand.deal(deal());

Thread.sleep(500);

I dealer.deal(deal()); Thread.sleep(500);

F

if ((hand = nextHand(true)) != null) I setButtons(getPlayer());

wait(); // wait for players to play their hands

setButtons(null);

dealer.expose();

Thread.sleep(1000); i f (hand != null)

while (dealer.value() <= 16) { dealer.deal(deal()); Thread.sleep(500);

(continued)

28 Part I1: Up to Speed

(continued)

E

catch (InterruptedException e) 11

for (int pp = 0; pp < players.length; pp++) players[ppl.resolveDeal(dealer);

newdeal.enable();

I

BlackjackPlayer getPlayer () I

return curPlayer )- players.length ? null : players[curPlayerl;

BlackjackPlayer nextPlayer () I curP]ayer++;

return getPlayer();

BlackjackPlayerHand nextHand (boolean firstHand) {

BlackjackPlayer player = null;

BlackjackPlayerHand hand = null: i f (dealer.blackjack())

curPlayer = players.length;

else if ((player = getPlayer()) != null)

hand = firstHand ?

player.getHand() : player.nextHand();

while (player != null && hand == null)

if ((player = nextPlayer()) != null)

hand = player.getHand();

i f (player == null) I setButtons(null);

synchronized (this) I notify(); I // deal to dealer return null;

1

i f (hand.blackjack()) // skip this hand

return nextHand(false);

setButtons(player); return hand;

boolean newDeal ()

int ii = players.length;

boolean shuffled; curPlayer = 0;

if (shuffled = (deck.getSize() < ii * 3 + 3)) deck.reshuffle();

Chapter 6: Blackjack 129

dealer,clearHand();

while(--ii>=0){

players[iil.clearHands();

players[iij.newHand(0);

newdeal.enable();

setButtons(null); return shuffled;

private void setButtons (BlackjackPlayer player) I i f (lastActive != null) I

l astActive.setActive(false); l astActive = null;

stand.disable();

hit.disable();

split.disable();

doubledown.disable(); i f (player != null)

BlackjackPlayerHand hand = player.getHand(); i f (hand != null) I

(lastActive = hand).setActive(true): stand.enable();

int val = hand.value(); i f (val < 21)

hit.enable():

i € (player.getBankroll() >= hand.bet) I

i f (player.canSplit() && hand.canSplit()) split.enable(};

i f (val <= 11 && hand.cardCount() == 2) doubledown.enable();

private Card deal ()

try f return deck.deal(); )

catch (NoSuchElementException e) { deck.reshuffle();

return deal();

I

}Jl end class BlackjackApplet

130 Part II: Up to Speed

The HTML that loads the applet

The HyperText Markup Language (HTML) document invokes the Blackjack applet using the following applet tag:

<APPLET CODE=BlackjackApplet WIDTH=480 HEIGHT=460>

<PARAM NAME= PLAYERS VALUE= Doug,Wayne,Fast Freddy

</APPLET>

The B 1 a c k j a c k A p p 1 e t gets going like this:

1.HTML passes the player names to the applet.

The applet automatically adjusts the layout for more or fewer players.

2.The applet uses a B o r d e r L a y o u t to divide the applet into the dealer's hand at the top ( N o r th ), the button controls in the middle ( C e n -

te r ), and the players at the bottom ( S o u t h ).

3. i n i t ( ) creates a panel for each of the B o r d e r L ay o u t locations to hold the individual components.

The North location contains only the dealer's hand, but still uses a panel in order to prevent the border layout from resizing the dealer's hand, and cause border layout to resize the panel instead. Each of these panels uses the default F1 owLayout manager.

4. s e tB ut t o n s ( ) enables and disables the buttons to match the legal options for a given point in the game.

The state-driven approach determines by examining the state of the game the required state of the buttons.

5. d e a 1 ( ) deals cards from the deck and automatically reshuffles if the cards have all been dealt.

6.The applet spawns a new thread when the user presses the Deal button.

The thread controls the tempo of the deal from the run ( ) method.

7.After r u n ( ) deals the initial hands, the applet's Deal thread needs to wait for the players to play their hands.

run ( ) calls wa i t ( ) on the applet and waits for acti on () to handle the user options.

8. n ex t H a n d () determines the next hand to play and sets it as the active hand.

If the next hand is the dealer's hand, nextHand ( ) calls not i fy ( ) to wake up the Deal thread. When the Deal thread wakes up, run ( ) plays the dealer's hand, settles the bets with each player, enables the Deal button, and exits the thread.

Chapter 6: Blackjack 131

The players

Each player requires additional user interface elements:

-Label s to display the player's name and current bankroll

-A C h o i c e selector to allow the amount of the next bet to be selected

-A P a n e 1 to display the player's Blackjack hand(s)

B 1

a c k j a c k P 1 a y e r panel groups together these interface elements. A

B 1

a c k j a c k P 1 a y e r also includes all the necessary methods and fields for

keeping track of a player. The following code implements B 1 a c k j a c k P 1 a y e r:

i mport java.awt.*;

class BlackjackPlayer extends Panel {

public static final int STANDARD BET = 10;

public static final int STANDARD-BANKROLL = 1000;

private static int[]

betAmount

I l, 5, 10, 20, 30, 50, 100, 200, 500, 10001;

private static int

playerCount;

private String

name;

private int

l astBet, bankroll, curHand,

 

numHands;

private final BlackjackPlayerHand[]

 

hands = new BlackjackPlayerHand[4];

private Label

bankrollLabel;

private Choice

betEntry;

private Panel

handsPanel;

BlackjackPlayerHand getHand () I

return curHand >= numHands ? null : hands[curHand];

l

i nt getHandlndex () i

return curl-and >= numHands ? 1 : curl-and;

I

BlackjackPlayerHand nextHand () curHand++; handsPanel.layout();

return getHand();

1

i nt getBankroll () ( return bankroll; }

i nt getActiveHandCount () I return numHands; l

(continued)

32 Part II: Up to Speed

(continued)

boolean canSplit () I return numHands < hands length; I BlackjackPlayer (Container parent) I

this(parent, null, STANDARD_BANKROLL);

I

BlackjackPlayer (Container parent, String name,

i nt bankroll) I

parent.add(this); setLayout(new BorderLayout()):

playerCount++;

 

i f (name == null)

 

name = Player

+ playerCount;

add( North , new

Label (this.name = name, Label. CENTER));

i f (bankroll <= 0)

bankroll = STANDARD_BANKROLL;

String bankStr = Integer.toString(bankroll);'' Font font = new Font( Courier , Font.PLAIN, 10); bankrollLabel = new Label(bankStr, Label.RIGNT); betEntry = new Choice();

for (int ii = 0; ii < betAmount.1ength; ii++) betEntry.addItem(Integer.toString(betAmount[iil));

bankrollLabel.setFont(font);

betEntry.setFont(font): Panel pbank = new Panel(); add( Center , pbank); pbank.add(bankrol]Label); pbank.add(betEntry); addToBankroll(bankroll); setBet(STANDARDBET);

handsPanel = new Panel():

handsPanel.setLayout(new PlayerHandLayout(this, .3Of)); handsPanel.setBackground(Color.gray);

add( South , handsPanel);

for (int hh = 0; hh < hands.length; hh++) handsPanel.add(hands[hh] =

new BlackjackPlayerHand(this));

public boolean action (Event evt, Object what) i f (evt.target == betEntry)

setBet(Integer.parselnt(betEntry.getSelectedltem()));

Chapter 6: Blackjack 133

else

return super.action(evt, what); return true;

synchronized void clearHands () { while (numHands > 0)

hands[--numHandsl.clearHand(); curHand = 0; handsPanel.layout();

synchronized void resolveDeal (BlackjackHand dealer) I for (int hh = numHands; --hh >= 0; )

addToBankroll(hands[hh].winnings(dealer));

synchronized BlackjackPlayerHand newHand (int bet) I BlackjackPlayerHand result = null;

i f (bet == 0) bet = lastBet;

i f (numHands < hands.length && (bet = setBet(bet)) > 0)f result = hands[numHands++];

addToBankroll(-(result.bet = bet)); handsPanel.layout();

return result;

i nt setBet (int bet) { i f (bet > bankroll)

for (int i = betAmount.length;

i > 0 && (bet = betAmount[--i]) > bankroll; ); betEntry.select(Integer.toString(bet));

return lastBet = bet;

void addToBankroll (int amount) I this.bankroll += amount;

bankrollLabel.setText(Integer.teString(this.bankroll));

I /I end class BlackjackPlayer

array field stores all the hands.

4 Part II: Up to Speed

The responsibilities of a B 1 a c k j a c k P 1 a y e r are

V A B 1 a c k j a c k P 1 aye r can have up to four hands active at once. The

h and s C ]

- BlackjackPlayer uses a BorderLayout and places the name label in

the

N o r t h

location, the current bankroll and the bet selector in

the

C e n t e r , and the player's Blackjack hands in the S o u t h .

- g e t H a n d ( )

and n

ext H a n d ( ) return and update the current active

hand. n ewH a n d ( )

activates a new hand after first checking that the

player has enough money to cover the bet.

V The addToBankro110 and setBet( ) methods manage the player's money. These methods are responsible for making sure that the player

never gambles money he doesn't have.

V B 1 a c k j a c k P 1 aye r overrides a c t i o n ( ) to handle the events from the C h o i c e selector used to set the player's next bet.

The players' hands

The hand for a player is a specialized case of the B 1 a c k j a c k H a n d that the dealer uses, as discussed earlier in this chapter. On top of the dealer's hand's function, the player's hand has to handle the additional duties of wagering and splitting. The B 1 a c k j a c k P 1 a y e r H a n d extends the

B1 ackjackHand like this:

import java.awt.*;

class BlackjackPlayerHand extends BlackjackHand I i nt bet;

private boolean hasSplit;

BlackjackPlayerHand (Container parent) I super();

horizInset = 3; parent.add(this);

protected boolean isDealer () { return false boolean blackjack () {

return !hasSplit && super.blackjack();

1

boolean canSplit () I

return hand.size() == 2 && value(o) == value(1);