2
\$\begingroup\$

I recently just finished making this blackjack game using C++ and SDL2. Although this took a lot longer than I expected it to, I feel like I'm getting a good hang of everything. However, this is only my third game and feel like there's bound to be a lot of room for improvement. There's a lot different files for all of the classes so I'm only including the main.cpp and game.cpp files as they have the bulk of the code and the portions that I think would benefit most from a review.

For reference, the Card class has a rank, suit, and discarded bool. The Hand class has a vector of cards, blackjack split and double bools , and an endState enum to determine payout. And the Player class just has a mainHand, splitHand, money and wager variables and a bool for whether their turn is done.

During the beginning of programming the game I did not plan for the ability to split and the player to have two simultaneous hands, so I'm sure some of the split functionality is not as efficient as it could be.

I do have one specific question: There are quite a few situations where I find myself having to use member of members of members. For instance in Game::resetTable() when putting the cards back into the deck I have to use deck_.push_back(player_.mainHand_.cards_[player_.mainHand_.cards_.size() - 1]). Is this just the nature of using classes or would there be a better way of handling this situations?

Besides this, any general feedback on anything that could be improved would be greatly appreciated.

game.h

#pragma once
#include <string>
#include <deque>
#include <random>

#include <SDL_ttf.h>

#include "Texture.h"
#include "Card.h"
#include "Player.h"
#include "Hand.h"
#include "SDLInit.h"


constexpr int SCREEN_WIDTH = 640;
constexpr int SCREEN_HEIGHT = 480;

struct Game
{
    bool paidOut_ = false;
    bool handEnd_ = false;
    bool splitHandTurn_ = false;
    std::deque<Card> deck_;
    Player player_;
    Player dealer_;
    std::string mainHandResult_ = " ";
    std::string splitHandResult_ = " ";

    void reclaimDiscarded();
    void dealerTurn();
    void compareHands(Hand &playerHand, Hand dealerHand);
    void swapCards(Card &a, Card &b);
    void shuffleDeck();
    void resetTable();
    void getCard(Hand &hand);
    void setCards();
    void dealCards();
    void splitCards();
    int getHandValue(Hand hand);
};

struct AssetManager
{
    std::unique_ptr<SDL_Window, sdl_deleter> window_{ SDL_CreateWindow("Blackjack", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN) };
    std::unique_ptr<SDL_Renderer, sdl_deleter> renderer_{ SDL_CreateRenderer(window_.get(), -1, SDL_RENDERER_PRESENTVSYNC) };
    std::unique_ptr<TTF_Font, sdl_deleter> font_{ TTF_OpenFont("resources/opensans.ttf", 20) };
    std::unique_ptr<TTF_Font, sdl_deleter> largeFont_{ TTF_OpenFont("resources/opensans.ttf", 50) };

    SDL_Color whiteFont_ = { 0xff, 0xff, 0xff };
    SDL_Color yellowFont_ = { 0xFF, 0xFF, 0 };
    int fontWrapWidth_ = SCREEN_WIDTH;

    LTexture menuTexture_{ from_surface, renderer_.get(), "resources/menutexture.png" };
    LTexture onePlayerButton_{ from_surface, renderer_.get(), "resources/oneplayer.png" };

    LTexture wagerText_{ from_text, font_.get(), renderer_.get(), "Wager: ", whiteFont_, fontWrapWidth_ };
//just a bunch more textures and text...

    bool buttonIsPressed(SDL_Event const& event, SDL_Rect const& button_rect);
    void endOfHandRender(Game &game);
    void renderTable(Game &game);
};

game.cpp

#include "Game.h"

std::mt19937& random_engine()
{
    static std::mt19937 mersenne(std::random_device{}());
    return mersenne;
}

int getRandomNumber(int x, int y)
{
    std::uniform_int_distribution<> dist{ x,y };
    return dist(random_engine());
}

