Search code examples
javaarraylistblackjack

Card Values in BlackJack Java


First time posting on here. I've heard many good things about the community. I'm an amateur programmer and have dabbled in C++ and Java so far. Anywhoo, I've been cracking my head open with this BlackJack game in java I've sort of haphazardly put together over the last few days. Basically, I am having an issue with the creating of my deck. I am using an ArrayList to hold the cards, but I cant figure out a way to correctly add a value to each card. As you can see by my code, I am using parseint to get the value from the String and add it to the card sum but the problem is, when values such as "Ace" and "Jack" "King" "Queen" come up, clearly no int can be parsed from there so when the program runs, everything works fine, unless of course one of the previously mentioned cards are pulled. Then I get an error that reads:

(""Exception in thread "main" java.lang.NumberFormatException: For input string: "Queen" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:580) at java.lang.Integer.parseInt(Integer.java:615) at blackjack.Blackjack.getHumanValue(Blackjack.java:110) at blackjack.Blackjack.main(Blackjack.java:27) Java Result: 1 BUILD SUCCESSFUL (total time: 0 seconds)"") .

I've tried looking it up online to see if I can spark some inspiration but all I can find is to use Enums or Switch to build my deck, but the problem is I don't fully understand those techniques yet. Any advice will be greatly appreciated.

Thanks!

public class Blackjack{


ArrayList<card> buildDeck = new ArrayList<card>();

public static void main(String[] args) 
{


    Blackjack b = new Blackjack();

    // Compares both scores. The largest score wins.

    if(b.getHumanValue() < b.getRobotValue())
    {
        System.out.println("ROBOT WINS!!!");
    }
    else if(b.getRobotValue() > 21 && b.getHumanValue() <=21 )
    {
        System.out.println("YOU WIN!!!");
    }

}


  public ArrayList<card> buildDeck(ArrayList<card> buildDeck)
{      
    String [] suit = {"Spade", "Hearts", "Clubs", "Diamonds"};
    String [] cardValue = {"Ace","2","3","4","5","6",
        "7","8","9","10","Jack","Queen","King"};

    for(int i = 0; i < suit.length; i++)
    {
        for(int j = 0; j < cardValue.length; j++)
        {

            card card = new card(suit[i], cardValue[j]);
            buildDeck.add(card);

        }
    }

    return buildDeck;
}


 // This returns the human score

