Search code examples
c++algorithmblackjack

BlackJack Algorithm


What is the general alogirthm for a BlackJack game ? I'm writing one in c++ and end up having WAY too many if statements which ruin the whole thing.

The project is a win32 GUI application, and Im posting the message loop as well as the part of the program that checks the game's status Posting the complete code will make it humongous, so here are the links to all the files: Full Source Code

Message Loop

LRESULT CALLBACK WndProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ){
  switch(Msg)
  {
  case WM_PAINT:
  {
      PAINTSTRUCT PS;
      HDC hDC = BeginPaint(hWnd, &PS);
      You.Draw(hDC);
      Dealer.Draw(hDC);
      EndPaint(hWnd, &PS);
      if(Bet.Enabled){
          Bet.GetFocus();
          Bet.Select(0,Bet.Length());
      }
  }
  return 0;
  case WM_CTLCOLORSTATIC:
  {
      SetBkMode((HDC)wParam, TRANSPARENT);
  }
  return (INT_PTR)(HBRUSH)GetStockObject(NULL_BRUSH);
  case WM_CREATE:
  {
      //Create edit control
      Bet.Create(hWnd, 10, 550, 100, 25, "0");
      //Create labels
      char Buffer[30];
      sprintf(Buffer, "%d", You.HandValue());
      BetLabel.Create(hWnd, 10, 500, 100, 40, "Enter Bet Amount");
      GameControls.Create(hWnd, 10, 375, 100, 40, "Game Controls");
      PlayerLabels.Create(hWnd, 10, 10, 100, 20, "You:");
      PlayerLabels.Create(hWnd, 10, 150, 100, 20, "Dealer:");
      HandValueLabel.Create(hWnd, (int)You.x[You.cards] + 85, (int)You.y[You.cards] + 25, 100, 20, Buffer);
      YourMoney.Create(hWnd, 125, 500, 100, 40, "Your money: ");
      sprintf(Buffer, "%d", You.money);
      MoneyValue.Create(hWnd, 125, 525, 100, 40, Buffer);
      //Create buttons
      Ok.Create(hWnd, 10, 600, 100, 50, "Ok");
      Hit.Create(hWnd, 10, 425, 100, 50, "Hit");
      Stand.Create(hWnd, 120, 425, 100, 50, "Stand");
      //Select Text
      Bet.Select(0,3);
  }
  return 0;
  case WM_CLOSE:
    exit(0);
    break;
  case WM_COMMAND:
  {
      switch(HIWORD(wParam))
      {
      case BN_CLICKED:
      {
          switch(LOWORD(wParam))
          {
          case ID_OK:
          {
              //Place bet
              int bet = 0;
              bet = StringToNumber(Bet.Text());
              You.money -= bet;
              char Buffer[30];
              sprintf(Buffer, "%d", You.money);
              MoneyValue.SetText(Buffer);
              //Update the window
              InvalidateRect(hWnd, 0, TRUE);
              You.Bet = YES;
              Ok.Disable();
              Bet.Disable();
              You.DealCard();
              You.DealCard();
              Dealer.DealCard();
              Dealer.DealCard();
              You.win = false;
              You.bust = false;
              You.playing = YES;
              Dealer.win = NO;
              Dealer.bust = NO;
              Dealer.playing = YES;
          }
          break;
          case ID_HIT:
          {
             if(You.HandValue() < 21 && You.playing && !You.bust){
                 //Deal a card to the player, if he hasn't won or lost
                 You.DealCard();
             }
             if((Dealer.HandValue() <= 17 || Dealer.HandValue() < You.HandValue()) && Dealer.playing)
                       {
                         Dealer.DealCard();
                       }
            //Update Hand Value
            char Buffer[30];
            sprintf(Buffer, "%d", You.HandValue());
            HandValueLabel.SetText(Buffer);
            InvalidateRect(hWnd,0,TRUE);
            MoveWindow(HandValueLabel.Handle, (int)You.x[You.cards] + 80, (int)You.y[You.cards] + 25, 100, 20, TRUE);
            RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
          }
          break;
          case ID_STAND:
              if(Hit.Enabled){
                  //Don't deal more cards
                  Hit.Disable();
                  You.playing = false;
              }
              if((Dealer.HandValue() <= 17 || Dealer.HandValue() < You.HandValue()) && Dealer.playing){
                  //Deal a card to the dealer
                  Dealer.DealCard();
              }
          }

StatusChecker

void ProcessStatus(HWND hWnd){
     if(Dealer.HandValue() > 17){
          if(Dealer.HandValue() > You.HandValue() && Dealer.playing){
              Dealer.playing = false;
            }
          else if(!You.playing && Dealer.HandValue() <= You.HandValue() && Dealer.playing){
              Dealer.DealCard();
            }
        }
      else if(Dealer.HandValue() <= 17 && Dealer.HandValue() <= You.HandValue() && !You.playing && Dealer.playing){
          Dealer.DealCard();
        }
      if(EvaluateStatus() != 0){
          status = OVER;
        }
     if(EvaluateStatus() == -1){
         switch(MessageBoxA(hWnd, "You Lost! \n Keep Playing ?", "You Lost!", MB_YESNO | MB_ICONQUESTION))
         {
         case IDYES:
             Reset();
             break;
         case IDNO:
             exit(0);
             break;
         }
     }
     else if(EvaluateStatus() == 1){
         switch(MessageBoxA(hWnd, "You Won! \n Keep Playing ?", "You Won!", MB_YESNO | MB_ICONQUESTION))
         {
         case IDYES:
             Reset();
             break;
         case IDNO:
             exit(0);
             break;
         }
     }
    }
int EvaluateStatus()
{
  if(You.HandValue() > 21 && You.playing)
    {
      You.bust = true;
      Dealer.win = true;
      You.playing = NO;
      return -1;
    }
  if(You.HandValue() == 21)
    {
      You.win = true;
      return 1;
    }
  if(Dealer.HandValue() > 21)
    {
      Dealer.bust = true;
      You.win = true;
      return 1;
    }
  if(Dealer.HandValue() == 21)
    {
      Dealer.win = true;
      return -1;
    }
  if(!You.playing && Dealer.HandValue() > You.HandValue() &&!Dealer.bust)
    {
      Dealer.win = true;
      return -1;
    }
  if(You.HandValue() > Dealer.HandValue() && (!You.playing && (!Dealer.playing || Dealer.bust)))
    {
      You.win = true;
      return 1;
    }
  if(You.HandValue() == Dealer.HandValue() && (!You.playing || !Dealer.playing))
    {
      You.win = true;
      return 1;
    }

Solution

  • As a first step: I probably wouldn't mix game logic and your GUI logic.. separate them into different modules.

    And if you only have two players, you only need a bool to decide which one won. You don't need for both of the players Bust and Won variables.