bool AssetManager::buttonIsPressed(SDL_Event const& event, SDL_Rect const& button_rect)
{
    if (event.type == SDL_MOUSEBUTTONDOWN)
    {
        auto const& mouse_button_event = event.button;
        auto const mouse_position = SDL_Point{ mouse_button_event.x, mouse_button_event.y };
        return (mouse_button_event.button == SDL_BUTTON_LEFT) && SDL_PointInRect(&mouse_position, &button_rect);
    }

    return false;
}

void Game::reclaimDiscarded()
{
    for (size_t i = 0; i < deck_.size(); ++i)
    {
        if (deck_[i].discarded)
        {
            deck_[i].discarded = false;
        }
    }
}

void Game::dealerTurn()
{
    if (getHandValue(dealer_.mainHand_) > 21)
    {
        //don't change if blackjack or bust
        if (player_.mainHand_.endState == Hand::NONE)
        {
            player_.mainHand_.endState = Hand::DEALER_BUST;
        }
        if (player_.splitHand_.endState == Hand::NONE)
        {
            player_.splitHand_.endState = Hand::DEALER_BUST;
        }
        dealer_.turnEnd = true;
        handEnd_ = true;
    }

    if (getHandValue(dealer_.mainHand_) > 16)
    {
        handEnd_ = true;
        dealer_.turnEnd = true;
        return;
    }

    //makes it look like cards are being dealt instead of instant
    SDL_Delay(500);
    getCard(dealer_.mainHand_);
}

void Game::compareHands(Hand &playerHand, Hand dealerHand)
{
    if (getHandValue(playerHand) > getHandValue(dealerHand))
    {
        playerHand.endState = Hand::PLAYER_WON;
    }
    if (getHandValue(playerHand) < getHandValue(dealerHand))
    {
        playerHand.endState = Hand::DEALER_WON;
    }
    if (getHandValue(playerHand) == getHandValue(dealerHand))
    {
        playerHand.endState = Hand::DRAW;
    }
}

void Game::swapCards(Card &a, Card &b)
{
    Card temp = a;
    a = b;
    b = temp;
}

void Game::shuffleDeck()
{
    size_t count = 0;

    while (count < deck_.size())
    {
        int randNum = getRandomNumber(0, deck_.size() - 1);
        swapCards(deck_[count], deck_[randNum]);
        ++count;
    }
}

void Game::resetTable()
{
    //remove cards from hands and mark as discarded
    while (player_.mainHand_.cards_.size() > 0)
    {
        deck_.push_back(player_.mainHand_.cards_[player_.mainHand_.cards_.size() - 1]);
        deck_[deck_.size() - 1].discarded = true;
        player_.mainHand_.cards_.pop_back();
    }
    while (dealer_.mainHand_.cards_.size() > 0)
    {
        deck_.push_back(dealer_.mainHand_.cards_[dealer_.mainHand_.cards_.size() - 1]);
        deck_[deck_.size() - 1].discarded = true;
        dealer_.mainHand_.cards_.pop_back();
    }
    while (player_.splitHand_.cards_.size() > 0)
    {
        deck_.push_back(player_.splitHand_.cards_[player_.splitHand_.cards_.size() - 1]);
        deck_[deck_.size() - 1].discarded = true;
        player_.splitHand_.cards_.pop_back();
    }

    player_.mainHand_.numOfAces_ = 0;
    player_.splitHand_.numOfAces_ = 0;
    player_.mainHand_.canDouble = true;
    player_.splitHand_.canDouble = true;
    player_.turnEnd = false;
    player_.mainHand_.endState = Hand::NONE;
    player_.splitHand_.endState = Hand::NONE;

    dealer_.mainHand_.numOfAces_ = 0;
    dealer_.mainHand_.canDouble = true;
    dealer_.turnEnd = false;

    splitHandTurn_ = false;
    paidOut_ = false;
    handEnd_ = false;

    mainHandResult_ = " ";
    splitHandResult_ = " ";
}

