二十一点算法

发布于 2024-12-02 09:21:01 字数 6142 浏览 2 评论 0原文

二十一点游戏的一般算法是什么? 我正在用 C++ 编写一个,最终有太多的 if 语句破坏了整个事情。

该项目是一个 win32 GUI 应用程序,我发布了消息循环以及检查游戏状态的程序部分 发布完整的代码将使它变得巨大,所以这里是所有文件的链接: 完整源代码

消息循环

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;
    }

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;
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

耶耶耶 2024-12-09 09:21:01

第一步:我可能不会混合游戏逻辑和 GUI 逻辑..将它们分成不同的模块。

如果你只有两名玩家,你只需要一个 bool 来决定哪一个获胜。您不需要玩家的 Bust 和 Won 变量。

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.

↘人皮目录ツ 2024-12-09 09:21:01

Google 搜索显示了关于 BlackJack 算法的这篇 PDF 论文。我确信如果您使用 Google 进行更多研究,您也可以找到一些东西。

要弄清楚如何计算出玩游戏所需执行的实际步骤,请在纸上计算出游戏的不同步骤,然后决定如何创建代表游戏部分的类以及这些类中要执行的函数游戏的不同步骤。

这可能是一个迭代的事情,你经历它,然后创建一些类、函数等,现在你可以回去看看你所做的是否有意义,改进设计等。

也许还可以玩游戏,然后看看做了什么,如何将其转化为代码。

A google search revealed this PDF paper on BlackJack algorithms. I'm sure if you did some more research using Google, you could find things too.

To figure out how to work out the actual steps needing to be done to play the game, work out on paper the different steps of the game, then decide how you can create classes that represent parts of the game and functions in these classes to execute the different steps of the game.'

This could be an iterative thing, where you go through it, then create some classes, functions, etc, now you can go back and see if what you've done makes sense, improve on the design etc.

Perhaps also play the game and see what is done, how that could be translated into code.

潇烟暮雨 2024-12-09 09:21:01

我已经修改了程序处理消息的方式,并将其作为单独的答案发布。
由于一个小问题,它仍然被破坏,但我认为总体想法是可靠的。评论将不胜感激

cards.h

/*
 * cards.h
 *
 *  Created on: Aug 31, 2011
 *      Author: Viraj
 */
