/* BLACKJACK: Author: David Henke, converted to Java */ import java.io.*; import java.applet.*; import java.util.*; import java.awt.*; class C { final static int ERROR = -1; final static int NORMAL = 0; final static int MAX_HANDS_SIM = 1000000000; final static int WORDSIZE = 32; final static int MAX_STRING = 16; final static int NUM_COUNTS = 22; final static int NUM_CARDS = 52; final static int NUM_SUITS = 4; final static int NUM_DENOMINATIONS = 13; final static int CLUB = 0; final static int DIAMOND = 1; final static int HEART = 2; final static int SPADE = 3; final static int MAX_CLUB = 12; final static int MAX_DIAMOND = 25; final static int MAX_HEART = 38; final static int MAX_SPADE = 51; final static int DISPLAY_DOWN = 0; final static int DISPLAY_UP = 1; final static int MAX_CARDS_IN_HAND = 12; final static int MIN_TEN_COUNT = 10; final static int MAX_CARDS_PLAYED = 44; final static int MAX_HANDS = 4; final static int TWENTY_ONE = 21; final static int SEVENTEEN = 17; final static int ACES_TEN = 10; final static int SHOW_DOWN_INDEX = 13; final static int FIRST = 0; final static int SECOND = 1; final static int ACE = 0; final static int TWO = 1; final static int THREE = 2; final static int FOUR = 3; final static int FIVE = 4; final static int SIX = 5; final static int SEVEN = 6; final static int EIGHT = 7; final static int NINE = 8; final static int TEN = 9; final static int JACK = 10; final static int QUEEN = 11; final static int KING = 12; // globals for play control static boolean debug = false; static boolean check_rules; static boolean interactive; static boolean double_all; static int num_hands; // globals for display final static String denom_array[] = { " A", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9", "10", " J", " Q", " K", "XX" }; }; class rules { // tables for rules to play by static boolean split_table[][] = { // A 2 3 4 5 6 7 8 9 10 J Q K Dealer hole card // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, A always split {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, 2 split 4-7 {false, false, false, true, true, true, true, false, false, false, false, false, false}, // {0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, 3 split 4-7 {false, false, false, true, true, true, true, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4 never split {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5 never split {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, 6 split 3-6 {false, false, true, true, true, true, false, false, false, false, false, false, false}, // {0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, 7 split 2-7 {false, true, true, true, true, true, true, false, false, false, false, false, false}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 8 always split {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0}, 9 split 2-6, 8-9 {false, true, true, true, true, true, false, true, true, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10 never split {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, J never split {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Q never split {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, K never split {false, false, false, false, false, false, false, false, false, false, false, false, false}, }; static boolean hard_double_table[][] = { // A 2 3 4 5 6 7 8 9 10 J Q K Dealer hole card // two card count, no ace // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0 never 0 {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1 never 1 {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, 9 double down 3-6 {false, false, true, true, true, true, false, false, false, false, false, false, false}, // {0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, 10 double down 2-9 {false, true, true, true, true, true, true, true, true, false, false, false, false}, // {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 11 double down 2-10 {false, true, true, true, true, true, true, true, true, true, true, true, true}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21 never double down {false, false, false, false, false, false, false, false, false, false, false, false, false}, }; static boolean soft_double_table[][] = { // A 2 3 4 5 6 7 8 9 10 J Q K Dealer hole card // two card count, one is ace // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, 13 double down 5-6 {false, false, false, false, true, true, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, 14 double down 5-6 {false, false, false, false, true, true, false, false, false, false, false, false, false}, // {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, 15 double down 4-6 {false, false, false, true, true, true, false, false, false, false, false, false, false}, // {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, 16 double down 4-6 {false, false, false, true, true, true, false, false, false, false, false, false, false}, // {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, 17 double down 2-6 {false, true, true, true, true, true, false, false, false, false, false, false, false}, // {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, 18 double down 4-6 {false, false, false, true, true, true, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21 never {false, false, false, false, false, false, false, false, false, false, false, false, false}, }; static boolean hard_hit_table[][] = { // A 2 3 4 5 6 7 8 9 10 J Q K Dealer hole card // card count, no ace // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 0 never happens {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1 never happens {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 2 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 3 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 4 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 5 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 6 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 7 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 8 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 9 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 10 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 11 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1}, 12 hit all but 4-6 {true, true, true, false, false, false, true, true, true, true, true, true, true}, // {1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1}, 13 hit all but 2-6 {true, false, false, false, false, false, false, true, true, true, true, true, true, true}, // {1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1}, 14 hit all but 2-6 {true, false, false, false, false, false, false, true, true, true, true, true, true, true}, // {1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1}, 15 hit all but 2-6 {true, false, false, false, false, false, false, true, true, true, true, true, true, true}, // {1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1}, 16 hit all but 2-6 {true, false, false, false, false, false, false, true, true, true, true, true, true, true}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17 never hit {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18 never hit {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19 never hit {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20 never hit {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21 never hit {false, false, false, false, false, false, false, false, false, false, false, false, false}, }; static boolean soft_hit_table[][] = { // A 2 3 4 5 6 7 8 9 10 J Q K Dealer hole card // two card count, soft ace // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 0 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 2 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 3 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 4 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 5 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 6 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 7 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 8 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 9 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 10 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 11 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 12 nop {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 13 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 14 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 15 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 16 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 17 always hit {true, true, true, true, true, true, true, true, true, true, true, true, true}, // {1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}, 18 hit all but 2-8 {true, false, false, false, false, false, false, false, true, true, true, true, true}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19 never hit {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20 never hit {false, false, false, false, false, false, false, false, false, false, false, false, false}, // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21 never hit {false, false, false, false, false, false, false, false, false, false, false, false, false}, }; } /* end of constant rules declarations */ class card { public int denomination; public int suit; public int count; public card(int the_denomination, int the_suit, int the_count) { denomination = the_denomination; suit = the_suit; count = the_count; } public int display() { return(C.NORMAL); } }; class default_deck { public static card ddeck[] = { new card(C.ACE, C.CLUB, 1), new card(C.TWO, C.CLUB, 2), new card(C.THREE, C.CLUB, 3), new card(C.FOUR, C.CLUB, 4), new card(C.FIVE, C.CLUB, 5), new card(C.SIX, C.CLUB, 6), new card(C.SEVEN, C.CLUB, 7), new card(C.EIGHT, C.CLUB, 8), new card(C.NINE, C.CLUB, 9), new card(C.TEN, C.CLUB, 10), new card(C.JACK, C.CLUB, 10), new card(C.QUEEN, C.CLUB, 10), new card(C.KING, C.CLUB, 10), new card(C.ACE, C.DIAMOND, 1), new card(C.TWO, C.DIAMOND, 2), new card(C.THREE, C.DIAMOND, 3), new card(C.FOUR, C.DIAMOND, 4), new card(C.FIVE, C.DIAMOND, 5), new card(C.SIX, C.DIAMOND, 6), new card(C.SEVEN, C.DIAMOND, 7), new card(C.EIGHT, C.DIAMOND, 8), new card(C.NINE, C.DIAMOND, 9), new card(C.TEN, C.DIAMOND, 10), new card(C.JACK, C.DIAMOND, 10), new card(C.QUEEN, C.DIAMOND, 10), new card(C.KING, C.DIAMOND, 10), new card(C.ACE, C.HEART, 1), new card(C.TWO, C.HEART, 2), new card(C.THREE, C.HEART, 3), new card(C.FOUR, C.HEART, 4), new card(C.FIVE, C.HEART, 5), new card(C.SIX, C.HEART, 6), new card(C.SEVEN, C.HEART, 7), new card(C.EIGHT, C.HEART, 8), new card(C.NINE, C.HEART, 9), new card(C.TEN, C.HEART, 10), new card(C.JACK, C.HEART, 10), new card(C.QUEEN, C.HEART, 10), new card(C.KING, C.HEART, 10), new card(C.ACE, C.SPADE, 1), new card(C.TWO, C.SPADE, 2), new card(C.THREE, C.SPADE, 3), new card(C.FOUR, C.SPADE, 4), new card(C.FIVE, C.SPADE, 5), new card(C.SIX, C.SPADE, 6), new card(C.SEVEN, C.SPADE, 7), new card(C.EIGHT, C.SPADE, 8), new card(C.NINE, C.SPADE, 9), new card(C.TEN, C.SPADE, 10), new card(C.JACK, C.SPADE, 10), new card(C.QUEEN, C.SPADE, 10), new card(C.KING, C.SPADE, 10) }; }; class deck { private int card_indices[] = new int[C.NUM_CARDS]; public int deck_count; public deck() { for (int i = 0; i < C.NUM_CARDS; i++) { card_indices[i] = i; } } public void dump() { for (int i = 0; i < C.NUM_CARDS; i++) { System.out.println("deck[" + i + "]:" + card_indices[i]); } } public void shuffle() { int card_count; int card_num; int temp; /* generate a random number U, uniformly distributed between 0 and 1 */ Random randomObject = new Random(); for (card_count = C.NUM_CARDS - 1; card_count > 0; card_count--) { /* get card_num to lie between 0 and 51 */ card_num = (int) (card_count * randomObject.nextDouble()); /* exchange card_indices[card_num] with card_indices[card_count] */ temp = card_indices[card_num]; card_indices[card_num] = card_indices[card_count]; card_indices[card_count] = temp; } deck_count = -1; } public int deal_card() { deck_count++; if (deck_count >= C.NUM_CARDS) { // shuffle dead cards and finish this game // for now, recycle cards at beginning of deck to finish this hand if (C.debug) { System.out.println("No more cards in this deck, recycling."); } return(card_indices[deck_count % C.NUM_CARDS]); } return(card_indices[deck_count]); } }; abstract class hand { public boolean show_total; public boolean aces; public boolean hard_ace; public boolean over; public boolean play; public int hand_count; public int card_indices[] = new int[C.MAX_CARDS_IN_HAND]; public int card_count; public void initialize() { show_total = false; card_count = 0; play = true; over = false; } public boolean blackjack() { if (default_deck.ddeck[card_indices[C.FIRST]].denomination == C.ACE) { if (default_deck.ddeck[card_indices[C.SECOND]].count == 10) { return(true); } } else if (default_deck.ddeck[card_indices[C.SECOND]].denomination == C.ACE) { if (default_deck.ddeck[card_indices[C.FIRST]].count == 10) { return(true); } } return(false); } public int count() { boolean hard_ace_ok = true; aces = false; hard_ace = false; hand_count = 0; for (int i = 0; i < card_count; i++) { hand_count += default_deck.ddeck[card_indices[i]].count; if (default_deck.ddeck[card_indices[i]].denomination == C.ACE) { aces = true; } if (aces && !hard_ace && hard_ace_ok) { if ((hand_count + C.ACES_TEN) <= C.TWENTY_ONE) { hand_count += C.ACES_TEN; hard_ace = true; } } if ((hand_count > C.TWENTY_ONE) && hard_ace) { hand_count -= C.ACES_TEN; hard_ace = false; // no more hard aces hard_ace_ok = false; } } // test for over and return the count if (hand_count > C.TWENTY_ONE) { over = true; } return(hand_count); } public void deal_card(int new_card) { card_indices[card_count] = new_card; card_count++; } public abstract void display(); }; class dealer_hand extends hand { public boolean first_card_down; public void initialize() { super.initialize(); first_card_down = true; } public boolean insurance() { if (default_deck.ddeck[card_indices[C.SECOND]].denomination == C.ACE) { System.out.print("\n" + "Insurance?(Y/N)"); System.out.flush(); return(interact.get_answer()); } else { return(false); } } public void display() { int index; System.out.print("\n" + "Dealers hand: "); System.out.flush(); for (int i = 0; i < card_count; i++) { if ((first_card_down == true) && (i == 0)) { index = C.SHOW_DOWN_INDEX; } else { index = default_deck.ddeck[card_indices[i]].denomination; } System.out.print(" " + C.denom_array[index]); } System.out.flush(); if (show_total == true) { System.out.println(" total: " + count()); } } }; class player_hand extends hand { public boolean got_insurance; public boolean split_aces; public float bet; public float insure; public void initialize() { super.initialize(); got_insurance = false; split_aces = false; } public boolean split(int dealer_up_card) { if (default_deck.ddeck[card_indices[C.FIRST]].denomination == default_deck.ddeck[card_indices[C.SECOND]].denomination) { if (C.interactive) { System.out.print("\n" + "Split?(Y/N)"); System.out.flush(); boolean answer = interact.get_answer(); if (C.check_rules) { boolean rule_answer = rules.split_table [default_deck.ddeck[card_indices[C.FIRST]].denomination] [dealer_up_card]; if (answer != rule_answer) { interact.print_rule_violated(); } } return(answer); } else { return(rules.split_table [default_deck.ddeck[card_indices[C.FIRST]].denomination] [dealer_up_card]); } } else { return(false); } } public boolean double_down(int dealer_up_card) { int card1_plus_card2; boolean can_ask = false; if (C.double_all) { can_ask = true; } else { card1_plus_card2 = default_deck.ddeck[card_indices[C.FIRST]].count + default_deck.ddeck[card_indices[C.SECOND]].count; if ((card1_plus_card2 == 10) || (card1_plus_card2 == 11)) { can_ask = true; } } if (can_ask) { if (C.interactive) { System.out.print("\n" + "Double Down?(Y/N)"); System.out.flush(); boolean answer = interact.get_answer(); if (C.check_rules) { boolean rule_answer; if (aces && hard_ace) { // means hand has an ace which could be softened rule_answer = rules.soft_double_table[hand_count] [dealer_up_card]; } else { rule_answer = rules.hard_double_table[hand_count] [dealer_up_card]; } if (answer != rule_answer) { interact.print_rule_violated(); } } return(answer); } else { if (aces && hard_ace) { // means hand has an ace which could be softened return(rules.soft_double_table[hand_count][dealer_up_card]); } else { return(rules.hard_double_table[hand_count][dealer_up_card]); } } } else { return(false); } } public void display() { int index; System.out.print("\n" + " Your hand: "); System.out.flush(); for (int i = 0; i < card_count; i++) { index = default_deck.ddeck[card_indices[i]].denomination; System.out.print(" " + C.denom_array[index]); } System.out.flush(); if (show_total == true) { System.out.println(" total: " + count()); } } }; // Interactive routines ....... class interact { static boolean get_answer() { String your_answer; char ch; boolean answer = false; boolean ok_answer; ok_answer = false; while (ok_answer == false) { your_answer = getString(); ch = your_answer.charAt(0); if ((ch == 'y') || (ch == 'Y')) { answer = true; ok_answer = true; } else if ((ch == 'n') || (ch == 'N')) { answer = false; ok_answer = true; } else { System.out.print("\n" + "Make up your mind!(Y/N)"); System.out.flush(); } } return(answer); } static void print_rule_violated() { System.out.println( "\n" + "CHECK: MIKEY SAYS YOU BROKE THE RULE."); } static void print_usage() { System.out.println("usage: bj -i|-b numhands [-c] [-d]"); System.out.println("usage: -i ==> interactive"); System.out.println("usage: -b ==> batch; numhands ==> number of hands to play"); System.out.println("usage: -c ==> optional check against playing rules"); System.out.println("usage: -d ==> option to allow double down for any combo"); } static int check_inputs(String args[]) { C.check_rules = false; C.double_all = false; int argc = args.length; if ((argc == 0) || (argc > 4)) { return(C.ERROR); } else { if (args[0].compareTo("-i") == 0) { // interactive C.interactive = true; if (argc > 3) { return(C.ERROR); } else if ((argc == 2) || (argc == 3)) { if (args[1].compareTo("-c") == 0) { C.check_rules = true; } else if (args[1].compareTo("-d") == 0) { C.double_all = true; } else { return(C.ERROR); } } if (argc == 3) { if (args[2].compareTo("-c") == 0) { C.check_rules = true; } else if (args[2].compareTo("-d") == 0) { C.double_all = true; } else { return(C.ERROR); } } } else if (args[0].compareTo("-b") == 0) { /* batch job */ C.interactive = false; if (argc == 1) { return(C.ERROR); } // get the number of hands to play if ((args[1].compareTo("-c") == 0) || (args[1].compareTo("-d") == 0)) { // expecting num_hands return(C.ERROR); } C.num_hands = Integer.parseInt(args[1]); if ((C.num_hands < 1) || (C.num_hands > C.MAX_HANDS_SIM)) { return(C.ERROR); } if (argc > 4) { return(C.ERROR); } else if ((argc == 3) || (argc == 4)) { if (args[2].compareTo("-c") == 0) { C.check_rules = true; } else if (args[2].compareTo("-d") == 0) { C.double_all = true; } else { return(C.ERROR); } } if (argc == 4) { if (args[3].compareTo("-c") == 0) { C.check_rules = true; } else if (args[3].compareTo("-d") == 0) { C.double_all = true; } else { return(C.ERROR); } } } else { return(C.ERROR); } } return(C.NORMAL); } static String getString() { char mystring[] = new char[80]; char ch; int i = 0; try { ch = (char) System.in.read(); while (ch != '\n') { mystring[i] = ch; ch = (char) System.in.read(); i++; } } catch (Exception e) { System.out.println ("Exception: IO char read"); System.exit(-1); } return(new String(mystring, 0, i)); } }; class play { // Playing routines .... static int deal(deck card_deck, hand this_hand) { int new_card; if ((new_card = card_deck.deal_card()) == C.ERROR) { return(C.ERROR); } this_hand.deal_card(new_card); return(C.NORMAL); } static void do_split(deck card_deck, player_hand hand1, player_hand hand2) { // reset the number of cards in split hand to 1 hand1.card_count = 1; hand1.count(); // initialize the new hand and take card from card 2 of split hand hand2.initialize(); hand2.card_indices[C.FIRST] = hand1.card_indices[C.SECOND]; hand2.card_count = 1; hand2.bet = hand1.bet; hand2.count(); // check for split of aces if (default_deck.ddeck[hand1.card_indices[C.FIRST]].denomination == C.ACE) { hand1.split_aces = true; hand2.split_aces = true; } // deal another card to each hand deal(card_deck, hand1); deal(card_deck, hand2); } }; class tally { // Tallying routines .... static float settle_score(float your_totals, player_hand your_hand, dealer_hand dealers_hand) { if (your_hand.over) { if (C.interactive) { System.out.println("\n" + "You busted!"); } your_totals -= your_hand.bet; } else if (dealers_hand.over) { if (C.interactive) { System.out.println("\n" + "Dealer busted!"); } your_totals += your_hand.bet; } else { if (your_hand.hand_count > dealers_hand.hand_count) { if (C.interactive) { System.out.println("\n" + "You win."); } your_totals += your_hand.bet; } else if (your_hand.hand_count < dealers_hand.hand_count) { if (C.interactive) { System.out.println("\n" + "You lose."); } your_totals -= your_hand.bet; } else { if (your_hand.hand_count == C.TWENTY_ONE) { if (your_hand.blackjack()) { if (dealers_hand.blackjack()) { if (C.interactive) { System.out.println("\n" + "Push."); } } else { if (C.interactive) { System.out.println("\n" + "You win."); } your_totals += your_hand.bet; } } else { /* both at 21, no blackjack */ if (C.interactive) { System.out.println("\n" + "Push."); } } } else { if (C.interactive) { System.out.println("\n" + "Push."); } } } } return(your_totals); } static void print_totals(float your_totals) { if (your_totals < 0) { System.out.println("\n" + "You owe me " + FormatMoney(your_totals * -1)); } else if (your_totals == 0) { System.out.println("\n" + "We are dead even." + "\n"); } else { System.out.println("\n" + "I owe you " + FormatMoney(your_totals)); } } private static String FormatMoney(float input) { /* a truly ridiculous routine for formatting money strings */ String money; long dollar_val; int cent_val; dollar_val = (long) Math.floor(input); cent_val = (int) ((input - dollar_val + .005) * 100); if (cent_val == 100) { dollar_val = dollar_val++; cent_val = 0; } if (cent_val >=10) { money = new String("$" + dollar_val + "." + cent_val); } else { money = new String("$" + dollar_val + ".0" + cent_val); } int length = money.length(); int uniform_length = 11; if (length < uniform_length) { /* pad with blanks */ int num_blanks = uniform_length - length; for (int i = 0; i < num_blanks; i++) { money = money.concat(" "); } } return(money); }; }; public class bj { public static void main(String args[]) { deck card_deck = new deck(); dealer_hand dealers_hand = new dealer_hand(); player_hand your_hand[] = new player_hand[C.MAX_HANDS]; int num_user_hands; int dealer_up_card; int hands_played; int i; float your_totals; Float float_bet; String string_bet; boolean answer; boolean rule_answer; for (i = 0; i < C.MAX_HANDS; i++) { your_hand[i] = new player_hand(); } System.out.println(" ******************** BLACKJACK ********************"); if (interact.check_inputs(args) == C.ERROR) { interact.print_usage(); System.exit(-1); } card_deck.shuffle(); your_totals = 0; hands_played = 0; // do until user terminates the game or for n hands in batch mode for (;;) { hands_played++; if (C.interactive) { System.out.println("\n" + "************ NEW GAME *****************"); System.out.print("\n" + "Enter your bet (0 or less ends the game):"); System.out.flush(); string_bet = interact.getString(); System.out.println(string_bet); float_bet = Float.valueOf(string_bet); your_hand[0].bet = float_bet.floatValue(); if (your_hand[0].bet <= 0) { // terminate the game break; } your_hand[0].insure = your_hand[0].bet / 2; } else { your_hand[0].bet = 1; your_hand[0].insure = (float) 0.5; } // reshuffle if minimum number of cards left if (card_deck.deck_count > C.MAX_CARDS_PLAYED) { card_deck.shuffle(); } // initialize hands num_user_hands = 1; your_hand[0].initialize(); dealers_hand.initialize(); // deal the hand (two cards apiece) play.deal(card_deck, your_hand[0]); play.deal(card_deck, dealers_hand); play.deal(card_deck, your_hand[0]); play.deal(card_deck, dealers_hand); dealer_up_card = default_deck.ddeck[dealers_hand.card_indices[C.SECOND]].denomination; // display original hands if (C.interactive) { your_hand[0].display(); dealers_hand.display(); } // count original hands your_hand[0].count(); dealers_hand.count(); // test for your Blackjack if (your_hand[0].blackjack()) { if (C.interactive) { System.out.println("\n" + "You got blackjack."); } your_hand[0].bet += your_hand[0].insure; your_hand[0].play = false; } else { // test for insurance if (C.interactive && dealers_hand.insurance()) { your_hand[0].got_insurance = true; } else { your_hand[0].got_insurance = false; } } // test for dealer Blackjack if (dealers_hand.blackjack()) { if (C.interactive) { System.out.println("\n" + "Dealer got blackjack."); } dealers_hand.first_card_down = false; if (C.interactive) { dealers_hand.display(); } your_hand[0].play = false; dealers_hand.play = false; } else if (C.interactive && your_hand[0].blackjack()) { dealers_hand.display(); } if (your_hand[0].got_insurance) { if (dealers_hand.blackjack()) { // subtract insurance from original bet your_hand[0].bet -= your_hand[0].insure; } else { // pay out insurance your_totals -= your_hand[0].insure; } } // if neither of you got blackjack, play on if (your_hand[0].play && dealers_hand.play) { // test for split if (your_hand[0].split(dealer_up_card)) { play.do_split(card_deck, your_hand[0], your_hand[num_user_hands]); num_user_hands++; if (your_hand[0].split_aces == false) { if (your_hand[0].split(dealer_up_card)) { play.do_split(card_deck, your_hand[0], your_hand[num_user_hands]); num_user_hands++; if (your_hand[0].split(dealer_up_card)) { play.do_split(card_deck, your_hand[0], your_hand[num_user_hands]); num_user_hands++; } } if (your_hand[1].split(dealer_up_card)) { play.do_split(card_deck, your_hand[1], your_hand[num_user_hands]); num_user_hands++; if (your_hand[1].split(dealer_up_card)) { play.do_split(card_deck, your_hand[1], your_hand[num_user_hands]); num_user_hands++; } } if (num_user_hands > 2) { if (your_hand[2].split(dealer_up_card)) { play.do_split(card_deck, your_hand[2], your_hand[num_user_hands]); num_user_hands++; } } } } // play all the user hands for (i = 0; i < num_user_hands; i++) { if (C.interactive) { if (num_user_hands > 1) { System.out.println("\n" + "\n" + "Hand: " + i); } else { System.out.println("\n"); } } your_hand[i].count(); if (C.interactive) { your_hand[i].display(); } if (your_hand[i].split_aces == true) { // you got the one card you are entitled to your_hand[i].play = false; } else if (your_hand[i].double_down(dealer_up_card)) { // test for double down and play one card for you your_hand[i].bet = your_hand[i].bet * 2; play.deal(card_deck, your_hand[i]); your_hand[i].count(); if (C.interactive) { your_hand[i].display(); } your_hand[i].play = false; } else { // play out hand normally while (your_hand[i].play) { if (C.interactive) { System.out.print("\n" + "Hit?(Y/N)"); System.out.flush(); answer = interact.get_answer(); if (C.check_rules) { if (your_hand[i].aces && your_hand[i].hard_ace) { rule_answer = rules.soft_hit_table[your_hand[i].hand_count] [dealer_up_card]; } else { rule_answer = rules.hard_hit_table[your_hand[i].hand_count] [dealer_up_card]; } if (answer != rule_answer) { interact.print_rule_violated(); } } if (answer == true) { play.deal(card_deck, your_hand[i]); your_hand[i].display(); your_hand[i].count(); if (your_hand[i].over) { your_hand[i].play = false; } } else { your_hand[i].play = false; } } else { if (your_hand[i].aces && your_hand[i].hard_ace) { your_hand[i].play = rules.soft_hit_table[your_hand[i].hand_count] [dealer_up_card]; } else { your_hand[i].play = rules.hard_hit_table[your_hand[i].hand_count] [dealer_up_card]; } if (your_hand[i].play) { play.deal(card_deck, your_hand[i]); your_hand[i].count(); if (your_hand[i].over) { your_hand[i].play = false; } } } } if (C.interactive || C.debug) { your_hand[i].display(); } } } } // dealers play dealers_hand.first_card_down = false; while (dealers_hand.play) { if (C.interactive || C.debug) { dealers_hand.display(); } dealers_hand.count(); if ((dealers_hand.hand_count < C.SEVENTEEN) || ((dealers_hand.hand_count == C.SEVENTEEN) && (dealers_hand.aces && dealers_hand.hard_ace))) { /* note that dealer must hit below 17 and stay at 17 or over * but he must also hit a soft 17 */ play.deal(card_deck, dealers_hand); } else { // dealer must stay or is busted dealers_hand.play = false; } } /* end while */ // settle score for all hands played for (i = 0; i < num_user_hands; i++) { if (C.interactive) { if (num_user_hands > 1) { System.out.println("\n" + "\n" + "Hand: " + i); } else { System.out.println("\n"); } } your_totals = tally.settle_score(your_totals, your_hand[i], dealers_hand); } // print running tab if (C.interactive) { tally.print_totals(your_totals); } else { if (hands_played == C.num_hands) { break; } } } // end for loop if (!C.interactive) { tally.print_totals(your_totals); } System.exit(0); } // end main };