void Game::getCard(Hand &hand)
{
    if (deck_[0].discarded)
    {
        reclaimDiscarded();
        shuffleDeck();
    }

    if (deck_[0].rank_ == Card::ACE)
    {
        ++hand.numOfAces_;
    }

    hand.cards_.push_back(deck_[0]);
    deck_.pop_front();
}

int Game::getHandValue(Hand hand)
{
    int handValue = 0;

    for (size_t i = 0; i < hand.cards_.size(); i++)
    {
        if (hand.cards_[i].rank_ == Card::ACE)
        {
            handValue += 11;
        }
        else if (hand.cards_[i].rank_ == Card::JACK || hand.cards_[i].rank_ == Card::QUEEN || hand.cards_[i].rank_ == Card::KING)
        {
            handValue += 10;
        }
        else
        {
            handValue += hand.cards_[i].rank_ + 1;
        }
    }

    while (handValue > 21 && hand.numOfAces_ > 0)
    {
        hand.numOfAces_ -= 1;
        handValue -= 10;
    }

    return handValue;
}

void Game::setCards()
{
    for (int suit = Card::HEART; suit < Card::NUMBER_OF_SUITS; suit++)
    {
        for (int rank = Card::ACE; rank < Card::NUMBER_OF_RANKS; rank++)
        {
            Card card;
            card.cardClip_ = { rank * 60, suit * 90, 60, 90 };
            card.suit_ = static_cast<Card::CardSuit>(suit);
            card.rank_ = static_cast<Card::CardRank>(rank);
            deck_.push_back(card);
        }
    }
}

void Game::dealCards()
{
    getCard(player_.mainHand_);
    getCard(dealer_.mainHand_);
    getCard(player_.mainHand_);
    getCard(dealer_.mainHand_);
}

void Game::splitCards()
{
    player_.splitHand_.cards_.push_back(player_.mainHand_.cards_[1]);
    player_.mainHand_.cards_.pop_back();
    getCard(player_.mainHand_);
    getCard(player_.splitHand_);
}

void AssetManager::endOfHandRender(Game &game)
{   
    switch (game.player_.mainHand_.endState)
    {
    case Hand::NONE:
        break;
    case Hand::PLAYER_WON:
        game.mainHandResult_ = "YOU WON!";
        break;
    case Hand::DEALER_WON:
        game.mainHandResult_ = "DEALER WON!";
        break;
    case Hand::PLAYER_BUST:
        game.mainHandResult_ = "YOU BUST!";
        break;
    case Hand::DEALER_BUST:
        game.mainHandResult_ = "DEALER BUST";
        break;
    case Hand::BLACKJACK:
        game.mainHandResult_ = "BLACKJACK!!";
        break;
    case Hand::DRAW:
        game.mainHandResult_ = "DRAW!";
        break;
    }
    switch (game.player_.splitHand_.endState)
    {
    case Hand::NONE:
        break;
    case Hand::PLAYER_WON:
        game.splitHandResult_ = "YOU WON!";
        break;
    case Hand::DEALER_WON:
        game.splitHandResult_= "DEALER WON!";
        break;
    case Hand::PLAYER_BUST:
        game.splitHandResult_ = "YOU BUST!";
        break;
    case Hand::DEALER_BUST:
        game.splitHandResult_ = "DEALER BUST!";
        break;
    case Hand::BLACKJACK:
        game.splitHandResult_ = "BLACKJACK!!";
        break;
    case Hand::DRAW:
        game.splitHandResult_ = "DRAW!";
        break;
    }

    if (!game.splitHandTurn_)
    {
        LTexture mainHandResultTexture{ from_text,largeFont_.get(), renderer_.get(), game.mainHandResult_, yellowFont_, fontWrapWidth_ };
        mainHandResultTexture.render(renderer_.get(), SCREEN_WIDTH / 2 - mainHandResultTexture.width_ / 2, SCREEN_HEIGHT / 2 - mainHandResultTexture.height_ / 2);
    }
    else
    {
        LTexture mainHandResultTexture{ from_text, font_.get(), renderer_.get(), game.mainHandResult_, yellowFont_, fontWrapWidth_ };
        LTexture splitHandResultTexture{ from_text, font_.get(), renderer_.get(), game.splitHandResult_, yellowFont_, fontWrapWidth_ };
        mainHandResultTexture.render(renderer_.get(), SCREEN_WIDTH / 2 - mainHandResultTexture.width_ / 2, SCREEN_HEIGHT / 2 - mainHandResultTexture.height_ / 2);
        splitHandResultTexture.render(renderer_.get(), SCREEN_WIDTH - splitHandResultTexture.width_ - 50, SCREEN_HEIGHT / 2 - splitHandResultTexture.height_ / 2);
    }
}