#ifndef CARDS_H_
#define CARDS_H_
#include <iostream>
#include <algorithm>
#define STARTED true
#define OVER false
#define YES true
#define NO false
using namespace std;
HINSTANCE hApplication;
HBITMAP Bitmap;
char Buffer[30];
class Deck{
public:
    int deck[53];
    Deck(){
        for(int suit = 1; suit <= 4; suit++){
            for(int card = 1; card <= 13; card++){
                deck[((suit-1)*13)+card] = card;
            }
        }
        deck[0] = 0;
    }
};
Deck deck;
class Cards{
private:
    int card_seed;
    int suit_seed;
public:
    int card[11];
    int cards;
    int value[11];
    Cards(){
        fill(card, card + 10, 0);
        fill(value, value + 10, 0);
        cards = 0;
    }
    void DealCard()
    {
        cards++;
        while(!deck.deck[card[cards]]){
            card_seed = rand()%13 + 1;
            suit_seed = rand()%4 + 1;
            card[cards] = (suit_seed - 1)*13 + card_seed;
        }
        deck.deck[card[cards]] = 0;
        if(card_seed > 1 && card_seed < 11){
             value[cards] = card_seed;
        }
        else if(card_seed >= 11 && card_seed <= 13){
            value[cards] = 10;
        }
        else if(card_seed == 1){
            value[cards] = 11;
        }
    }
};
class Player : public Cards {
public:
    float x[11];
    float y[11];
    bool playing;
    bool bust;
    bool win;
    int money;
    Player(const char* Type){
        srand(time(NULL));
        playing = true;
        if(Type == "Dealer"){
            for(int card = 1; card <= 10; card++){
                x[card] = 10 + (card-1)*75;
                y[card] = 200;
            }
        }
        else{
            for(int card = 1; card <= 10; card++){
                x[card] = 10 + (card-1)*75;
                y[card] = 35;
                money = 1000;
            }
        }
    }
    void Reset(){
        cards = 0;
        fill(card, card + 10, 0);
        fill(value, value + 10, 0);
        playing = true;
    }
    int HandValue(){
        int sum = 0;
        for(int current_card = 1; current_card <= cards; current_card++){
            sum += value[current_card];
          }
        if(sum > 21){
            for(int current_card = 1; current_card <= cards; current_card++){
                if(value[current_card] == 11 && sum > 21){
                    value[current_card] = 1;
                    sum = HandValue();
                    break;
                  }
              }
          }
        return sum;
    }
    void Draw(HDC hDC){
        HDC MemoryDevice;
        for(int CardToLoad = 1; CardToLoad <= cards; CardToLoad++){
            Bitmap = LoadBitmap(hApplication, MAKEINTRESOURCE(card[CardToLoad]));
            MemoryDevice = CreateCompatibleDC(hDC);
            SelectObject(MemoryDevice, Bitmap);
            BitBlt(hDC, (int)x[CardToLoad], (int)y[CardToLoad], 75, 100, MemoryDevice, 0, 0, SRCCOPY);
        }
        DeleteDC(MemoryDevice);
    }
};
class CONTROL{
public:
    HWND Handle;
    char* ClassName;
    char* Caption;
    DWORD ClassStyle;
    DWORD ExtendedStyle;
    int x;
    int y;
    int Width;
    int Height;
    int ID;
    bool Enabled;
    void Create(HWND ParentHandle, int x, int y, int Width, int Height, char* Caption){
        Handle = CreateWindowExA(ExtendedStyle, ClassName, Caption, ClassStyle, x, y, Width, Height, ParentHandle, (HMENU)ID, NULL, NULL);
        Enabled = true;
        CONTROL::Caption = Caption;
        CONTROL::x = x;
        CONTROL::y = y;
        CONTROL::Width = Width;
        CONTROL::Height = Height;
    }
    void GetFocus(){
        SetFocus(Handle);
    }
    void Disable(){
        EnableWindow(Handle, FALSE);
        Enabled = false;
    }
    void Enable(){
        EnableWindow(Handle, TRUE);
        Enabled = true;
    }
    void SetText(char* String){
        SetWindowTextA(Handle, String);
    }
};
class BUTTON : public CONTROL {
public:
    BUTTON(int Identifier){
        ClassStyle = BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD;
        ID = Identifier;
        ClassName = "BUTTON";
        ExtendedStyle = 0;
    }
};
class EDIT : public CONTROL {
public:
    EDIT(int Identifier){
        ClassStyle = ES_NUMBER | WS_VISIBLE | ES_CENTER | WS_CHILD | ES_NOHIDESEL;
        ExtendedStyle = WS_EX_CLIENTEDGE;
        ID = Identifier;
        ClassName = "EDIT";
    }
    void Select(int first, int last){
        Edit_SetSel(Handle, first, last);
    }
    int Length(){
        return Edit_GetTextLength(Handle);
    }
    const char* Text(){
        char Buffer[Length() + 1];
        Edit_GetText(Handle, (LPTSTR)&Buffer, Length() + 1);
        string String = Buffer;
        return String.c_str();
    }
};
class STATIC : public CONTROL {
public:
    STATIC() {
        ClassStyle = WS_VISIBLE | SS_CENTER | WS_CHILD;
        ID = 0;
        ClassName = "STATIC";
        ExtendedStyle = 0;
    }
};
Player You("You"), Dealer("Dealer");
BUTTON Ok(ID_OK), Hit(ID_HIT), Stand(ID_STAND);
EDIT Bet(ID_BET);
STATIC BetLabel, GameControls, PlayerLabels, HandValueLabel, YourMoney, MoneyValue, Bust;
class Game{
public:
    bool started;
    Game(){
        started = false;
    }
    void Stop(){
        started = false;
    }
    void ResetGame(HWND hWnd){
        //Reset Players
        You.Reset();
        Dealer.Reset();
        //Reset Controls
        Ok.Enable();
        Bet.Enable();
        Hit.Enable();
        //Reset Hand value
        sprintf(Buffer, "%d", You.HandValue());
        HandValueLabel.SetText(Buffer);
        //Reset deck
        deck = Deck();
        //Stop the game
        started = false;
        //Update the Display
        InvalidateRect(hWnd, 0, TRUE);
        RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
    }
    int SendMessage(HWND hWnd, int ButtonID, unsigned int MESSAGE, int Information, char* _Information){
        return ProcessMessage(hWnd, ButtonID, MESSAGE, Information, _Information);
    }
    int ProcessMessage(HWND hWnd, int ButtonID, unsigned int MESSAGE, int Information, char* _Information){
        switch(MESSAGE)
        {
        case START_GAME:
            //Place Bet
            You.money -= Information;
            started = YES;
            sprintf(Buffer, "%d", You.money);
            //Update Controls
            MoneyValue.SetText(Buffer);
            Ok.Disable();
            Bet.Disable();
            //Deal two cards to player and dealer
            You.DealCard();
            You.DealCard();
            Dealer.DealCard();
            Dealer.DealCard();
            //Update the Hand Value Label
            sprintf(Buffer, "%d", You.HandValue());
            HandValueLabel.SetText(Buffer);
            //Move the label
            MoveWindow(HandValueLabel.Handle, (int)You.x[You.cards] + 80, (int)You.y[You.cards] + 25, 100, 20, TRUE);
            //Send PAINT message
            InvalidateRect(hWnd,0, TRUE);
            RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
            //Check for BlackJacks
            if(You.HandValue() == 21){
                SendMessage(hWnd, 0, INTERNAL, YOU_WIN, "");
            }
            else if(Dealer.HandValue() == 21){
                SendMessage(hWnd, 0, INTERNAL, DEALER_WIN, "");
            }
            break;
        case STAND:
            if(started){
                Hit.Disable();
                You.playing = false;
            }
            break;
        case INTERNAL:
            switch(Information)
            {
            case DEALER_WIN:
                return MessageBoxA(hWnd, "You Loose! \n Play Again ?", "Game Over", MB_YESNO | MB_ICONINFORMATION);
            case YOU_WIN:
                return MessageBoxA(hWnd, "You Win! \n Keep Playing ?", "Game Over", MB_YESNO | MB_ICONINFORMATION);
            }
        break;
        case IDLE:
            if(started){
                //Check for BlackJacks
                if(Dealer.HandValue() == 21){
                    started = false;
                    switch(SendMessage(hWnd, 0, INTERNAL, DEALER_WIN, ""))
                    {
                    case IDYES:
                        ResetGame(hWnd);
                        return 0;
                    case IDNO:
                        exit(0);
                        return 0;
                    }
                }
                if(!You.playing && Dealer.playing && Dealer.HandValue() < You.HandValue())
                    Dealer.DealCard();
                    //Update the Window
                    InvalidateRect(hWnd,0, TRUE);
                    RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
                    //Check for a Bust
                    if(Dealer.HandValue() > 21){
                        switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
                        {
                        case IDYES:
                            ResetGame(hWnd);
                            return 0;
                        case IDNO:
                            exit(0);
                            return 0;
                        }
                    }
                    if(Dealer.HandValue() == 21){
                        switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
                        {
                        case IDYES:
                            ResetGame(hWnd);
                            return 0;
                        case IDNO:
                            exit(0);
                            return 0;
                        }
                    }

                }
        break;
        case HIT:
            //Check to see who's still playing and deal a card to them
            if(started){
            if(You.playing){
                You.DealCard();
                //Update the Hand Value Label
                sprintf(Buffer, "%d", You.HandValue());
                HandValueLabel.SetText(Buffer);
                //Move the label and update the screen
                MoveWindow(HandValueLabel.Handle, (int)You.x[You.cards] + 80, (int)You.y[You.cards] + 25, 100, 20, TRUE);
                InvalidateRect(hWnd, 0, TRUE);
                RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
                //Check for a BlackJack
                if(You.HandValue() == 21){
                    started = false;
                    switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
                    {
                    case IDYES:
                        ResetGame(hWnd);
                        return 0;
                    case IDNO:
                        exit(0);
                        return 0;
                    }
                }
                //Check for a bust
                if(You.HandValue() > 21){
                    started = false;
                    switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
                    {
                    case IDYES:
                        ResetGame(hWnd);
                        return 0;
                    case IDNO:
                        exit(0);
                        return 0;
                    }
                }
            }
            if(Dealer.playing){
                Dealer.DealCard();
                InvalidateRect(hWnd, 0, TRUE);
                RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
                //Check for BlackJack
                if(Dealer.HandValue() == 21){
                    started = false;
                    switch(SendMessage(hWnd, 0, INTERNAL, DEALER_WIN, ""))
                    {
                    case IDYES:
                        ResetGame(hWnd);
                        return 0;
                    case IDNO:
                        exit(0);
                        return 0;
                    }
                }
                //Check for Bust
                if(Dealer.HandValue() > 21){
                    started = false;
                    switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
                    {
                    case IDYES:
                        ResetGame(hWnd);
                        return 0;
                    case IDNO:
                        exit(0);
                        return 0;
                    }

                }
            }
            }
            break;
        }
        return 0;
    }
};
Game game;
#endif

