// ************************************************************************ // Blackjack is a console game that emulates the game of "Blackjack" aka "21" // in which the objective is to get a hand as close to (or equal to) 21. This // Java version of the game accomodates one player against the programmatic // dealer. This release of the game doesn't allow "doubling down." // // // Kelli Wiseth // 17-August-2004 // Platform: Wintel [Windows 2000] // JDK version: JDK 1.4.1 // //****************************************************************************** import java.io.*; import java.text.NumberFormat; import java.util.Random; class Blackjack { static final double MIN_BET=2.00; static final double MAX_BET=1000.00; static final double MAX_CHIPS=10000.00; static final double MIN_CHIPS=2.00; static final int MAX_CARDS=5; static final int SOFT_17=17; static final int HARD_17=17; static final int SOFT_18=18; //**************************************************************************** // The main method begins here. It's the driver for the rest of the program-- // it sets up variables, asks user to input a dollar amount to bet, and starts // a do-while loop that calls several other methods to validate the input // before the game actually begins. //**************************************************************************** public static void main (String args[]) throws IOException { String chip_amt="0"; String bet_amt="0"; String response=" "; double chips=0.0; double balance=0.0; double bet=0.0; double winnings=0.0; double total_winnings=0.0; String card_1, card_2, card_3, card_4, card_5, card_6, card_7, card_8, card_9, card_10; String newcard1="blank"; String newcard2="blank"; String newcard3="blank"; int card_1_val, card_2_val, card_3_val, card_4_val, card_5_val, card_6_val, card_7_val, card_8_val; int newcard1_val=0; int newcard2_val=0; int newcard3_val=0; int card_count_plr=0; int card_count_dlr=0; int player_hand=0; int dealer_hand=0; char alpha; boolean natural=false; boolean natural_plr=false; boolean natural_dlr=false; boolean Aceflag_plr=false; boolean Aceflag_dlr=false; boolean hand_over=false; boolean game_over=false; boolean five_card_charlie=false; boolean soft_11=true; BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); NumberFormat money = NumberFormat.getCurrencyInstance(); //object for formatting output //**************************************************************************** // Ask user to enter a dollar amount to gamble. Nested inside a do-while loop // that ensures valid input. //**************************************************************************** System.out.println("**************************************************"); System.out.println("* *"); System.out.println("* Welcome to the virtual Blackjack table! *"); System.out.println("* Buy some chips--up to $10,000--to get *"); System.out.println("* started. Then, minimum bet is $2.00, *"); System.out.println("* maximum bet is $1,000, per hand. Good luck! *"); System.out.println("* *"); System.out.println("**************************************************"); do { System.out.print("How many chips do you want to buy? "); System.out.flush(); chip_amt=stdin.readLine(); if (chip_amt.length()==0) System.out.println("Please enter a value between 2 and 10000." ); else { if (!validate(chip_amt)) System.out.println("Please enter a value between 2 and 10000. "); else { chips=Double.parseDouble(chip_amt); if ((chipsMAX_CHIPS)) { System.out.println("\nThe minimum amount of chips you can buy is " + money.format(MIN_CHIPS) + " and the maximum is " + money.format(MAX_CHIPS)); System.out.println("Please try again"); } else System.out.println("\nYou've purchased " + money.format(chips) + " to play with. Have fun!"); } }//closing brace for 'else' paired with if (!validate) above) }//closing brace for do-while loop while((chip_amt.length()==0) || (!validate(chip_amt)) || (chipsMAX_CHIPS)); balance=chips; do { //****************************************************************************************************** // At this point, we should have a valid chip-purchase amount, so we can set the beginning balance and // ask the player to place a bet. //****************************************************************************************************** do { System.out.print("\nPlease place your bet by entering an\namount from 2 dollars to 1000 dollars: "); System.out.flush(); bet_amt=stdin.readLine(); if (bet_amt.length()==0) //#1 System.out.println("Please enter a value between 2 and 1000." ); else //#1-else { if (validate(bet_amt)) { bet=Double.parseDouble(bet_amt); if ((bet>balance) || (betMAX_BET)) { System.out.println("\nThe minimum bet is " + money.format(MIN_BET) + "; maximum bet is " + money.format(MAX_BET) + "\nand your available balance is " + money.format(balance)); System.out.println("Please try again"); } else { //debug System.out.println("\nvalue of bet_amt.charAt(0) is " + bet_amt.charAt(0)); //debug System.out.println("I'm ready to exit the loop and the amount of bet is " + bet_amt); System.out.println("\n\nYour bet is " + money.format(bet) + ". Time to deal. "); } } } //closing brace for #1-else }//closing brace for 'do' above while((bet_amt.length()==0) || (!validate(bet_amt)) || (bet>balance) || (betMAX_BET)); //****************************************************************************************************** //At this point, we should have a valid bet, and we can deal the cards. //****************************************************************************************************** System.out.println("\t\t\t\t\tPlayer\t\tHouse"); System.out.println("\t\t\t\t\t*******\t\t********"); //One card to player, one card to dealer, face up card_1=deal(); card_2=deal(); // card_1="A"; // debug // card_2="A"; //debug card_1_val=evaluateCards(card_1); card_2_val=evaluateCards(card_2); System.out.println("\t\t\t\t\t" + card_1 +"\t\t" + card_2); // Second card to player, second card to dealer (dealer's is face down) card_3=deal(); card_4=deal(); // card_3="A"; //debug // card_4="A"; //debug card_3_val=evaluateCards(card_3); card_4_val=evaluateCards(card_4); System.out.println("\t\t\t\t\t" + card_3+ "\t\t?"); //************************************************************** // Both player and dealer now have two cards in their hands. //************************************************************** card_count_plr=2; card_count_dlr=2; //**************************************************************************************************** // Let's see if any of the four cards is an Ace, and if so, let's set a flag which we'll use later. //**************************************************************************************************** if ((card_1.charAt(0)=='A') || (card_3.charAt(0)=='A')) Aceflag_plr=true; if ((card_2.charAt(0)=='A') || (card_4.charAt(0)=='A')) Aceflag_dlr=true; //debug System.out.println("here's what card 1 looks like " + card_1); //debug //debug System.out.println("the player's aceflag is " + Aceflag_plr); //debug //debug System.out.println("the dealer's aceflag is " + Aceflag_dlr); //debug //debug System.out.println("here's what card 3 looks like " + card_3); //debug //************************************************************************** // Let's get the value of all four cards and just hold it here temporarily. //************************************************************************** player_hand=card_1_val + card_3_val; dealer_hand=card_2_val + card_4_val; //debug System.out.println("player hand is " + player_hand); //debug System.out.println("dealer hand here is " + dealer_hand); //***************************************************************************** //Let's first check to see if the player has a natural blackjack by passing in //the player's two cards to the naturalBlackjack method. //***************************************************************************** if (naturalBlackjack(card_1, card_3)) { natural_plr=true; System.out.println("You have a natural Blackjack!"); System.out.println("Unless the dealer also has a blackjack, you will have won."); System.out.println("We'll see in a second..."); } else //if it's not a natural blackjack, let's ask the user to hit or stay { do { System.out.print("Do you want to [h]it or [s]tay? "); System.out.flush(); response=stdin.readLine(); alpha=alphaCheck(response); //debug System.out.println("response is " + response); //debug System.out.println("alphaCheckresponse is " + alphaCheck(response)); //debug System.out.println("alpha is " + alpha); //************************************************************************************************** // Player hits and the cards are evaluated. Player hits until he or she decides to stay, or busts. // We use a card counter to keep track of the number of cards dealt. Depending on whether the Aceflag // is true or not, we pass the cards to an evaluateHand method. There are four different signatures // for the evaluateHand method() to support the different number of cards possible in a hand. //************************************************************************************************** if ((alpha=='H') && (card_count_plr<=MAX_CARDS)) { if (card_count_plr<=2) { newcard1=deal(); card_count_plr++; newcard1_val=evaluateCards(newcard1); //this value may change in the evaluateHand() method System.out.println("\t\t\t\t\t" + newcard1); if (newcard1.charAt(0)=='A') Aceflag_plr=true; if (!Aceflag_plr) player_hand += newcard1_val; else player_hand =(evaluateHand(card_1_val, card_3_val, newcard1_val)); } else if (card_count_plr==3) { newcard2=deal(); card_count_plr++; newcard2_val=evaluateCards(newcard2); //this value may change in the evaluateHand() method System.out.println("\t\t\t\t\t" + newcard2); if (newcard2.charAt(0)=='A') Aceflag_plr=true; if (!Aceflag_plr) player_hand += newcard2_val; else player_hand =(evaluateHand(card_1_val, card_3_val, newcard1_val, newcard2_val)); } else if (card_count_plr==4) { newcard3=deal(); card_count_plr++; newcard3_val=evaluateCards(newcard3); //this value may change in the evaluateHand() method System.out.println("\t\t\t\t\t" + newcard3); if (newcard3.charAt(0)=='A') Aceflag_plr=true; if (!Aceflag_plr) player_hand += newcard3_val; else player_hand =(evaluateHand(card_1_val, card_3_val, newcard1_val, newcard2_val, newcard3_val)); } //debug System.out.println("player hand at this point is " + player_hand); //debug //debug System.out.println("dealer hand here is " + dealer_hand); //debug //debug System.out.println("balance at this point is " + balance); //debug //debug System.out.println("player's cards dealt at this point is " + card_count_plr); //debug //debug System.out.println("dealer's cards dealt at this point is " + card_count_dlr); //debug if ((card_count_plr==5) && (player_hand<=21)) { System.out.println("You've reached the five-card limit."); five_card_charlie=true; alpha='S'; } }//closing brace for 'if' alpha== H } //brace for 'do' above while ((alpha=='H') && (player_hand<=21) && (card_count_plr<=MAX_CARDS)); //********************************************************************************************** // Player stays and the game turns over to the dealer's portion. Here we reveal the dealer's // face-down card and then hit or stay according to the rules of the game. //********************************************************************************************* if ((alpha=='S') || ((card_count_plr==MAX_CARDS) && player_hand<=21)) { // #S1 System.out.println("Player is staying on a hand of " + player_hand); System.out.println("----------------------------------------------"); System.out.println(); System.out.println("\nNow it's the dealer's turn..."); System.out.println("First, let's turn the dealer's second card face up: \t" + card_4); System.out.println(); if ((card_2_val+card_4_val)>21) //both cards must be Aces, change one card to value of 1 card_2_val=1; dealer_hand=card_2_val+card_4_val; //************************************************************************* //Let's just check to see if the dealer has a natural blackjack by passing in //the dealer's two cards to the naturalBlackjack method. //************************************************************************* if (naturalBlackjack(card_2, card_4)) { System.out.println("The dealer has a natural Blackjack! "); natural_dlr=true; } else { // if ((card_2_val+card_4_val)<=21)) // dealer_hand=(evaluateHand(card_2_val, card_4_val)); //******************************************************************************* // Dealer must hit based on certain rules. We have to concern ourselves with the // value of the Ace (Soft, hard) only if the dealer has an Ace. //******************************************************************************* do { //debug System.out.println("we're in the do loop now "); //debug System.out.print("The dealer's hand adds up to " + dealer_hand + ",\nso the dealer must "); if (((Aceflag_dlr) && (dealer_hand<=17)) || ((!Aceflag_dlr) && (dealer_hand<=16))) { if ((card_count_dlr==2)) { System.out.print("hit.\n"); System.out.println(); newcard1=deal(); newcard1_val=evaluateCards(newcard1); //this value may change in the evaluateHand() method card_count_dlr++; System.out.println("Dealer's next card is ...\t\t\t\t" + newcard1); System.out.println(); if (newcard1.charAt(0)=='A') Aceflag_dlr=true; if (!Aceflag_dlr) dealer_hand += newcard1_val; else { dealer_hand =(evaluateHand(card_2_val, card_4_val, newcard1_val)); Aceflag_dlr=false; } } else if (card_count_dlr==3) { System.out.print("hit.\n"); System.out.println(); newcard2=deal(); newcard2_val=evaluateCards(newcard2); //this value may change in the evaluateHand() method card_count_dlr++; System.out.println("Dealer's next card is ...\t\t\t\t" + newcard2); System.out.println(); if (newcard2.charAt(0)=='A') Aceflag_dlr=true; soft_11=true; if (!Aceflag_dlr) dealer_hand += newcard2_val; else dealer_hand =(evaluateHand(card_2_val, card_4_val, newcard1_val, newcard2_val)); } else if (card_count_dlr==4) { System.out.print("hit.\n"); System.out.println(); newcard3=deal(); newcard3_val=evaluateCards(newcard3); //this value may change in the evaluateHand() method card_count_dlr++; System.out.println("The dealer's next card is ...\t\t\t\t" + newcard3); System.out.println(); if (newcard3.charAt(0)=='A') Aceflag_dlr=true; if (!Aceflag_dlr) dealer_hand += newcard3_val; else dealer_hand =(evaluateHand(card_2_val, card_4_val, newcard1_val, newcard2_val, newcard3_val)); } } //closing brace for if nested inside do-while loop else System.out.print("stand with a hand valued at " + dealer_hand + ". \n"); // System.out.println("inside do-while logic for dealer"); //debug // System.out.println("dealer hand here is " + dealer_hand); //debug // System.out.println("balance at this point is " + balance); //debug // System.out.println("player's cards dealt at this point is " + card_count_plr); //debug // System.out.println("dealer's cards dealt at this point is " + card_count_dlr); //debug } while((dealer_hand<=16) && (!Aceflag_dlr) || (dealer_hand<=17) && (Aceflag_dlr)); } //closing brace for 'else' above System.out.print("The dealer's hand adds up to " + dealer_hand + ",\nso the dealer "); if (dealer_hand>21) System.out.print("has busted.\n"); else System.out.print("must stand.\n"); } //closing brace for "if alpha==S" statement #S1 above }//closing brace //for major 'else' that begins above the do-loop for the 'hit or stay' prompt //************************************************************************************************* // GAME OVER. Let's see who won, whether it's a push, and so on, and calculate winnings. // // //************************************************************************************************* if ((natural_plr) && (!natural_dlr)) { System.out.println("You have a natural Blackjack and the dealer doesn't, so you've won this hand."); balance += ((bet*1.5)+bet); } else if (((natural_plr) && (natural_dlr)) || (player_hand==dealer_hand)) { System.out.println("This is a push: Your hand is " + player_hand + ",\nand the dealer's hand is " + dealer_hand); System.out.println("You don't lose your bet, but you don't win any moola either."); balance=balance; } else if ((player_handdealer_hand) && (player_hand<=21)) { System.out.println("You've beaten the dealer!"); System.out.println("Dealer's hand is " + dealer_hand + ", while your hand is " + player_hand); balance+=bet; } else if ((dealer_hand>21) && (player_hand<=21)) { System.out.println("The house has busted with a hand of " + dealer_hand); balance+=bet; } else if (player_hand>21) { System.out.println("Sorry, you've busted with a hand of " + player_hand); System.out.println("And it doesn't matter what the dealer has,\nbut just fyi, the dealer has " + dealer_hand); balance-=bet; } System.out.println("\nYour balance of chips is " + money.format(balance)); System.out.println("---------------------------------------------------------------"); System.out.print("Do you want to play again? [y]es or [n]o? "); System.out.flush(); response=stdin.readLine(); alpha=alphaCheck(response); if (alpha=='N') { System.out.println("Thanks for playing Blackjack!"); System.out.println("Your closing balance of chips is " + money.format(balance)); System.out.println("Come back and play again sometime."); game_over=true; } if ((alpha=='Y') && (balance>=2)) { //#Y-1 game_over=false; Aceflag_dlr=false; Aceflag_plr=false; natural_plr=false; natural_dlr=false; five_card_charlie=false; } } while (!game_over); }//main method closing brace //******************************************************************************** // AUXILIARY METHODS BELOW THIS POINT // //******************************************************************************** //************************************************************************* // The validate() method evaluates input for valid numeric content. It // checks for multiple decimal points, leading 0 or -. Any non-numeric input // is rejected. //************************************************************************* static boolean validate(String input) { int max=input.length(); int valid_input_cntr=max; char digit; int counter=0; int counter2=0; int valid_digit_cntr=0; int dec_pnt_cntr=0; //Loop through the input string and find valid and invalid character conditions for (counter=0; counter='0') && (digit<='9')) { valid_digit_cntr=max; //debug System.out.println("digit is " + digit); //debug System.out.println("phase I valid entry test passed and valid digit counter = " + valid_digit_cntr); } else if (digit=='.') { //#3 dec_pnt_cntr++; if (dec_pnt_cntr>1) { valid_input_cntr--; //debug System.out.println("\nYou've got too many decimal points in your entry. "); } } //#3 else { //debug System.out.println("\nYou've got some kind of garbage in your input. Please try again. "); valid_input_cntr--; } }//for-loop closing brace //debug System.out.println("\nI'm leaving this validate method and the value of the valid counter is " + valid_input_cntr); //debug System.out.println("I'm leaving this validate method and the value of max is " + max); //debug System.out.println("which means the return value will be " + (valid_input_cntr==max)); return(valid_input_cntr==max); } //validate method closing brace //************************************************************************ // The alphaCheck() method evaluates input during the course of the game, and // ensures that menu selections will be made correctly. This is basically // a setup routine for handling responses. //************************************************************************ static char alphaCheck(String input) { char clean_char=' '; if (input.length()==0) System.out.println("Please enter a response. "); else if ((input.charAt(0)=='h') || (input.charAt(0)=='H')) clean_char='H'; else if ((input.charAt(0)=='s') || (input.charAt(0)=='S')) clean_char='S'; else if ((input.charAt(0)=='b') || (input.charAt(0)=='B')) clean_char='B'; else if ((input.charAt(0)=='q') || (input.charAt(0)=='Q')) clean_char='Q'; else if ((input.charAt(0)=='y') || (input.charAt(0)=='Y')) clean_char='Y'; else if ((input.charAt(0)=='n') || (input.charAt(0)=='N')) clean_char='N'; return clean_char; }//alphaCheck method closing brace //************************************************************************** // The deal() method uses the Random() class to generate cards. // The numbers generate so fast that they're often all the same, so the // method includes a "dummy delay." Experimentation led to the value used. //************************************************************************* static String deal() { int cardnum = 0; String cardface="blank"; for (int i=0; i<=100000000; i++); //A dummy loop to ensure better seed data (systemtime) 'random-ness' Random gen_card = new Random(); cardnum=(((Math.abs(gen_card.nextInt()%13))+1)); if (cardnum==13) cardface="K"; else if (cardnum==12) cardface="Q"; else if (cardnum==11) cardface="J"; else if (cardnum==1) cardface="A"; // else // cardface=((char)(cardnum)); // This didn't work (and won't work) because integers are signed, chars are not, and so // the characters that get displayed using this approach are not correct. else if (cardnum==2) cardface="2"; else if (cardnum==3) cardface="3"; else if (cardnum==4) cardface="4"; else if (cardnum==5) cardface="5"; else if (cardnum==6) cardface="6"; else if (cardnum==7) cardface="7"; else if (cardnum==8) cardface="8"; else if (cardnum==9) cardface="9"; else if (cardnum==10) cardface="10"; return cardface; } //method deal() closing brace //************************************************************************* // The naturalBlackjack() method takes two inputs--the first two cards of the player's // hand--and evaluates whether the player has a natural blackjack. // //************************************************************************* static boolean naturalBlackjack(String card1, String card2) { boolean natural=false; if (((card1.charAt(0)=='A') || (card2.charAt(0)=='A')) && ((card1.charAt(0)=='K') || (card1.charAt(0)=='Q') || (card1.charAt(0)=='J') || (card1.charAt(0)=='1') || (card1.charAt(0)=='A')) && ((card2.charAt(0)=='K') || (card2.charAt(0)=='Q') || (card2.charAt(0)=='J') || (card2.charAt(0)=='1') || (card2.charAt(0)=='A')) && (card1.charAt(0)!=card2.charAt(0))) { natural=true; //debug System.out.println("A natural blackjack is 21 on the first two cards."); } else { natural=false; //debug System.out.println("not a natural blackjack"); } return natural; } //closing brace //************************************************************************ // The evaluateCards() method evaluates a single card after it's dealt. // By default, we'll give the Ace a value of 11 to get // started, and we'll fiddle with its value later on, in another routine. //************************************************************************ static int evaluateCards(String card) { int card_value=0; if ((card.charAt(0)=='K') || (card.charAt(0)=='Q') || (card.charAt(0)=='J') || (card.charAt(0)=='1')) card_value=10; else if (card.charAt(0)>='2' && card.charAt(0)<='9') card_value=Integer.parseInt(card); else if (card.charAt(0)=='A') card_value=11; // System.out.println("one-input method card face is " + card + " and card value that will be returned is " + card_value); //debug return card_value; }//closing brace //************************************************************************* // This evaluateHand() method takes two inputs--the first two cards dealt--and // recalculates the value based on hard 11. //************************************************************************* static int evaluateHand(int card1_val, int card2_val) { int hand_value=0; // System.out.println("the incoming value of the two cards is:\n" + card1_val + " " + card2_val); //debug // System.out.println("These add up to " + (card1_val+card2_val)); /debug if ((card1_val + card2_val)<=16) { if (card2_val==11) { card1_val=1; // System.out.println("inside the first nested if"); //debug // System.out.println("card1_val is " + card1_val); //debug } if (card2_val==11) { card2_val=1; // System.out.println("inside the second nested if"); //debug // System.out.println("card1_val is " + card2_val); //debug } hand_value=card1_val + card2_val; } else //otherwise leave the ace valued at 11 //debug System.out.println("inside the else"); hand_value = card1_val + card2_val; //debug System.out.println("two inputs to re-evaluate the Ace when necessary. "); //debug System.out.println("the value of this hand is " + hand_value); return hand_value; } //closing brace //************************************************************************* // This evaluateHand() method takes three inputs--the first two cards dealt // and a third card after the first hit. //************************************************************************* static int evaluateHand(int card1_val, int card2_val, int card3_val) { int hand_value=0; // System.out.println("the incoming value of the three cards is:\n" + card1_val + " " + card2_val + " " + card3_val); // System.out.println("These add up to " + (card1_val+card2_val+card3_val)); if ((card1_val + card2_val + card3_val)>21) { if (card1_val==11) card1_val=1; if (card2_val==11) card2_val=1; if (card3_val==11) card3_val=1; hand_value=card1_val + card2_val + card3_val; } else //otherwise leave the ace valued at 11 hand_value = card1_val + card2_val + card3_val; //debug System.out.println("three-inputs to re-evaluate the Ace when necessary. "); //debug System.out.println("the value of this hand is " + hand_value); return hand_value; } //closing brace //************************************************************************* // This evaluateHand() method takes four cards as input. //************************************************************************* static int evaluateHand(int card1_val, int card2_val, int card3_val, int card4_val) { int hand_value=0; // System.out.println("the incoming value of the four cards is:\n" + card1_val + " " + card2_val + " " + card3_val + " " + card4_val); // System.out.println("These add up to " + (card1_val+card2_val+card3_val+card4_val)); if ((card1_val + card2_val + card3_val + card4_val)>21) { if (card1_val==11) card1_val=1; if (card2_val==11) card2_val=1; if (card3_val==11) card3_val=1; if (card4_val==11) card4_val=1; hand_value=card1_val + card2_val + card3_val + card4_val; } else //otherwise leave the ace valued at 11 hand_value = card1_val + card2_val + card3_val + card4_val; //debug System.out.println("four inputs to re-evaluate the Ace when necessary. "); //debug System.out.println("the value of this hand is " + hand_value); return hand_value; } //closing brace //************************************************************************* // This evaluateHand() method takes five cards as input. //************************************************************************* static int evaluateHand(int card1_val, int card2_val, int card3_val, int card4_val, int card5_val) { int hand_value=0; // System.out.println("the incoming value of the five cards is:\n" + card1_val + " " + card2_val + " " + card3_val + " " + card4_val + " " + card5_val); // System.out.println("These add up to " + (card1_val+card2_val+card3_val+card4_val+card5_val)); if ((card1_val + card2_val + card3_val + card4_val + card5_val)>21) { if (card1_val==11) card1_val=1; if (card2_val==11) card2_val=1; if (card3_val==11) card3_val=1; if (card4_val==11) card4_val=1; if (card5_val==11) card5_val=1; hand_value=card1_val + card2_val + card3_val+ card4_val + card5_val; } else //otherwise leave the ace valued at 11 hand_value = card1_val + card2_val + card3_val + card4_val + card5_val; //debug System.out.println("five inputs to re-evaluate the Ace when necessary. "); //debug System.out.println("the value of this hand is " + hand_value); return hand_value; } //closing brace }//Blackjack class