void AssetManager::renderTable(Game &game)
{
    tableTexture_.render(renderer_.get(), 0, 0);

    //display cards in hands
    if (game.player_.mainHand_.cards_.size() > 0)
    {
        for (size_t numCards = 0; numCards < game.player_.mainHand_.cards_.size(); numCards++)
        {
            cardSpriteSheet_.render(renderer_.get(), 285 + (numCards * 20), 315, &game.player_.mainHand_.cards_[numCards].cardClip_);
        }
    }

    if (game.player_.splitHand_.cards_.size() > 0)
    {
        for (size_t numCards = 0; numCards < game.player_.splitHand_.cards_.size(); numCards++)
        {
            cardSpriteSheet_.render(renderer_.get(), 490 + (numCards * 20), 315, &game.player_.splitHand_.cards_[numCards].cardClip_);
        }
    }
    //hide 2nd dealer card until dealer's turn
    if (game.player_.mainHand_.cards_.size() > 0)
    {
        if (!game.player_.turnEnd)
        {
            cardSpriteSheet_.render(renderer_.get(), 280, 48, &game.dealer_.mainHand_.cards_[0].cardClip_);
            backOfCardTexture_.render(renderer_.get(), 280 + 20, 48);
        }
        else
        {
            for (size_t numCards = 0; numCards < game.dealer_.mainHand_.cards_.size(); numCards++)
            {
                cardSpriteSheet_.render(renderer_.get(), 280 + (numCards * 20), 48, &game.dealer_.mainHand_.cards_[numCards].cardClip_);
            }
        }
    }

    hitButton_.render(renderer_.get(), 165, 300);
    standButton_.render(renderer_.get(), 165, 332);
    doubleButton_.render(renderer_.get(), 165, 364);
    splitButton_.render(renderer_.get(), 165, 396);
    dealButton_.render(renderer_.get(), 165, 428);

    handValueTotalText_.render(renderer_.get(), 275, 270);
    handValueTotalText_.render(renderer_.get(), 275, 150);
    wagerText_.render(renderer_.get(), 455, 250);
    moneyText_.render(renderer_.get(), 455, 270);

    //show chip signifying wager has been placed
    if (game.player_.wager_ > 0)
    {
        betChipTexture_.render(renderer_.get(), 395, 247);
    }

    LTexture playerHandValueText_{ from_text, font_.get(), renderer_.get(), std::to_string(game.getHandValue(game.player_.mainHand_)), whiteFont_, fontWrapWidth_ };
    playerHandValueText_.render(renderer_.get(), 275 + handValueTotalText_.width_ + 2, 270);

    LTexture playerMoneyTotalText_{ from_text, font_.get(), renderer_.get(), std::to_string(game.player_.moneyValue_ - game.player_.wager_), whiteFont_, fontWrapWidth_ };
    playerMoneyTotalText_.render(renderer_.get(), 455 + moneyText_.width_, 270);

    LTexture playerWagerValueText_{ from_text, font_.get(), renderer_.get(), std::to_string(game.player_.wager_), whiteFont_, fontWrapWidth_ };
    playerWagerValueText_.render(renderer_.get(), 455 + wagerText_.width_, 250);

    //only show dealer hand value after player stands or busts
    if (game.player_.turnEnd)
    {
        LTexture dealerHandValueText__{ from_text, font_.get(), renderer_.get(), std::to_string(game.getHandValue(game.dealer_.mainHand_)), whiteFont_, fontWrapWidth_ };
        dealerHandValueText__.render(renderer_.get(), 275 + handValueTotalText_.width_ + 2, 150);
    }
}

