Blackjack++
  Main Logic  

Main Logic


Includes and defines...
#include <allegro.h>
#include <vector>
#include <sstream>
#include "deck.h"
#include "player.h"
#include "card.h"
#include "button.h"
#include "time.h"

#define AI_X        200
#define AI_Y        20
#define PLAYER_X    200
#define PLAYER_Y    300
#define B_HIT       0
#define B_STAND     1
#define B_NEW       2
#define B_EXIT      3

void init();
void deinit();
Once in main, the program runs init() to initialize and setup Allegro, a graphics library.
int main() {
    init();
After that is finished, it declares all the variables that will be needed during gameplay, such as the Deck, the two Players, the BITMAP buffer, etc.
    std::srand(time(0));        // seed the random generator for shuffling
    std::stringstream ss;       // std::stringstreams are used for num -> text
    Deck deck;
    Player player;
    Player ai;
    BITMAP *buf;  
    BITMAP *bjpplogo;  
    int turn = 0;
    bool done=false;
    bool ai_facedown=true;
    bool finish_game=false;
    bool new_game=true;
    int wins=0;
    int ties=0;
    int losses=0;
    std::vector<Button> buttons;
    
    buf = create_bitmap(SCREEN_W,SCREEN_H);     // Create our bitmap to draw to
    clear_to_color(buf,makecol(0,128,0));       // Clear it to a lovely green
    bjpplogo = load_bitmap("images/bjppsm.bmp",default_palette);
    
    // Initialize the vector of buttons...
    buttons.push_back(Button(buf,"Hit Me",20,300,100,20,makecol(255,255,255),makecol(0,128,0)));
    buttons.push_back(Button(buf,"Stand",20,325,100,20,makecol(255,255,255),makecol(0,128,0)));
    buttons.push_back(Button(buf,"New Game",20,400,100,20,makecol(255,255,255),makecol(0,128,0)));
    buttons.push_back(Button(buf,"Exit",20,425,100,20,makecol(255,255,255),makecol(0,128,0)));
Now we get to the main game loop...
    while (!done) {
              
        // If a new round is starting, we need to shuffle the deck, clean
        // up the player hands, and draw some starting cards  
        if (new_game) {
            deck.shuffle();
            player.clear();
            ai.clear();
            ai_facedown=true;
            new_game=false;
            player.drawCard(&deck,2);
            ai.drawCard(&deck,2);
            turn = 0;
        }
        clear_to_color(buf,makecol(0,128,0));
        if (bjpplogo) blit(bjpplogo,buf,0,0,15,25,bjpplogo->w,bjpplogo->h);
        
        // If a key is pressed, this will grab it. Just checks for ESC to exit.
        if (keypressed()) {
            char k = readkey() >> 8;
            if (k==KEY_ESC)
                done=true;
        }
        
        // Loop through the buttons to update and draw each of them, and react
        // to clicks
        for (int i=0;i<buttons.size();i++) {
            buttons[i].update();
            buttons[i].draw();
            if (buttons[i].isClicked()) {
                switch (i) {
                    case B_HIT:
                        player.drawCard(&deck,1);
                        turn++;
                        break;
                    case B_STAND:
                        player.stand();
                        turn++;
                        break;
                    case B_NEW:
                        new_game=true;
                        break;
                    case B_EXIT:
                        done=true;
                        break;
                }
            }
        }
                
        // Computer's turn... AI stands on 17
        if (turn == 1) {
            if (ai.value()<17) {
                ai.drawCard(&deck,1);
            } else {
                ai.stand();
            }
            turn = 0;
        }
        
        // Make the player stand if they bust
        if (player.value() > 21) {
            player.stand();
        }
        
        // Give the turn back to the computer if the player has stood
        if (turn==0 && player.isStanding()) turn = 1;
        
        // When both are done, finish out the round        
        if (ai.isStanding() && player.isStanding()) {
            finish_game = true;
        }
        
        ss<<"Wins: " << wins;
        textout_centre_ex(buf,font,ss.str().c_str(),70,360,makecol(255,255,255),-1);
        ss.str("");
        ss.clear();
        ss<<"Ties: " << ties;
        textout_centre_ex(buf,font,ss.str().c_str(),70,370,makecol(255,255,255),-1);
        ss.str("");
        ss.clear();
        ss<<"Losses: " << losses;
        textout_centre_ex(buf,font,ss.str().c_str(),70,380,makecol(255,255,255),-1);
        ss.str("");
        ss.clear();
        
        // Draw the player hands
        player.draw(buf,PLAYER_X,PLAYER_Y,false);
        ai.draw(buf,AI_X,AI_Y,finish_game?false:true);
        
        if (finish_game) {
            int outcome = 0; // Outcome: 0 = loss, 1 = win, 2 = tie
            bool p_bj = false;
            bool ai_bj = false;
                        
            // Check for Busting...
            if (ai.value()>21) outcome = 1;
            if (player.value()>21) outcome = 0;
            if (ai.value()>21&&player.value()>21) outcome = 2;
                        
            // otherwise continue...
            if (ai.value()<=21&&player.value()<=21) {
            
                // Checking for blackjacks
                if (player.handSize() == 2 && player.value() == 21) p_bj=true;
                if (ai.handSize() == 2 && ai.value() == 21) ai_bj=true;
                
                // Simple less than comparisons...
                if (player.value() < ai.value()) outcome = 0;
                if (player.value() > ai.value()) outcome = 1;
                if (player.value() == ai.value()) {
                    outcome = 2;                   // Equal so tie unless... 
                    if (p_bj&&!ai_bj) outcome = 1; // only player has a blackjack 
                    if (ai_bj&&!p_bj) outcome = 0; // or only AI has a blackjack
                } 
            }
            
            // Displays the outcome to the user and waits for them to hit "OK"
            Button ok(buf,"Ok",SCREEN_W/2-50,SCREEN_H/2,100,20,makecol(255,255,255),makecol(40,128,128));
            rectfill(buf,SCREEN_W/2-150,SCREEN_H/2-50,SCREEN_W/2+150,SCREEN_H/2+50,makecol(40,128,128));
            rect(buf,SCREEN_W/2-150,SCREEN_H/2-50,SCREEN_W/2+150,SCREEN_H/2+50,makecol(255,255,255));
            switch (outcome) {
                case 0:
                    textout_centre_ex(buf,font,"You lose. Try again!",
                      SCREEN_W/2,SCREEN_H/2-22,makecol(255,255,255),-1);
                    break;
                case 1:
                    textout_centre_ex(buf,font,"You win. CONGRATULATIONS!",
                      SCREEN_W/2,SCREEN_H/2-22,makecol(255,255,255),-1);
                    break;
                case 2:
                    textout_centre_ex(buf,font,"You tied. Try again!",
                      SCREEN_W/2,SCREEN_H/2-22,makecol(255,255,255),-1);
                    break;
            }
            textout_centre_ex(buf,font,"Click OK",SCREEN_W/2,SCREEN_H/2-12,makecol(255,255,255),-1);
            while (!ok.isClicked()) {
                ok.update();
                ok.draw();
                blit(buf,screen,0,0,0,0,buf->w,buf->h);
                rest(1);
            }
            
            // Keeps a record of Player losses, wins, and ties
            if (outcome==0) losses++;
            if (outcome==1) wins++;
            if (outcome==2) ties++;
            finish_game=false;
            new_game=true;
        }
        // Draw the game board to the screen.
        blit(buf,screen,0,0,0,0,buf->w,buf->h);
        rest(1);
    }
And then wrap up main with a deinit() that just clears the keybuffer.
Note: END_OF_MAIN() is an Allegro-specific macro which does not require a semicolon at the end...
    deinit();
    return 0;
}
END_OF_MAIN()
And the init() and deinit() functions that were prototyped earlier.
void init() {
    int depth, res;
    allegro_init();
    depth = desktop_color_depth();
    if (depth == 0) depth = 32;
    set_color_depth(depth);
    res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
    if (res != 0) {
        allegro_message(allegro_error);
        exit(-1);
    }

    install_timer();
    install_keyboard();
    install_mouse();
    enable_hardware_cursor();
    show_mouse(screen);
    set_window_title("Blackjack++");
}

void deinit() {
    clear_keybuf();
}

Stephen Cole - Pitt Community College - December 2006