消息循环

 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, 175, 100, 20, "Dealer:");
      HandValueLabel.Create(hWnd, (int)You.x[You.cards] + 85, 60, 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());
              game.SendMessage(hWnd, ID_OK, START_GAME, bet, "");
          }
          break;
          case ID_HIT:
          {
              //Tell the game that the player wants another card
              game.SendMessage(hWnd, ID_HIT, HIT, 0, "");
          }
          break;
          case ID_STAND:
              game.SendMessage(hWnd, ID_STAND, STAND, 0, "");
          }
      }
      break;
      }
    }
  break;
    default:
    //Default:
    game.SendMessage(hWnd, 0, IDLE, 0, "");
    return DefWindowProcA(hWnd, Msg, wParam, lParam);
    }
  return 0;
}

I have modified the way the program handles messages, and am posting it as a seperate answer.
It is still broken because of a minor hiccup, but i think the general idea is solid. comments would be appreciated

cards.h

/*
 * cards.h
 *
 *  Created on: Aug 31, 2011
 *      Author: Viraj
 */
#ifndef CARDS_H_
#define CARDS_H_
#include <iostream>
#include <algorithm>
#define STARTED true
#define OVER false
#define YES true
#define NO false
using namespace std;
HINSTANCE hApplication;
HBITMAP Bitmap;
char Buffer[30];
class Deck{
public:
    int deck[53];
    Deck(){
        for(int suit = 1; suit <= 4; suit++){
            for(int card = 1; card <= 13; card++){
                deck[((suit-1)*13)+card] = card;
            }
        }
        deck[0] = 0;
    }
};
Deck deck;
class Cards{
private:
    int card_seed;
    int suit_seed;
public:
    int card[11];
    int cards;
    int value[11];
    Cards(){
        fill(card, card + 10, 0);
        fill(value, value + 10, 0);
        cards = 0;
    }
    void DealCard()
    {
        cards++;
        while(!deck.deck[card[cards]]){
            card_seed = rand()%13 + 1;
            suit_seed = rand()%4 + 1;
            card[cards] = (suit_seed - 1)*13 + card_seed;
        }
        deck.deck[card[cards]] = 0;
        if(card_seed > 1 && card_seed < 11){
             value[cards] = card_seed;
        }
        else if(card_seed >= 11 && card_seed <= 13){
            value[cards] = 10;
        }
        else if(card_seed == 1){
            value[cards] = 11;
        }
    }
};
class Player : public Cards {
public:
    float x[11];
    float y[11];
    bool playing;
    bool bust;
    bool win;
    int money;
    Player(const char* Type){
        srand(time(NULL));
        playing = true;
        if(Type == "Dealer"){
            for(int card = 1; card <= 10; card++){
                x[card] = 10 + (card-1)*75;
                y[card] = 200;
            }
        }
        else{
            for(int card = 1; card <= 10; card++){
                x[card] = 10 + (card-1)*75;
                y[card] = 35;
                money = 1000;
            }
        }
    }
    void Reset(){
        cards = 0;
        fill(card, card + 10, 0);
        fill(value, value + 10, 0);
        playing = true;
    }
    int HandValue(){
        int sum = 0;
        for(int current_card = 1; current_card <= cards; current_card++){
            sum += value[current_card];
          }
        if(sum > 21){
            for(int current_card = 1; current_card <= cards; current_card++){
                if(value[current_card] == 11 && sum > 21){
                    value[current_card] = 1;
                    sum = HandValue();
                    break;
                  }
              }
          }
        return sum;
    }
    void Draw(HDC hDC){
        HDC MemoryDevice;
        for(int CardToLoad = 1; CardToLoad <= cards; CardToLoad++){
            Bitmap = LoadBitmap(hApplication, MAKEINTRESOURCE(card[CardToLoad]));
            MemoryDevice = CreateCompatibleDC(hDC);
            SelectObject(MemoryDevice, Bitmap);
            BitBlt(hDC, (int)x[CardToLoad], (int)y[CardToLoad], 75, 100, MemoryDevice, 0, 0, SRCCOPY);
        }
        DeleteDC(MemoryDevice);
    }
};
class CONTROL{
public:
    HWND Handle;
    char* ClassName;
    char* Caption;
    DWORD ClassStyle;
    DWORD ExtendedStyle;
    int x;
    int y;
    int Width;
    int Height;
    int ID;
    bool Enabled;
    void Create(HWND ParentHandle, int x, int y, int Width, int Height, char* Caption){
        Handle = CreateWindowExA(ExtendedStyle, ClassName, Caption, ClassStyle, x, y, Width, Height, ParentHandle, (HMENU)ID, NULL, NULL);
        Enabled = true;
        CONTROL::Caption = Caption;
        CONTROL::x = x;
        CONTROL::y = y;
        CONTROL::Width = Width;
        CONTROL::Height = Height;
    }
    void GetFocus(){
        SetFocus(Handle);
    }
    void Disable(){
        EnableWindow(Handle, FALSE);
        Enabled = false;
    }
    void Enable(){
        EnableWindow(Handle, TRUE);
        Enabled = true;
    }
    void SetText(char* String){
        SetWindowTextA(Handle, String);
    }
};
class BUTTON : public CONTROL {
public:
    BUTTON(int Identifier){
        ClassStyle = BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD;
        ID = Identifier;
        ClassName = "BUTTON";
        ExtendedStyle = 0;
    }
};
class EDIT : public CONTROL {
public:
    EDIT(int Identifier){
        ClassStyle = ES_NUMBER | WS_VISIBLE | ES_CENTER | WS_CHILD | ES_NOHIDESEL;
        ExtendedStyle = WS_EX_CLIENTEDGE;
        ID = Identifier;
        ClassName = "EDIT";
    }
    void Select(int first, int last){
        Edit_SetSel(Handle, first, last);
    }
    int Length(){
        return Edit_GetTextLength(Handle);
    }
    const char* Text(){
        char Buffer[Length() + 1];
        Edit_GetText(Handle, (LPTSTR)&Buffer, Length() + 1);
        string String = Buffer;
        return String.c_str();
    }
};
class STATIC : public CONTROL {
public:
    STATIC() {
        ClassStyle = WS_VISIBLE | SS_CENTER | WS_CHILD;
        ID = 0;
        ClassName = "STATIC";
        ExtendedStyle = 0;
    }
};
Player You("You"), Dealer("Dealer");
BUTTON Ok(ID_OK), Hit(ID_HIT), Stand(ID_STAND);
EDIT Bet(ID_BET);
STATIC BetLabel, GameControls, PlayerLabels, HandValueLabel, YourMoney, MoneyValue, Bust;
class Game{
public:
    bool started;
    Game(){
        started = false;
    }
    void Stop(){
        started = false;
    }
    void ResetGame(HWND hWnd){
        //Reset Players
        You.Reset();
        Dealer.Reset();
        //Reset Controls
        Ok.Enable();
        Bet.Enable();
        Hit.Enable();
        //Reset Hand value
        sprintf(Buffer, "%d", You.HandValue());
        HandValueLabel.SetText(Buffer);
        //Reset deck
        deck = Deck();
        //Stop the game
        started = false;
        //Update the Display
        InvalidateRect(hWnd, 0, TRUE);
        RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
    }
    int SendMessage(HWND hWnd, int ButtonID, unsigned int MESSAGE, int Information, char* _Information){
        return ProcessMessage(hWnd, ButtonID, MESSAGE, Information, _Information);
    }
    int ProcessMessage(HWND hWnd, int ButtonID, unsigned int MESSAGE, int Information, char* _Information){
        switch(MESSAGE)
        {
        case START_GAME:
            //Place Bet
            You.money -= Information;
            started = YES;
            sprintf(Buffer, "%d", You.money);
            //Update Controls
            MoneyValue.SetText(Buffer);
            Ok.Disable();
            Bet.Disable();
            //Deal two cards to player and dealer
            You.DealCard();
            You.DealCard();
            Dealer.DealCard();
            Dealer.DealCard();
            //Update the Hand Value Label
            sprintf(Buffer, "%d", You.HandValue());
            HandValueLabel.SetText(Buffer);
            //Move the label
            MoveWindow(HandValueLabel.Handle, (int)You.x[You.cards] + 80, (int)You.y[You.cards] + 25, 100, 20, TRUE);
            //Send PAINT message
            InvalidateRect(hWnd,0, TRUE);
            RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
            //Check for BlackJacks
            if(You.HandValue() == 21){
                SendMessage(hWnd, 0, INTERNAL, YOU_WIN, "");
            }
            else if(Dealer.HandValue() == 21){
                SendMessage(hWnd, 0, INTERNAL, DEALER_WIN, "");
            }
            break;
        case STAND:
            if(started){
                Hit.Disable();
                You.playing = false;
            }
            break;
        case INTERNAL:
            switch(Information)
            {
            case DEALER_WIN:
                return MessageBoxA(hWnd, "You Loose! \n Play Again ?", "Game Over", MB_YESNO | MB_ICONINFORMATION);
            case YOU_WIN:
                return MessageBoxA(hWnd, "You Win! \n Keep Playing ?", "Game Over", MB_YESNO | MB_ICONINFORMATION);
            }
        break;
        case IDLE:
            if(started){
                //Check for BlackJacks
                if(Dealer.HandValue() == 21){
                    started = false;
                    switch(SendMessage(hWnd, 0, INTERNAL, DEALER_WIN, ""))
                    {
                    case IDYES:
                        ResetGame(hWnd);
                        return 0;
                    case IDNO:
                        exit(0);
                        return 0;
                    }
                }
                if(!You.playing && Dealer.playing && Dealer.HandValue() < You.HandValue())
                    Dealer.DealCard();
                    //Update the Window
                    InvalidateRect(hWnd,0, TRUE);
                    RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
                    //Check for a Bust
                    if(Dealer.HandValue() > 21){
                        switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
                        {
                        case IDYES:
                            ResetGame(hWnd);
                            return 0;
                        case IDNO:
                            exit(0);
                            return 0;
                        }
                    }
                    if(Dealer.HandValue() == 21){
                        switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
                        {
                        case IDYES:
                            ResetGame(hWnd);
                            return 0;
                        case IDNO:
                            exit(0);
                            return 0;
                        }
                    }

                }
        break;
        case HIT:
            //Check to see who's still playing and deal a card to them
            if(started){
            if(You.playing){
                You.DealCard();
                //Update the Hand Value Label
                sprintf(Buffer, "%d", You.HandValue());
                HandValueLabel.SetText(Buffer);
                //Move the label and update the screen
                MoveWindow(HandValueLabel.Handle, (int)You.x[You.cards] + 80, (int)You.y[You.cards] + 25, 100, 20, TRUE);
                InvalidateRect(hWnd, 0, TRUE);
                RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
                //Check for a BlackJack
                if(You.HandValue() == 21){
                    started = false;
                    switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
                    {
                    case IDYES:
                        ResetGame(hWnd);
                        return 0;
                    case IDNO:
                        exit(0);
                        return 0;
                    }
                }
                //Check for a bust
                if(You.HandValue() > 21){
                    started = false;
                    switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
                    {
                    case IDYES:
                        ResetGame(hWnd);
                        return 0;
                    case IDNO:
                        exit(0);
                        return 0;
                    }
                }
            }
            if(Dealer.playing){
                Dealer.DealCard();
                InvalidateRect(hWnd, 0, TRUE);
                RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
                //Check for BlackJack
                if(Dealer.HandValue() == 21){
                    started = false;
                    switch(SendMessage(hWnd, 0, INTERNAL, DEALER_WIN, ""))
                    {
                    case IDYES:
                        ResetGame(hWnd);
                        return 0;
                    case IDNO:
                        exit(0);
                        return 0;
                    }
                }
                //Check for Bust
                if(Dealer.HandValue() > 21){
                    started = false;
                    switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
                    {
                    case IDYES:
                        ResetGame(hWnd);
                        return 0;
                    case IDNO:
                        exit(0);
                        return 0;
                    }

                }
            }
            }
            break;
        }
        return 0;
    }
};
Game game;
#endif

Message Loop

 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, 175, 100, 20, "Dealer:");
      HandValueLabel.Create(hWnd, (int)You.x[You.cards] + 85, 60, 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());
              game.SendMessage(hWnd, ID_OK, START_GAME, bet, "");
          }
          break;
          case ID_HIT:
          {
              //Tell the game that the player wants another card
              game.SendMessage(hWnd, ID_HIT, HIT, 0, "");
          }
          break;
          case ID_STAND:
              game.SendMessage(hWnd, ID_STAND, STAND, 0, "");
          }
      }
      break;
      }
    }
  break;
    default:
    //Default:
    game.SendMessage(hWnd, 0, IDLE, 0, "");
    return DefWindowProcA(hWnd, Msg, wParam, lParam);
    }
  return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文