main.cpp

#include <iostream>
#include <vector>
#include <random>
#include <string>
#include <deque>

#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>

#include "SDLInit.h"
#include "Texture.h"
#include "Game.h"
#include "Card.h"
#include "Player.h"
#include "Hand.h"

enum class GameState
{
    MAIN_MENU,
    WAGER,
    GAME_LOOP,
    SPLIT,
    PLAY_AGAIN,
    EXIT,
};

bool playAgain_render(Game& game, AssetManager& assets)
{
    SDL_RenderClear(assets.renderer_.get());
    assets.menuTexture_.render(assets.renderer_.get(), 0, 0);
    assets.youRanOutofMoneyText_.render(assets.renderer_.get(), SCREEN_WIDTH / 2 - assets.youRanOutofMoneyText_.width_ / 2, 100);
    assets.playAgainText_.render(assets.renderer_.get(), SCREEN_WIDTH / 2 - assets.playAgainText_.width_ / 2, 160);
    assets.yesButton_.render(assets.renderer_.get(), SCREEN_WIDTH / 2 - assets.yesButton_.width_ / 2, 200);
    assets.noButton_.render(assets.renderer_.get(), SCREEN_WIDTH / 2 - assets.noButton_.width_ / 2, 235);

    SDL_RenderPresent(assets.renderer_.get());
    return true;
}
bool playAgain_update()
{
    return true;
}
bool playAgain_input(GameState& gameState, Game& game, AssetManager& assets)
{
    SDL_Event e;

    while (SDL_PollEvent(&e) != 0)
    {
        if (e.type == SDL_QUIT)
        {
            gameState = GameState::EXIT;
            return false;
        }
        if (assets.buttonIsPressed(e, assets.yesButton_.button_))
        {
            game.player_.moneyValue_ = 100;
            game.resetTable();
            gameState = GameState::WAGER;
            return false;
        }
        else if (assets.buttonIsPressed(e, assets.noButton_.button_))
        {
            gameState = GameState::EXIT;
            return false;
        }
    }

    return true;
}

