Stuck on Blackjack Program

Hi all, I’m building some blackjack code just for fun but encountered a problem when I was testing my duplicate card function. I decided to test the function by drawing all 52 cards in the deck and printing them out to see, assuming that the duplicate card function would work it should print out all 52 cards on the screen, but it’s not. It doesn’t even get to the card printing/debug serial print section of my void loop.

Here’s the code:

String cardNames[] = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
String Suit[] = {" of Spades"," of Clubs"," of Diamonds"," of Hearts"};

String playerHand[52];
String dealerHand[7];

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
randomSeed(analogRead(0));
}

void loop() {
  // put your main code here, to run repeatedly: 
  
  WaitforKey();
  Draw(52,"player");
  Serial.println("debug");
  for(int i = 0;i<52;i++)
   {
    Serial.println(playerHand[i]); 
   }
}

void WaitforKey()
{
  boolean keypress = false;
  while(keypress == false){
  if(Serial.available() > 0)
    {
     keypress = true;
     Serial.read();
    }
  }
}

void Draw(int numberDraws, String individual){
  if(individual == "player")
  {
    for(int i = 0;i<numberDraws;i++)
      {
        String Card;
        do
        {
          
        String randomCard = cardNames[random(0,13)];
        String randomSuit = Suit[random(0,3)];
        Card = randomCard + randomSuit;
        
      }while(duplicateCheck(Card) == true);
                
        int cardSlot = 0;
        Serial.println(playerHand[38]); 
        while(playerHand[cardSlot] != "")
          {cardSlot++;}
        playerHand[cardSlot] = Card;
        Serial.println(cardSlot);
        //Serial.println("debug");
      }
  }
}

boolean duplicateCheck(String Card)
  {
    for(int i = 0;i<52;i++)
      {
        if(playerHand[i] == Card)
          {return(true);}
       // if(dealerHand[i] == Card)
         // {return(true);}
      }
    return(false);
  }

Doing a little troubleshooting I think I tracked the problem down to this section of code:

 while(playerHand[cardSlot] != "")
          {cardSlot++;}

basically this part is intended to change the slot in the array for the card to be placed, if the slot isn’t empty then it adds one to cardSlot and tries again to place a card there. The problem with this piece of code, which I don’t understand, is that it will always get stuck at 38.

Please help! :zipper_mouth_face:

I suspect you're running short of RAM. Ditch the Strings.

You need only six bits to identify any card, using a String is a waste of RAM.

Okay, sounds good, should I try using characters instead? Also is there a command I can use to monitor how much is being used?

EDIT: After a little bit of searching I found a available memory library here and after trying it, it does look like a large array of strings is pretty intensive on the RAM.

The problem is though that I don't really know what to replace Strings with that will work identical to what I've already made. I tried playing with adding characters together like I do the two string arrays, but it's not really working out well. What I plan on doing in the mean time is just using the code as is. Since I only actually need at most 14 or less cards stored for the player and dealer for the actual game I shouldn't have memory problems using Strings. Though it would be nice to know another way to fix my memory usage for the future.

jaeryl:

You can reduce this:

 String Suit[] = {" of Spades"," of Clubs"," of Diamonds"," of Hearts"};

to this:

String Suit[] = {"Spades","Clubs","Diamonds","Hearts"};
...
        Card = randomCard + " of " + randomSuit;

saving 12 bytes and this:String cardNames[] = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"}; to this:Char cardNames[] = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"}; saving a further 26 bytes, but that uses a non-standard abbreviation (T) for ten.

Why not just get a random number between 1 and 13 (no need for an array) and use if/ else or switch/ case to name the 3 court cards (11, 12 or 13), or ace, if selected.

I think I understand what you’re saying Henry, I’ll rewriting it a bit and post back with my results

EDIT: Alright, I changed up my code to what I believe Henry said and thought I had everything working, but when testing my duplicate card function with the entire deck I’m having the same problem I was in my original post. Here’s my code:

//#include <MemoryFree.h>

int playerHandValue[52];
int playerHandSuit[52];

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
randomSeed(analogRead(0));
for(int i = 0; i < 52;i++)
  {
    playerHandValue[i] = 0;
    playerHandSuit[i] = 0;
  }
}

void loop() {
  // put your main code here, to run repeatedly: 
  
  //WaitforKey();
  Draw(52);
  displayCards(1,52);
  while(1);
  
}

void WaitforKey()
{
  boolean keypress = false;
  while(keypress == false){
  if(Serial.available() > 0)
    {
     keypress = true;
     Serial.read();
    }
  }
}

void Draw(int drawAmount){
 
  int randomCardValue;
  int randomCardSuit;
  
  for(int i = 0;i < drawAmount;i++)
    {
      do{
       randomCardValue = random(1,13);
       randomCardSuit = random(1,4);
      } while(duplicateCheck(randomCardValue,randomCardSuit) == true);
           

            
      int cardSlot = 0;
      
      while(playerHandValue[cardSlot] != 0)
        {cardSlot++;}
        
                      
Serial.println(cardSlot);
//Serial.print("freeMemory()=");
//    Serial.println(freeMemory());
      playerHandValue[cardSlot] = randomCardValue;
      playerHandSuit[cardSlot] = randomCardSuit;
    }
    
}

boolean duplicateCheck(int Value,int Suit)
  {
    for(int i = 0;i<52;i++)
      {
       if(Value == playerHandValue[i] && Suit == playerHandSuit[i])
          {return(true);} 
      }
      return(false);
  }
  
void displayCards(int Start,int End)
  {
    for(int i = (Start - 1);i<=(End - 1);i++)
      {
       if(playerHandValue[i] == 1 || playerHandValue[i] >= 11)
         {
           switch(playerHandValue[i]){
             case 1:
               Serial.print("Ace");
               break;
             case 11:
               Serial.print("Jack");
               break;
             case 12:
               Serial.print("Queen");
               break;
             case 13:
               Serial.print("King");
               break;
         }
      }
    else
      {
       if(i > 1)
       Serial.print(" ");
       
       Serial.print(playerHandValue[i]); 
      }
      
    switch(playerHandSuit[i]){
      case 1:
        Serial.print(" of Spades");
        break;
      case 2:
        Serial.print(" of Diamonds");
        break;
      case 3:
        Serial.print(" of Hearts");
        break;
      case 4:
        Serial.print(" of Clubs");
        break;
  }
  if(i < End)
    {Serial.print(",");}
      Serial.println("");

  }
  }

The problem is, similar to the original post my cardSlot while loop will only get to 35 before getting stuck. With a little troubleshooting I’ve narrowed the problem down to the duplicateCheck/top of my draw function:

do{
       randomCardValue = random(1,13);
       randomCardSuit = random(1,4);
       Serial.println("debug");
      } while(duplicateCheck(randomCardValue,randomCardSuit) == true);

By putting my serial.println in this section of my code I noticed when the for loop gets to 35 it will get stuck in this do while loop and continuously repeat, though I don’t understand why.