Black Jack! The dealer stands on all 17s. Doubling after splitting is always all
ID: 3755501 • Letter: B
Question
Black Jack!
The dealer stands on all 17s. Doubling after splitting is always allowed. Multiple splitting is always allowed.
The yellow highlighting in BlackJack represents the optimal decision given your cards and the dealer's up card. Refer to the table below for the complete optimal strategy for blackjack. Across is the dealer's up card (T means a 10 or any face card). Down is your hand value. The table entries are as follows:
• S = Stand
• H = Hit
• D = Double Down
• P = Split
The A/ table entries represent soft hands of two or more cards. Splitting is only relevant at the bottom of the table where the possible duplicate card values are listed.
The row value listed next to the hand total indicates the row in the strategy array (see BlackJackPlayer) where the desired move for the corresponding hand total can be found. After the row has been determined by the hand total, simply go to the column corresponding to the dealer's up card. Note: the hand totals begin with 2 (two aces, row 0) and go up to 21 (row 19).
Dealer's Up Card
2
3
4
5
6
7
8
9
T
A
<= 8 (row 0 - 6)
H
H
H
H
H
H
H
H
H
H
9 (row 7)
H
D
D
D
D
H
H
H
H
H
10 (row 8)
D
D
D
D
D
D
D
D
H
H
11 (row 9)
D
D
D
D
D
D
D
D
D
H
12 (row 10)
H
H
S
S
S
H
H
H
H
H
13 (row 11)
S
S
S
S
S
H
H
H
H
H
14 (row 12)
S
S
S
S
S
H
H
H
H
H
15 (row 13)
S
S
S
S
S
H
H
H
H
H
16 (row 14)
S
S
S
S
S
H
H
H
H
H
>= 17 (row 15 - 19)
S
S
S
S
S
S
S
S
S
S
A/2 (row 20)
H
H
H
D
D
H
H
H
H
H
A/3 (row 21)
H
H
H
D
D
H
H
H
H
H
A/4 (row 22)
H
H
D
D
D
H
H
H
H
H
A/5 (row 23)
H
H
D
D
D
H
H
H
H
H
A/6 (row 24)
H
D
D
D
D
H
H
H
H
H
A/7 (row 25)
S
D
D
D
D
S
S
H
H
H
A/8 (row 26)
S
S
S
S
S
S
S
S
S
S
A/9 (row 27)
S
S
S
S
S
S
S
S
S
S
A/10 (row 28)
S
S
S
S
S
S
S
S
S
S
2/2 (row 29)
P
P
P
P
P
P
H
H
H
H
3/3 (row 30)
P
P
P
P
P
P
H
H
H
H
4/4 (row 31)
H
H
H
P
P
H
H
H
H
H
5/5 (row 32)
D
D
D
D
D
D
D
D
H
H
6/6 (row 33)
H
P
P
P
P
H
H
H
H
H
7/7 (row 34)
P
P
P
P
P
P
H
H
H
H
8/8 (row 35)
P
P
P
P
P
P
P
P
P
P
9/9 (row 36)
P
P
P
P
P
S
P
P
S
S
10/10 (row 37)
S
S
S
S
S
S
S
S
S
S
A/A (row 38)
P
P
P
P
P
P
P
P
P
P
Part I: Decks of Cards
Download the Card class at PLEASE SEE DROPBOX LINK : https://www.dropbox.com/s/0782vvtss4q4pq5/Card.class?dl=0
Card class will compare by face value first, then by suit. A sorted Deck of Cards will have all the Aces first in the order Spades, Hearts, Clubs, Diamonds. Then the 2s in the same suit order, and so forth.
Complete the constructor in the Decks class PLEASE SEE DROPBOX LINK : https://www.dropbox.com/s/10kdogih9ctd0nv/Decks.java?dl=0
Create the requested number of standard 52 card decks (check user input). You will need to use a nested for loop. After you have all the required Cards, shuffle all of the of Cards together.
Complete the shuffle method in the Decks class. Use the Permutation class, which requires the Random class PLEASE SEE DROPBOX LINK : https://www.dropbox.com/s/cw9lo6kh9l169ib/Random.java?dl=0
After all of the Cards are shuffled, reset count so that all of the Cards in the Decks are again available.
Look at the deal method PLEASE SEE DROPBOX LINK : https://www.dropbox.com/s/wlomhwvqxv00870/Method%20Detail.docx?dl=0
The deal method uses the count instance variable to return the next Card in the Decks. After a Card has been selected from the Decks, count is decremented in preparation for the next call to deal. If there are no more Cards left to deal, shuffle is called to reset the Decks.
Part II: BlackJackHand
Complete the BlackJackHand class PLEASE SEE DROPBOX LINK : https://www.dropbox.com/s/wbyaibs6ww0zoa2/BlackJackHand.java?dl=0
A BlackJackHand object holds a minimum of two Cards, but the maximum number that the hand will hold is not known. Thus, it is convenient to use an ArrayList to hold the Cards in the BlackJackHand. Make your ArrayList able to hold only Card objects. The constructor will accept two Cards, which are placed in the ArrayList. You must also determine whether the hand is a soft hand or not. Simply determine if one of the two Cards is an Ace, in which case the hand is soft. The remaining methods that you need to complete are described in the comments.
Part III: BlackJackPlayer
Complete the BlackJackPlayer class PLEASE SEE DROPBOX LINK : https://www.dropbox.com/s/7t4nog650mcte1r/BlackJackPlayer.java?dl=0
The BlackJackPlayer class holds all of the player's hands. Like the number of cards in a BlackJackHand, the maximum number of hands that the player will have is not known (due to splitting). BlackJackPlayer keeps track (through the index instance variable) of which hand the player is currently
playing. The BlackJackPlayer class also has-a BlackJackStrategy which must be instantiated in the constructor.
Part IV: BlackJackStrategy
Complete the BlackJackStrategy class PLEASE SEE DROPBOX LINK : https://www.dropbox.com/s/vq21juzpqbpxkz4/BlackJackStrategy.java?dl=0
To obtain the desired move given a player's hand total and the dealer's up card. The desired strategy is read in from a text file and stored in a matrix ,BasicMatrixInterface PLEASE SEE DROPBOX LINK :
https://www.dropbox.com/s/mdfzgdmv7doww1a/BasicMatrixInterface.java?dl=0
https://www.dropbox.com/s/1zgdxe0wypv5ocb/BasicMatrixInterface.class?dl=0
Use the row and column information provided above to determine the optimal strategy. Your result will be highlighted in yellow when the game is running. The user is not required to use the optimal strategy, however. Assume a BlackJackHand method isSoft() is available PLEASE SEE DROPBOX LINK : https://www.dropbox.com/s/wbyaibs6ww0zoa2/BlackJackHand.java?dl=0
https://www.dropbox.com/s/hpjrhb30qg5es7g/BlackJackHand.html?dl=0
which you will write in the next part. Note the following convention when reading from the text file:
• 1 = Stand
• 2 = Hit
• 3 = Double
• 4 = Split
Dealer's Up Card
2
3
4
5
6
7
8
9
T
A
<= 8 (row 0 - 6)
H
H
H
H
H
H
H
H
H
H
9 (row 7)
H
D
D
D
D
H
H
H
H
H
10 (row 8)
D
D
D
D
D
D
D
D
H
H
11 (row 9)
D
D
D
D
D
D
D
D
D
H
12 (row 10)
H
H
S
S
S
H
H
H
H
H
13 (row 11)
S
S
S
S
S
H
H
H
H
H
14 (row 12)
S
S
S
S
S
H
H
H
H
H
15 (row 13)
S
S
S
S
S
H
H
H
H
H
16 (row 14)
S
S
S
S
S
H
H
H
H
H
>= 17 (row 15 - 19)
S
S
S
S
S
S
S
S
S
S
A/2 (row 20)
H
H
H
D
D
H
H
H
H
H
A/3 (row 21)
H
H
H
D
D
H
H
H
H
H
A/4 (row 22)
H
H
D
D
D
H
H
H
H
H
A/5 (row 23)
H
H
D
D
D
H
H
H
H
H
A/6 (row 24)
H
D
D
D
D
H
H
H
H
H
A/7 (row 25)
S
D
D
D
D
S
S
H
H
H
A/8 (row 26)
S
S
S
S
S
S
S
S
S
S
A/9 (row 27)
S
S
S
S
S
S
S
S
S
S
A/10 (row 28)
S
S
S
S
S
S
S
S
S
S
2/2 (row 29)
P
P
P
P
P
P
H
H
H
H
3/3 (row 30)
P
P
P
P
P
P
H
H
H
H
4/4 (row 31)
H
H
H
P
P
H
H
H
H
H
5/5 (row 32)
D
D
D
D
D
D
D
D
H
H
6/6 (row 33)
H
P
P
P
P
H
H
H
H
H
7/7 (row 34)
P
P
P
P
P
P
H
H
H
H
8/8 (row 35)
P
P
P
P
P
P
P
P
P
P
9/9 (row 36)
P
P
P
P
P
S
P
P
S
S
10/10 (row 37)
S
S
S
S
S
S
S
S
S
S
A/A (row 38)
P
P
P
P
P
P
P
P
P
P
Explanation / Answer
BlackJackHand.java
import java.util.ArrayList;
import java.awt.Graphics;
/**
* This class represents a black jack hand, which contains two or more Cards.
*/
public class BlackJackHand
{
/** The ArrayList to store all of the Cards in the BlackJackHand. */
private ArrayList<Card> hand;
/** A boolean to keep track of whether the Hand is soft or not. */
private boolean soft;
/** A boolean to keep track of whether the Hand has been doubled or not. */
private boolean doubled;
/**
* The constructor to accept the starting two Cards for this BlackJackHand.
* If one of the Cards is an ace, this BlackJackHand is soft (card.getFaceInt() == 1).
* The hand is not doubled initially.
*/
public BlackJackHand(Card c1, Card c2)
{
//remember to instantiate the ArrayList before adding anything to it
hand = new ArrayList<Card>();
hand.add(c1);
hand.add(c2);
if(c1.getFaceInt() == 1 || c2.getFaceInt() == 1)
soft = true;
else
soft = false;
}
/** Draws this BlackJackHand (a player hand) to the screen. */
public void drawPlayerHands(Graphics g, int x, int y)
{
int count = 0;
//DO THIS write a for-each loop to draw all of the cards in the player's hand
for(Card card : hand){
card.draw(g, x, y + (count*35));
count++;
}
}
/** Draws this BlackJackHand (the dealer's hand) to the screen. */
public void drawDealerHand(Graphics g, int x, int y, boolean done)
{
int count = 0;
//DO THIS write a for-each loop to draw all of the cards in the dealer's hand
for(Card card : hand){
//the first card that the dealer gets is the up card
//unless the current game is complete, the second card is hidden
if (count == 0)
{
card.draw(g, x, y + (count*35));
}
else if (done)
{
card.draw(g, x, y + (count*35));
}
count++;
}
}
private static int handVal = 0;
private int[] sum()
{
int[] sum = new int[2];
sum[0] = 0;
sum[1] = 0;
boolean ace = false; //only one ace is given the value of 11
//DO THIS (use a for-each statement and complete some details below
for(Card card : hand){
int faceInt = card.getFaceInt();
if (faceInt > 10) {
faceInt = 10;
}
sum[0] += faceInt;
if (faceInt == 1 && !ace)
{
sum[1] += faceInt + 10;
ace = true;
}
else
{
sum[1] += faceInt;
}
}
return sum;
}
public int handValue()
{
int[] total = sum();
handVal++;
//DO THIS
int hand1 = total[0];
int hand2 = total[1];
if(hand2 >21){
soft = false;
return hand1;
} else if(hand2 < 21 && hand2 == hand1){
soft = false;
return hand1;
}else{
soft = true;
return hand2;
}
}
public void hit(Card card)
{
//DO THIS
hand.add(card);
}
public boolean canSplit()
{
boolean split = false;
if (hand.size() == 2)
{
//DO THIS
Card c1 = hand.get(0);
Card c2 = hand.get(1);
if(c1.getFaceInt() == c2.getFaceInt())
split = true;
}
return split;
}
public BlackJackHand[] split(Card card1, Card card2)
{
BlackJackHand[] split = null;
if (canSplit())
{
//DO THIS
BlackJackHand h1 = new BlackJackHand(hand.get(0), card1);
BlackJackHand h2 = new BlackJackHand(hand.get(1), card2);
split = new BlackJackHand[]{h1, h2};
}
return split;
}
/** Returns the value of the first Card in the ArrayList in case this BlackJackHand is the dealer's hand. */
public int upCard()
{
Card card = hand.get(0);
int faceInt = card.getFaceInt();
if (faceInt > 10)
{
faceInt = 10;
}
return faceInt;
}
/** Returns the number of Cards in this BlackJackHand. */
public int numCards()
{
return hand.size();
}
/**
* Returns true if this BlackJackHand has been doubled, and false otherwise.
*/
public boolean isDouble()
{
return doubled;
}
/**
* Sets this BlackJackHand as having been doubled.
*/
public void doubleDown()
{
doubled = true;
}
/**
* Returns true if this BlackJackHand is soft, and false otherwise.
*/
public boolean isSoft()
{
return soft;
}
}
BlackJackPlayer.java
import java.util.ArrayList;
import java.awt.Graphics;
import java.awt.Color;
public class BlackJackPlayer
{
private ArrayList<BlackJackHand> hands;
private BlackJackStrategy strategy;
private int hand_index; //index of 1 is the first hand
public BlackJackPlayer(String filename)
{
hands = new ArrayList<BlackJackHand>();
strategy = new BlackJackStrategy(filename);
hand_index = 0; //keep track of which hand is being operated on by the game
}
public void draw(Graphics g, int width, int height)
{
int count = 1;
int num_hands = numHands();
double offset = (num_hands - 1)/2.0 * 100.0;
int off = width/2 - (int) offset;
//DO THIS use a for-each loop to draw all of the player hands
for(BlackJackHand hand : hands){
hand.drawPlayerHands(g, off + (count - 1) * 100 - 50, 300);
if (count == hand_index) //indicate the current hand with a yellow dot above the hand
{
g.setColor(Color.black);
g.fillOval(off + (count - 1) * 100 - 23, 284, 13, 13);
g.setColor(Color.yellow);
g.fillOval(off + (count - 1) * 100 - 21, 285, 10, 10);
g.setColor(Color.black);
}
count++;
}
}
public void split(Card card1, Card card2)
{
if (canSplit())
{
//DO THIS
for( BlackJackHand hand : hands){
if(hand.canSplit()) {
hands.remove(hand);
BlackJackHand[] array = hand.split(card1, card2);
hands.add(array[0]);
hands.add(array[1]);
}
}
}
}
public void doubleDown(Card dealt)
{
BlackJackHand hand = hands.get(hand_index - 1);
hand.hit(dealt);
System.out.println("Double");
//DO THIS (call a method in BlackJackHand)
hand.doubleDown();
}
public void hit(Card dealt)
{
BlackJackHand hand = hands.get(hand_index - 1);
hand.hit(dealt);
}
public int result(BlackJackHand dealer)
{
int winnings = 0;
int dValue = dealer.handValue();
//DO THIS
//use a for-each loop to compute the player's winnings over all player hands
for(BlackJackHand hand : hands){
int pValue = hand.handValue();
//check for player bust first
if (pValue > 21)
{
if (hand.isDouble())
{
winnings -= 1;
}
winnings -= 1;
}
//only if player did not bust do we check for a dealer bust
else if (dValue > 21)
{
if (hand.isDouble())
{
winnings += 1;
}
winnings += 1;
}
else if (pValue > dValue)
{
if (hand.isDouble())
{
winnings += 1;
}
winnings += 1;
}
else if (dValue > pValue)
{
if (hand.isDouble())
{
winnings -= 1;
}
winnings -= 1;
}
}
return winnings;
}
//'S' = stand, 'H' = hit, 'D' = double, 'P' = split
public char optimal(BlackJackHand dealer)
{
if (hand_index > numHands())
{
return 0;
}
BlackJackHand hand = hands.get(hand_index - 1);
//first, determine if a split is possible
boolean can_split = canSplit();
if (can_split)
{
//if a split is possible, should we do it?
boolean should_split = strategy.shouldSplit(hand, dealer);
if (should_split)
{
return 'P';
}
}
char optimal = strategy.getMove(hand, dealer);
//make sure the player can double if that is the optimal move (else just hit)
if (optimal == 'D' && hand.numCards() > 2)
{
optimal = 'H';
}
return optimal;
}
public int numHands()
{
return hands.size();
}
public boolean isDone()
{
return (hand_index > numHands());
}
//starting a new hand
public void removeAllHands(BlackJackHand playersHand)
{
hands.clear();
hand_index = 1;
hands.add(hand_index - 1, playersHand);
}
public void nextHand()
{
hand_index++;
}
public boolean canSplit()
{
if (hand_index > numHands())
{
return false;
}
BlackJackHand current = hands.get(hand_index - 1);
return current.canSplit();
}
public int handValue()
{
BlackJackHand current = hands.get(hand_index - 1);
return current.handValue();
}
}
BlackJackStrategy.java
import matrix.*;
public class BlackJackStrategy
{
private BasicMatrixInterface strategy;
public char getMove(BlackJackHand player, BlackJackHand dealer)
{
int up_card = dealer.upCard();
int player_value = player.handValue();
char optimal = 'S';
int col = up_card;
if(up_card == 1)//Dealer Ace card hint
col = 9;
//First determine if player hand is hard or soft
if(player.isSoft()){
player_value +=7;
optimal = getAction(strategy.getElement(player_value, col));
}else{
optimal = getAction(strategy.getElement(player_value, col));
}
return optimal;
}
public char getAction(double val){
switch((int)val){
case 1:
return 'S';
case 2:
return 'H';
case 3:
return 'D';
case 4:
return 'P';
default:
return 'S';
}
}
public boolean shouldSplit(BlackJackHand player, BlackJackHand dealer)
{
int up_card = dealer.upCard();
boolean should_split = false;
int row = player.handValue();
int col = up_card;
if(player.canSplit() && getAction(strategy.getElement(row, col)) == 'P'){
//Determine strategy
should_split = true;
}
return should_split;
}
/** Reads the strategy in from a file. */
public BlackJackStrategy(String fileName)
{
strategy = MatrixCreator.create(39, 10);
FileIO file = new FileIO(fileName, FileIO.FOR_READING);
int rows = strategy.getNumRows();
int cols = strategy.getNumColumns();
for (int i = 1; i <= rows; i++)
{
for (int j = 1; j <= cols; j++)
{
String line = file.readLine();
int strategy_int = Integer.parseInt(line);
strategy.setElement(i, j, strategy_int);
}
}
file.close();
}
}
Decks.java
/**
* Represents one or more decks of cards.
*/
public class Decks
{
/** An array of Cards representing multiple complete decks of the standard 52 deck of cards. */
private Card[] decks;
/** The number of Cards remaining in the deck. */
private int count;
/** The number of Decks. */
private int numDecks;
/** The total number of Cards. */
private final int SIZE;
/** The size of a standard deck of cards. */
public final int STANDARD_DECK_SIZE = 52;
/**
* Constructor to create several copies of the standard 52 deck of cards and to shuffle them all together.
*/
public Decks(int num)
{
if (num > 0 && num < 10)
{
numDecks = num;
}
else
{
numDecks = 1;
}
SIZE = STANDARD_DECK_SIZE * numDecks;
decks = new Card[SIZE];
int count = 0;
for (int i = 0; i < numDecks; i++)
{
for(int j =1; j <=52; j++){
decks[(52*count)+j-1] = new Card(j);
}
count++;
}
//DO THIS
//mix them up
shuffle();
//printArray(decks);
}
public void printArray(Card[] d){
int count = 1;
for( Card c : d){
if (c != null){
System.out.println("Card " + count + " :" + c.toString());
count++;
}
}
}
public void shuffle()
{
//Copy of decks
Card[] shuffle_deck = decks.clone();
//use the Permutation class to shuffle the Cards
Permutation p = new Permutation(SIZE,SIZE-1);
for(int i = 0; i < SIZE-1; i++){
//DEBUG - PRINT
int val = p.next();
decks[i] = shuffle_deck[val];
}
count = SIZE - 1; //the entire deck is available again
}
public Card deal()
{
Card current;
if (count == -1)
{
shuffle();
}
current = decks[count];
count = count - 1;
return current;
}
/**
* Returns the number of Cards remaining in the Deck.
*/
public int getCount()
{
return count + 1;
}
/**
* Returns the number of Decks.
*/
public int getNumDecks()
{
return numDecks;
}
/**
* Lists the Cards remaining in the Deck.
*/
public String toString()
{
String temp = "";
for (int i = count; i >= 0; i--)
{
temp += decks[i] + " ";
}
return temp;
}
}
Permutation.java
import java.util.List;
import java.util.ArrayList;
public class Permutation
{
private int r;
private List<Integer> numbers;
//pick r of them from 1 to n
public Permutation(int r, int n)
{
this.r = r;
numbers = new ArrayList<Integer>();
for (int i = 1; i <= n; i++)
{
numbers.add(i);
}
}
public int next()
{
if (r == 0) return -1;
int rand = Random.getRandomNumberGenerator().randomInt(1, numbers.size());
int value = numbers.get(rand - 1);
numbers.remove(rand - 1);
r--;
return value;
}
}
Random.java
/**
* A class to return random numbers (int and double) within a user specified range. <br>
*/
public class Random
{
private static Random random = new Random();
/** The object that will generate the random numbers. Only one random number generator is ever needed. */
private java.util.Random rand;
private Random()
{
rand = new java.util.Random(System.currentTimeMillis());
}
public static Random getRandomNumberGenerator()
{
return random;
}
/**
* Returns a randomly generated integer between low and high (inclusive of both).
*/
public int randomInt(int low, int high)
{
return rand.nextInt(high - low + 1) + low;
}
/**
* Returns a randomly generated floating point number between low (inclusive) and high (exclusive).
*/
public double randomFloat(int low, int high)
{
return rand.nextDouble()*(high - low) + low;
}
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.