bool split_render(Game& game, AssetManager& assets)
{
    SDL_RenderClear(assets.renderer_.get());
    assets.renderTable(game);
    assets.endOfHandRender(game);

    SDL_Rect currentHandOutLineRect;
    if (!game.splitHandTurn_)
    {
        currentHandOutLineRect = { 275, 305, 80, 110 };
    }
    else
    {
        currentHandOutLineRect = { 480, 305, 80, 110 };
    }
    SDL_SetRenderDrawColor(assets.renderer_.get(), 0xFF, 0x00, 0x00, 0xFF);
    SDL_RenderDrawRect(assets.renderer_.get(), &currentHandOutLineRect);

    assets.handValueTotalText_.render(assets.renderer_.get(), 475, 420);

    LTexture playerSplitHandValueText__{ from_text, assets.font_.get(), assets.renderer_.get(), std::to_string(game.getHandValue(game.player_.splitHand_)), assets.whiteFont_, assets.fontWrapWidth_ };
    playerSplitHandValueText__.render(assets.renderer_.get(), 475 + assets.handValueTotalText_.width_ + 2, 420);

    SDL_RenderPresent(assets.renderer_.get());
    return true;
}
bool split_update(GameState& gameState, Game& game, AssetManager& assets)
{
    if (!game.splitHandTurn_)
    {
        if (game.player_.mainHand_.hasBlackjack())
        {
            game.player_.mainHand_.endState = Hand::BLACKJACK;
            game.splitHandTurn_ = true;
        }
        else if (game.getHandValue(game.player_.mainHand_) > 21)
        {
            game.player_.mainHand_.endState = Hand::PLAYER_BUST;
            game.splitHandTurn_ = true;
        }
    }
    else
    {
        if (game.player_.splitHand_.hasBlackjack())
        {
            game.player_.splitHand_.endState = Hand::BLACKJACK;
            if (game.player_.mainHand_.endState == Hand::NONE)
            {
                game.player_.turnEnd = true;
            }
            //if both hands blackjack or bust just skip dealer turn
            else
            {
                game.handEnd_ = true;
            }
        }
        else if (game.getHandValue(game.player_.splitHand_) > 21)
        {
            game.player_.splitHand_.endState = Hand::PLAYER_BUST;
            if (game.player_.mainHand_.endState == Hand::NONE)
            {
                game.player_.turnEnd = true;
            }
            else
            {
                game.handEnd_ = true;
            }
        }
    }

    if (game.player_.turnEnd)
    {
            game.dealerTurn();
    }

    if (game.player_.turnEnd && game.dealer_.turnEnd)
    {
        if (game.player_.mainHand_.endState == Hand::NONE)
        {
            game.compareHands(game.player_.mainHand_, game.dealer_.mainHand_);
        }
        if (game.player_.splitHand_.endState == Hand::NONE)
        {
            game.compareHands(game.player_.splitHand_, game.dealer_.mainHand_);
        }
        game.handEnd_ = true;
    }

    if (game.handEnd_ && !game.paidOut_)
    {
        game.player_.updateMoney(game.player_.mainHand_);
        game.player_.updateMoney(game.player_.splitHand_);
        game.paidOut_ = true;

        //remember previous wager unless it is more money than the player has 
        if (game.player_.wager_ > game.player_.moneyValue_)
        {
            game.player_.wager_ = 0;
        }

        gameState = GameState::WAGER;
        return false;
    }

    return true;
}
bool split_input(GameState& gameState, Game& game, AssetManager& assets)
{
    SDL_Event e;

    while (SDL_PollEvent(&e) != 0)
    {
        if (e.type == SDL_QUIT)
        {
            gameState = GameState::EXIT;
            return false;
        }

        if (assets.buttonIsPressed(e, assets.hitButton_.button_) && !game.player_.turnEnd)
        {
            if (!game.handEnd_)
            {
                if (!game.splitHandTurn_)
                {
                    game.getCard(game.player_.mainHand_);
                    game.player_.mainHand_.canDouble = false;
                }
                else
                {
                    game.getCard(game.player_.splitHand_);
                    game.player_.mainHand_.canDouble = false;
                }
            }
        }
        else  if (assets.buttonIsPressed(e, assets.standButton_.button_) && !game.handEnd_)
        {
            if (!game.splitHandTurn_)
            {
                game.splitHandTurn_ = true;
            }
            else
            {
                game.player_.turnEnd = true;
                game.player_.splitHand_.canDouble = false;
            }
        }
        else if (assets.buttonIsPressed(e, assets.doubleButton_.button_) && !game.handEnd_ && game.player_.mainHand_.canDouble)
        {
            if (game.player_.wager_ * 2 <= game.player_.moneyValue_)
            {
                game.player_.wager_ *= 2;

                if (!game.splitHandTurn_ && game.player_.mainHand_.canDouble)
                {
                    game.getCard(game.player_.mainHand_);
                    game.splitHandTurn_ = true;
                }
                else if (game.splitHandTurn_ && game.player_.splitHand_.canDouble)
                {
                    game.getCard(game.player_.splitHand_);
                    game.player_.turnEnd = true;
                }
            }
        }
        else if (assets.buttonIsPressed(e, assets.dealButton_.button_) && game.handEnd_)
        {
            gameState = GameState::GAME_LOOP;
            game.resetTable();
            return false;
        }
    }

    return true;
}

