Okay, so I almost made a blackjack game, then...
I decided to rework my engine LOL. I just started switching things around a bit to model what I think my card game engine should look like. I realize that there are a few key boolean or numerical values that may be used when working out game logic. Things such as, if all bets are going against the house (like in blackjack), or not, (like in poker).
Here is the basis of the system, the Card_Game class.
Code:
#ifndef GAME_H
#define GAME_H
#include <vector>
#include "Player.h"
#include "Hand.h"
#include "Resource_Manager.h"
#include <list>
class Card_Game
{
public:
void init();
void cleanup();
Card_Game();
virtual void turn_logic(std::string player_id);
virtual void menu_logic();
std::vector<std::string> m_vPlayer_List;
private:
int calculate_winnings();
void initialize_players()
{
for(unsigned int loop = 0; loop < m_vPlayer_List.size(); loop++)
{
Player * new_player = new Player(m_vPlayer_List[loop]);
m_rPlayers.manage_resource( m_vPlayer_List[loop], new_player );
}
}
// Give player id a new hand
void give_player_hand(std::string player_id)
{
Hand * p_hand = new Hand();
m_rHands.get_resource(player_id).px->push_back(p_hand);
}
void shuffle_deck(int deck_id)
{
m_vDeck[deck_id]->shuffle_deck();
}
// Draw how_many cards to player id's hand_id from deck_idntyd
void draw_card(std::string player_id, int hand_id, int deck_id, int how_many)
{
for(int loop = 0; loop < how_many; loop++)
{
m_rHands.get_resource(player_id).px->at(hand_id)->add_card(m_vDeck[deck_id]->draw_card());
}
}
void place_bet(std::string player_id, int bet)
{
int * p_bet = &bet;
m_rBets.manage_resource(player_id, &(p_bet));
m_rPlayers.get_resource(player_id).px->m_cash -= bet;
}
// Split player's active hand
void split_hand(std::string player_id, int hand_id)
{
give_player_hand(player_id);
m_rHands.get_resource(player_id).px->back()->add_card(m_rHands.get_resource(player_id).px->at(hand_id)->take_card());
}
// check if hand value > check_value
bool check_hand_value(std::string player_id, int hand_id, int check_value)
{
if (m_rHands.get_resource(player_id).px->at(hand_id)->point_value() > check_value)
{
return true; // hand is over check
}
else
{
return false; // hand is under check
}
}
Resource_Manager< Player > m_rPlayers;
Resource_Manager< std::vector<Hand*> > m_rHands;
Resource_Manager< int* > m_rBets;
Resource_Manager< Deck* > m_rDecks;
std::vector< Deck* > m_vDeck;
};
#endif
Those are all the functions I find pertinent to a blackjack card_game at this point in time, you'll notice what is missing, certain settings like the minimum bet, this internal betting switch I've told you about, and other internal switches that might be needed during runtime.
I may use another resource manager for the job, and create another object called setting. I could derive a few types of settings like an intsetting, bool setting, etc etc.
Then I can populate this list of settings with a virtual card_game constructor, what do you guys think about this solution?
By the way, here is how I've defined the blackjack turn logic, its kindof incomplete at the moment still, but here it is :)
Code:
void Card_Game::turn_logic(std::string player_id)
{
using namespace std;
while(!(cin >> m_result))
{
cin.clear();
cin.ignore();
}
switch(m_result)
{
case 1:
draw_card(player_id, m_rPlayers.get_resource(player_id).px->m_active_hand, 0, 1);
if(check_hand_value(player_id, m_rPlayers.get_resource(player_id).px->m_active_hand, 21))
{
m_rPlayers.get_resource(player_id).px->m_winner = false;
}
break;
case 2: // stay hand
// while dealer has hand value less than 18
while(check_hand_value("Dealer", 0, 18))
{
draw_card("Dealer", 0, 0, 1); // (for dealer draw to 0 hand, from 0 deck, 1 card)
}
// if the dealer goes over 21
if (check_hand_value("Dealer", 0, 21))
{
// player wins
m_rPlayers.get_resource(player_id).px->m_winner = true;
// state_manager->change_state( Deal_State::instance(), game );
}
// if player's hand value is greater than the dealer's
else if( check_hand_value(player_id, m_rPlayers.get_resource(player_id).px->m_active_hand, m_rHands.get_resource("Dealer").px->at(0)->point_value()))
{
// player wins
m_rPlayers.get_resource(player_id).px->m_winner = true;
// state_manager->change_state( Deal_State::instance(), game );
}
else
{
// player loses
m_rPlayers.get_resource(player_id).px->m_winner = false;
// state_manager->change_state( Deal_State::instance(), game );
}
break;
case 3: // double down?
if (m_rHands.get_resource(player_id).px->at(m_rPlayers.get_resource(player_id).px->m_active_hand)->get_size() == 2)
{
//game->m_players[1].bet(game->m_players[1].m_bets[game->m_players[1].m_active_hand]);
draw_card(player_id, m_rPlayers.get_resource(player_id).px->m_active_hand, 0, 1);
if( check_hand_value(player_id, m_rPlayers.get_resource(player_id).px->m_active_hand, m_rHands.get_resource("Dealer").px->at(0)->point_value()))
{
// player wins
m_rPlayers.get_resource(player_id).px->m_winner = true;
// state_manager->change_state( Deal_State::instance(), game );
}
else
{
// player loses
m_rPlayers.get_resource(player_id).px->m_winner = false;
// state_manager->change_state( Deal_State::instance(), game );
}
}
else { break; }
case 4:// split hand
split_hand(player_id, m_rPlayers.get_resource(player_id).px->m_active_hand);
break;
case 5: // fold
// player loses
m_rPlayers.get_resource(player_id).px->m_winner = false;
//state_manager->change_state( Deal_State::instance(), game );
break;
default:// invalid entry
cout << "Please enter 1 or 2.\n";
break;
}
}
Right now state changing has been disabled, this isn't really something I'm worried about at the moment, basically I also need to rethink what should be a gamestate and what shouldn't.