//
// Copyright (C) 1999 Grace Software
//
// The contents of this file are subject to the Grace Software Public
// License Version 1.0 (the "GracePL"); you may not use this file
// except in compliance with the GracePL. You may obtain a copy of the
// GracePL at http://www.homestead.com/javalog/files/license.html
//
// Software distributed under the GracePL is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
// the GracePL for the specific language governing rights and
// limitations under the GracePL.
//
// The Original Code is Grace Software's JavaLog code, released March
// 21, 1999. The Initial Developer of the Original Code is Grace
// Software. Portions created by Grace Software are Copyright (C)
// 1999 Grace Software. All Rights Reserved.
//
// Contributor(s):
//
/*blackjack.java -- This program demonstrates the card class. It does
not implement all the rules of blackjack (maybe later). I bashed it together
in an afternoon so I could have a realistic demo of the card class to show
you.
*/
import java.awt.*;
import java.applet.*;
import java.util.*;
public class blackjack extends Applet implements Runnable
{
Image osi; Graphics osg;
Image bufferImage; Graphics bufferGraphics; // double buffering - not needed in many cases
int cardWidth=85; // this cannot be changed
int cardHeight=125; // this cannot be changed
double sizeOfCard=1.0; // you can modify the size, but it will look like crap
cardclass cc;
int CLUB=1;
int DIAMOND=2;
int HEART=3;
int SPADE=4;
int currentCard=0;
Random rnd = new Random();
int temp[]=new int[52];
int deal[]=new int[52];
Thread kicker = null;
boolean newDeal=true;
boolean hitPressed=false;
boolean stayPressed=false;
boolean userAce=false;
boolean dealerAce=false;
boolean dealOver=false;
boolean showScoreOK=false;
Font header = new Font("TimesRoman", Font.BOLD, 24);
Font normal = new Font("TimesRoman", Font.PLAIN,12);
Button hit = new Button("Hit");
Button stay = new Button("Stay");
Button redeal = new Button("Redeal");
int userCardPosition;
int dealerCardPosition;
int hiddenCard;
int userScore=0;
int dealerScore=0;
//
// there are three graphics screens to worry about.
// a. The normal screen that gets the buttons
// b. An offscreen graphic (bufferGraphic) that is used for double buffering
// c. An offscreen graphic (osg) that gets a card painted on it by
// the cardclass.class.
//
public void init()
{
// create the offscreen graphics
osi=createImage(cardWidth,cardHeight);
osg=osi.getGraphics();
bufferImage=createImage(640,480);
bufferGraphics=bufferImage.getGraphics();
// instantiate the card class
cc=new cardclass(this);
// make an array of cards that number from 1 to 52
makeDeck();
//
// use null layout for the buttons - the graphic will paint behind them
//
setLayout(null);
addNotify();
add(hit);
hit.reshape(insets().left + 270,insets().top + 285,40,20);
add(stay);
stay.reshape(insets().left + 320,insets().top + 285,40,20);
add(redeal);
redeal.reshape(insets().left + 370, insets().top + 285,60,20);
}
//
// restart uses a new deck each time. This is not how real blackjack is
// played.
//
public void restart()
{
newDeal=true;
hitPressed=false;
stayPressed=false;
currentCard=0;
makeDeck();
userScore=0;
dealerScore=0;
userAce=false;
dealerAce=false;
dealOver=false;
showScoreOK=false;
}
//
// booleans are used in the run thread. When one is detected, the
// thread processes it. The booleans are set by mouse clicks on
// the buttons or by the restart/init methods.
//
public void run()
{
// Create the thread
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
// Do the animation
while (kicker != null)
{
if(newDeal) // restart (and init) method sets this
{
deal();
newDeal=false;
checkForBlackJack();
}
if((hitPressed) && (!stayPressed)) // buttons set this
{
doUserHit();
hitPressed=false;
}
if(stayPressed) // buttons set this
{
checkDealerStatus();
stayPressed=false;
}
repaint();
pause(20);
}
}
public void checkForBlackJack() // called right after the initial deal
// by the deal method
{
if(dealerScore==21)
{
stayPressed=true;
checkDealerStatus(); // this will flip over hidden card and
// declare winner using normal testing methods
return;
}
if(userScore==21) // if user has blackjack, it is handled as a special
// case here
{
bufferGraphics.setColor(Color.green.darker());
bufferGraphics.fillRect(110,140,90,10);// erase previous score
bufferGraphics.setColor(Color.black);
bufferGraphics.drawString("You BLACKJACK .. you win",110,150);
bufferGraphics.setColor(Color.green.darker());
bufferGraphics.fillRect(110,290,190,310);// erase previous score
bufferGraphics.setColor(Color.black);
bufferGraphics.drawString("You BLACKJACK .. you win",110,305);
dealOver=true;
}
}
public void checkDealerStatus() // called after the 'Stay' button is
// pressed and by 'checkForBlackJack'
// when dealer has 21 on first two cards
{
// first, we flip over the hidden card
int card;
int suit;
card=hiddenCard;
suit=hiddenCard;
card=(card % 13)+1;
suit=(suit % 4)+1;
osg.setColor(Color.green.darker()); // see doDealerHit - we need to reverse what we did there
osg.fillRect(0,0,20,185);
cc.drawCard(osg,card,suit,0);
bufferGraphics.drawImage(osi,50,15,this);
pause(100);
repaint();
pause(100);
while(dealerScore<17)
{
doDealerHit();
repaint();
}
if(dealerScore>21) return;
pause(100);
// check to see who has higher score
bufferGraphics.setColor(Color.green.darker());
bufferGraphics.fillRect(110,140,90,10);// erase previous score
bufferGraphics.setColor(Color.black);
if (userScore>dealerScore)
bufferGraphics.drawString("Dealer loses .. you win",110,150);
else
bufferGraphics.drawString("Dealer wins .. you lose",110,150);
dealOver=true;
}
public void doUserHit() // called with the 'Hit' button is pressed
{
int card;
int suit;
currentCard++;
userCardPosition+=20; // move the card over so you can see the ones underneath
card=deal[currentCard];
suit=deal[currentCard];
card=(card % 13)+1;
suit=(suit % 4)+1;
addUserScore(card);
osg.setColor(Color.white); // this is screwed. .. it is needed to make the card overlap look right
osg.fillRect(0,0,20,185);
osg.setColor(Color.black);
osg.drawLine(0,0,20,0);
osg.drawLine(0,124,20,124);
cc.drawCard(osg,card,suit,0);
bufferGraphics.drawImage(osi,userCardPosition,155,this);
pause(200);
}
public void addUserScore(int card) // called by the doUserHit and deal methods
{
if(card>9) userScore+=10;
else userScore+=card;
if((card==1) && (userScore<12)) { userScore+=10; userAce=true; }// Ace
if(userScore > 21)
{
if(userAce)
{
userScore-=10;
userAce=false;
}
}
bufferGraphics.setColor(Color.green.darker());
bufferGraphics.fillRect(110,290,190,310);// erase previous score
bufferGraphics.setColor(Color.black);
if(userScore < 22) bufferGraphics.drawString("Your Total = " + Integer.toString(userScore),110,305);
else
{
bufferGraphics.drawString("You Busted .. you lose",110,305);
dealOver=true;
}
}
public void addDealerScore(int card) // called by the doDealerHit method and deal method
{
if(card>9) dealerScore+=10;
else dealerScore+=card;
if((card==1) && (dealerScore<12))
{
dealerScore+=10;
dealerAce=true;
}// Ace
if(dealerScore > 21)
{
if(dealerAce)
{
dealerScore-=10;
dealerAce=false;
}
}
if(showScoreOK)
{
bufferGraphics.setColor(Color.green.darker());
bufferGraphics.fillRect(110,140,90,10);// erase previous score
bufferGraphics.setColor(Color.black);
if(dealerScore < 22) bufferGraphics.drawString("Dealer Total = " + Integer.toString(dealerScore),110,150);
else
{
bufferGraphics.drawString("Dealer Busted .. you win",110,150);
dealOver=true;
}
}
}
public void doDealerHit() // called by checkDealerStatus method
{
int card;
int suit;
currentCard++;
dealerCardPosition+=20; // move the card over so you can see the ones underneath
card=deal[currentCard];
suit=deal[currentCard];
card=(card % 13)+1;
suit=(suit % 4)+1;
addDealerScore(card);
osg.setColor(Color.white); // this is screwed. .. it is needed to make the card overlap look right
osg.fillRect(0,0,20,185);
osg.setColor(Color.black);
osg.drawLine(0,0,20,0);
osg.drawLine(0,124,20,124);
cc.drawCard(osg,card,suit,0);
bufferGraphics.drawImage(osi,dealerCardPosition,15,this);
pause(200);
}
public void pause(int sleepTime) // if you want to speed things up, uncomment the following line
{
// sleepTime=1;
try {Thread.sleep(sleepTime);} catch (InterruptedException e){}
}
public void start()
{
if (kicker == null) {
kicker = new Thread(this);
kicker.start();
}
}
public void stop()
{
kicker = null;
}
public void deal() // called for the initial deal of the cards. This
// is where you set up the screen.
{
int card;
int suit;
// make the basic fields of the table and the cards green
// the cardclass will make the cards themselves white
// if you don't do this, there will be an ugly corner on
// each card that shows through white on your green table
osg.setColor(Color.green.darker());
osg.fillRect(0,0,cardWidth,cardHeight);
bufferGraphics.setColor(Color.green.darker());
bufferGraphics.fillRect(0,0,640,480);
bufferGraphics.setFont(normal);
card=deal[currentCard];
suit=deal[currentCard];
hiddenCard=card;
card=(card % 13)+1;
suit=(suit % 4)+1;
addDealerScore(card);
cc.drawCard(osg,0,suit,1);
bufferGraphics.setColor(Color.gray);
bufferGraphics.drawString("Delays are on purpose (makes things look nicer).", 250,30);
bufferGraphics.setColor(Color.yellow.brighter());
bufferGraphics.setFont(header);
bufferGraphics.drawString("BLACKJACK SHELL", 250, 70);
bufferGraphics.setFont(normal);
bufferGraphics.setColor(Color.black);
bufferGraphics.drawString("This shell only demonstrates the card class. It doesn't", 250,90);
bufferGraphics.drawString("implement the full set of BlackJack rules. But it's still fun.", 250,105);
bufferGraphics.drawString("Dealer",125,150);
bufferGraphics.drawString("You",132,290);
pause(100);
repaint();
bufferGraphics.drawImage(osi,50,15,this);
pause(100);
repaint();
currentCard++;
card=deal[currentCard];
suit=deal[currentCard];
card=(card % 13)+1;
suit=(suit % 4)+1;
addDealerScore(card);
cc.drawCard(osg,card,suit,0);
bufferGraphics.drawImage(osi,150,15,this);
dealerCardPosition=150;
pause(200);
repaint();
// now player
currentCard++;
card=deal[currentCard];
suit=deal[currentCard];
card=(card % 13)+1;
suit=(suit % 4)+1;
cc.drawCard(osg,card,suit,0);
addUserScore(card);
bufferGraphics.drawImage(osi,50,155,this);
pause(200);
repaint();
currentCard++;
card=deal[currentCard];
suit=deal[currentCard];
card=(card % 13)+1;
suit=(suit % 4)+1;
addUserScore(card);
cc.drawCard(osg,card,suit,0);
userCardPosition=150;
bufferGraphics.drawImage(osi,150,155,this);
}
public void makeDeck() // a simple shuffling routine which makes an
// array of 52 ints that range from 1 - 52 and are
// random and non-repeating
{
int r, x, y;
y=0;
for (x=0;x<52;x++){ temp[x]=0; deal[x]=0;}
r=Math.abs(rnd.nextInt()%52);
while(y<52)
{
while(temp[r]==1) r=Math.abs(rnd.nextInt()%52);
temp[r]=1;
deal[y]=r+1;
y++;
}
currentCard=0;
}
public void paint(Graphics g)
{
update(g);
}
public void update(Graphics g)
{
g.drawImage(bufferImage,0,0,this);
}
public boolean action (Event e, Object arg) // catch the button clicks and do something
{
if((arg=="Hit")&&(!dealOver)) hitPressed=true;
if((arg=="Stay")&&(!dealOver)) {stayPressed=true; showScoreOK=true;}
if(arg=="Redeal") restart();
return true;
}
}