bool gameLoop_render(Game& game, AssetManager& assets)
{   
    SDL_RenderClear(assets.renderer_.get());
    assets.renderTable(game);
    assets.endOfHandRender(game);
    SDL_RenderPresent(assets.renderer_.get());
    return true;
}
bool gameLoop_update(GameState& gameState, Game& game, AssetManager& assets)
{
    if (game.dealer_.mainHand_.hasBlackjack())
    {
        game.player_.turnEnd = true;

        if (game.player_.mainHand_.hasBlackjack())
        {
            game.player_.mainHand_.endState = Hand::DRAW;
        }
        else
        {
            game.player_.mainHand_.endState = Hand::DEALER_WON;
        }
        game.handEnd_ = true;

        //delay so there is a reveal
        SDL_Delay(500);
    }
    else if (game.player_.mainHand_.hasBlackjack())
    {
        game.player_.mainHand_.endState = Hand::BLACKJACK;
        game.handEnd_ = true;
    }
    else if (game.getHandValue(game.player_.mainHand_) > 21)
    {
        game.player_.mainHand_.endState = Hand::PLAYER_BUST;
        game.handEnd_ = true;
    }
    else if (game.player_.turnEnd)
    {
        game.dealerTurn();
    }

    //if no one has blackjack or bust
    if (game.player_.turnEnd && game.dealer_.turnEnd && game.player_.mainHand_.endState == Hand::NONE)
    {
        game.compareHands(game.player_.mainHand_, game.dealer_.mainHand_);
        game.handEnd_ = true;
    }

    if (game.handEnd_ && !game.paidOut_)
    {
        game.player_.updateMoney(game.player_.mainHand_);
        game.paidOut_ = true;

        //remember previous wager unless it is more money than the player has 
        if (game.player_.wager_ > game.player_.moneyValue_)
        {
            game.player_.wager_ = 0;
        }

        gameState = GameState::WAGER;
        return false;
    }

    return true;
}
bool gameLoop_input(GameState& gameState, Game& game, AssetManager& assets)
{
    SDL_Event e;

    while (SDL_PollEvent(&e) != 0)
    {
        if (e.type == SDL_QUIT)
        {
            gameState = GameState::EXIT;
            return false;
        }
        else if (assets.buttonIsPressed(e, assets.hitButton_.button_) && !game.player_.turnEnd)
        {
            if (!game.handEnd_)
            {
                game.getCard(game.player_.mainHand_);
                game.player_.mainHand_.canDouble = false;
            }
        }
        else  if (assets.buttonIsPressed(e, assets.standButton_.button_) && !game.handEnd_)
        {
            game.player_.turnEnd = true;
            game.player_.mainHand_.canDouble = false;
        }
        else if (assets.buttonIsPressed(e, assets.doubleButton_.button_) && !game.handEnd_ && game.player_.mainHand_.canDouble)
        {
            if (game.player_.wager_ * 2 <= game.player_.moneyValue_)
            {
                game.getCard(game.player_.mainHand_);
                game.player_.turnEnd = true;
                game.player_.wager_ *= 2;
            }

        }
        else if (assets.buttonIsPressed(e, assets.splitButton_.button_) && game.player_.mainHand_.canSplit())
        {
            if (game.player_.wager_ * 2 <= game.player_.moneyValue_)
            {
                gameState = GameState::SPLIT;
                game.player_.wager_ *= 2;
                return false;
            }
        }
        else if (assets.buttonIsPressed(e, assets.dealButton_.button_) && game.handEnd_)
        {
            game.resetTable();
            game.dealCards();
        }
    }

    return true;
}

