Я изменил способ, которым программа обрабатывает сообщения, и публикую его как отдельный ответ.Это все еще сломано из-за незначительного сбоя, но я думаю, что общая идея является твердой.приветствуются комментарии
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;
}