  public int getHumanValue()
{
    buildDeck(buildDeck);

    Scanner s = new Scanner(System.in);

    card value;

    int ranCard = 0;
    int i = 0;
    int aceValue = 0;
    int totalValue = 0;

    String drawAgain = "";

    System.out.println("[[Dealer gives you two cards.]]");
    System.out.println("");

   while(i < 2)
    {
        ranCard = 0+(int)(Math.random()*52);
        System.out.println("Card " + (i+1) + ":");
        System.out.println(buildDeck.get(ranCard));
        value = buildDeck.get(ranCard);

      while(value.cardValue.equalsIgnoreCase("Ace")) // Ace value; either 1 or 11
        {
            System.out.println("");
            System.out.println("This is an ace.");
            System.out.println("It is equal to 1 or 11");
            System.out.println("Which number do you prefer?");
            System.out.println("");
            aceValue = s.nextInt();
            s.nextLine();
            if(aceValue == 11)
            {
                totalValue += 11;
                totalValue -= 1; // Subtracted 1; was off by one
                break;
            }
            else if(aceValue == 1)
                    {
                        totalValue += 1;
                        totalValue -= 1; // Subtracted 1; was off by one
                        break;
                    }
        }

        totalValue += Integer.parseInt(value.cardValue);
        System.out.println("Total Score: " + totalValue);
        System.out.println("");
        i++;
    }

    System.out.println("[[Would you like to draw another card? Yes/No]]");
    System.out.println("");

    drawAgain = s.nextLine();    

    System.out.println("");

    if(drawAgain.equalsIgnoreCase("YES"))
            {
        ranCard = 0+(int)(Math.random()*52);
        System.out.println("Card 3:");
        System.out.println(buildDeck.get(ranCard));
        value = buildDeck.get(ranCard);
        totalValue += Integer.parseInt(value.cardValue);
        System.out.println("Total Score: " + totalValue);
        System.out.println("");
    }
    else
    {

    }

    return totalValue;
}

// This returns the robot's score
// Mostly copied from gethumanValue method but more automated

public int getRobotValue()
{

    buildDeck(buildDeck);

    card value;

    int ranCard = 0;
    int i = 0;
    int totalValue2 = 0;

    System.out.println("[[Dealer gives Robot two cards.]]");
    System.out.println("");

    while(i < 2)
    {
        ranCard = 0+(int)(Math.random()*52);
        System.out.println("Card " + (i+1) + ":");
        System.out.println(buildDeck.get(ranCard));
        value = buildDeck.get(ranCard);

       while(value.cardValue.equalsIgnoreCase("Ace")) // Ace value; either 1 or 11
        {

            if(totalValue2 < 11)
            {
                totalValue2 += 11;
                totalValue2 -= 1; // Subtracted 1; was off by one
                break;
            }
            else if(totalValue2 > 10)
                    {
                        totalValue2 += 1;
                        totalValue2 -= 1; // Subtracted 1; was off by one
                        break;
                    }
        }

        totalValue2 += Integer.parseInt(value.cardValue);
        System.out.println("Total Score: " + totalValue2);
        System.out.println("");
        i++;
    }

    if(totalValue2 < 17)
    {
        ranCard = 0+(int)(Math.random()*52);
        System.out.println("Card 3:");
        System.out.println(buildDeck.get(ranCard));
        value = buildDeck.get(ranCard);
     while(value.cardValue.equalsIgnoreCase("Ace")) // Ace value; either 1 or 11
        {         
         if(totalValue2 < 11)
            {
                totalValue2 += 11;
                totalValue2 -= 1; // Subtracted 1; was off by one
                break;
            }
            else if(totalValue2 > 10)
                    {
                        totalValue2 += 1;
                        totalValue2 -= 1; // Subtracted 1; was off by one
                        break;
                    }
        }

        totalValue2 += Integer.parseInt(value.cardValue);
        System.out.println("Total Score: " + totalValue2);
        System.out.println("");
    }
    else
    {

    }

    return totalValue2;
}

}

EDIT Sorry, Forgot to include my card class!!!

public class card {
String suit;
String cardValue;



@Override
public String toString() {
    return cardValue + " of " + suit;
}


public card(String suit, String cardValue) {
    this.suit = suit;
    this.cardValue = cardValue;
}


public card(String cardValue) {
    this.cardValue = cardValue;
}

public String getSuit() {
    return suit;
}

public void setSuit(String suit) {
    this.suit = suit;
}

Solution

  • Pay close attention to this call.

    totalValue2 += Integer.parseInt(value.cardValue);
    

    It's innocuous enough since it works for any of the integer values you have in cardValue. But, you don't just have integral values there either - you have words, too.

    You can't change the word "Queen" to a number. Java doesn't have that capability, since it has no numerical meaning*.

    It'd be better to store the value of the card and the name of the card as separate parts of data, since the name of the card would also include the suit information.

    You haven't shown us your Card class implementation, but what you can do without changing your external contract is to do a bit of parsing on the inside when you get the String, and return an int instead of a String when you retrieve the cardValue. In the case of an "Ace" type, then depending on the total value of the hand, you should pick the most appropriate value (either 1 or 11). This part I leave as an exercise for the reader.

    public Card(String suit, String value) {
        this.suit = suit;
        switch(value) {
            case "Ace":
                isAce = true; // conditional logic req'd since Ace can be 1 or 11.
                break;
            case "Jack":
            case "Queen":
            case "King":
                this.value = 10;
                break;
         }
         this.cardName = value;
    }
    

    *: "Queen" does have a value in base 31: 24919187. But that's probably not what you were going for.