bool wager_render(GameState &gameState, Game &game, AssetManager& assets)
{
    //render logic...
    return true;
}
bool wager_update(GameState &gameState, Game &game)
{
    if (game.player_.moneyValue_ == 0)
    {
        gameState = GameState::PLAY_AGAIN;
        return false;
    }

    return true;
}
bool wager_input(GameState& gameState, Game& game, AssetManager& assets)
{
    SDL_Event e;

    while (SDL_PollEvent(&e) != 0)
    {
        if (e.type == SDL_QUIT)
        {
            gameState = GameState::EXIT;
            return false;
        }
        //player must wager at least 1 money
        else if (assets.buttonIsPressed(e, assets.dealButton_.button_) && game.player_.wager_ > 0)
        {
            gameState = GameState::GAME_LOOP;
            game.resetTable();
            return false;
        }
        else if (assets.buttonIsPressed(e, assets.chip1_.button_))
        {
            //can not wager more than they have
            if (game.player_.wager_ + 1 <= game.player_.moneyValue_)
            {
                game.player_.wager_ += 1;
            }
        }
        else if (assets.buttonIsPressed(e, assets.chip5_.button_))
        {
            if (game.player_.wager_ + 5 <= game.player_.moneyValue_)
            {
                game.player_.wager_ += 5;
            }
        }
        else if (assets.buttonIsPressed(e, assets.chip25_.button_))
        {
            if (game.player_.wager_ + 25 <= game.player_.moneyValue_)
            {
                game.player_.wager_ += 25;
            }
        }
        else if (assets.buttonIsPressed(e, assets.chip50_.button_))
        {
            if (game.player_.wager_ + 50 <= game.player_.moneyValue_)
            {
                game.player_.wager_ += 50;
            }
        }
        else if (assets.buttonIsPressed(e, assets.resetWagerButton_.button_))
        {
            game.player_.wager_ = 0;
        }
    }

    return true;
}

bool mainMenu_render(AssetManager& assets)
{
    //render logic
    return true;
}
bool mainMenu_update()
{

    return true;
}
bool mainMenu_input(GameState& gameState, AssetManager& assets)
{
    //input logic
    return true;
}

int main(int argc, char* args[])
{
    //initialize sdl systems
    sdl sdlinit;
    sdl_img img;
    sdl_ttf ttf;

    GameState gameState = GameState::MAIN_MENU;
    Game game;
    AssetManager assets;
    game.setCards();
    game.shuffleDeck();

    while (gameState != GameState::EXIT)
    {
        switch (gameState)
        {
            case GameState::MAIN_MENU:
            {
            while (mainMenu_input(gameState, assets) &&
                mainMenu_update() &&
                mainMenu_render(assets))
            {}
            break;
            }
            case GameState::WAGER:
            {
                while (wager_input(gameState, game, assets) &&
                    wager_update(gameState, game) &&
                    wager_render(gameState, game, assets))
                {}
                break;
            }
            case GameState::GAME_LOOP:
            {
                game.dealCards();

                while (gameLoop_input(gameState, game, assets) &&
                    gameLoop_render(game, assets) &&
                    gameLoop_update(gameState, game, assets))
                {}
                break;
            }
            case GameState::SPLIT:
            {
                game.splitCards();

                while (split_input(gameState, game, assets) &&
                    split_render(game, assets) &&
                    split_update(gameState, game, assets))
                {}
                break;
            }
            case GameState::PLAY_AGAIN:
            {
            while (playAgain_input(gameState, game, assets) &&
                playAgain_update() &&
                playAgain_render(game, assets))
            {}
            break;
            }
        }
    }
    return 0;
}

Here's a list to github with all of the source code if needed.

\$\endgroup\$
  • \$\begingroup\$ You should include your Card, Hand and Player classes too. The idea is to provide a minimal working program (so a main() is required too) the reviewer can use to test your program and his own modifications \$\endgroup\$ – papagaga Oct 15 '18 at 9:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.