Sign in to follow this  
braclayrab

my first game - blackjack

Recommended Posts

braclayrab    160
I'm using C++ to do my first game. I'm going to try to implement graphics later. Right now I'm just using cout and cin. Anyway, I'm having an issue where my program freezes and I can't discern why. It takes input for the bet and then just quits. I added some output right after the call to makebet() but I never see the output. BTW, I'm also using VC++ Thanks in advance.
#include<iostream.h>
#include <ctime>
#include<cstdlib>



class dealer
{
public:
	void initdealer();			//sets hand to 0
	void initdeck();			//refills deck
	void dlrplay();
	int showhand();
	void dlrcard(int card);		//tallies dlrhand
	int deal();
private:
	int aces;					
	int dlrhand;				//The value of the dealer's hand
	int deck[52];				//The deck will not actually be shuffled and will instead
};								//draw a random card from an 'organized' deck.
								//A card's presence will be held in this array with a 1 meaning
								//the card is still in the deck and a 0 meaning it has aready been dealt
								//it has aready been dealt


class player
{
public:
	player();
	void initplayer();			//sets hand to 0
	int getbet();				//gets wager from player
	void makebet();
	int showhand();
	void plrcard(int card, int whichcard);		//tallies plrhand
	char getplay();				//hit or stay
	char getfirstplay();		//includes the possibility to double-down or split
	void won();
	void lost();
	int getbankroll();
private:
	int aces;
	int plrhand;
	int cardone;				//needed for splitting
	int cardtwo;				//
	int bankroll;
	int bet;
};


main()
{
	char play;

	srand((unsigned)time(0)); 

	dealer dlr;
	player plr;

	plr.makebet();

	cout <<"wtf?";

	while(plr.getbet() != 0)
	{
		dlr.initdealer();
		dlr.initdeck();
		plr.initplayer();

		for(int i=0; i<2; i++)
		{
			plr.plrcard(dlr.deal(),i);
			dlr.dlrcard(dlr.deal());
		}	

		cout << "player shows " << plr.showhand() << endl;

		play = plr.getfirstplay();

		if (play == 'd')
			{
				plr.plrcard(dlr.deal(),2);
			}

		while(play == 'h' && plr.showhand() <= 21)
		{
			play = plr.getplay();
			if (play == 'h')
				plr.plrcard(dlr.deal(),2);
		}

		//if(play == s)
		


		
		dlr.dlrplay();

		if(plr.showhand() > 21)
		{
			cout << "Player shows " << plr.showhand() << "\nYou busted\n";
			plr.lost();
		}
		else if (dlr.showhand() > 21)
		{
			cout << "Dealer shows " << dlr.showhand() << "\nDealer busted\n";
			plr.won();
		}
		else 
		{
			cout<< "Dealer shows " << dlr.showhand() << ".\nPlayer shows " << plr.showhand() << endl;

			if (dlr.showhand() > plr.showhand())
			{
				cout << "You lost...\n";
				plr.lost();
			}
			else if (plr.showhand() > dlr.showhand())
			{
				cout << "You Won!\n";
				plr.won();
			}
			else
			{
			cout << "Push\n";
			}
		}

	plr.makebet();

	}


	return(0);		
}






void dealer::initdealer()
{
	cout << "initdlr\n";
	aces = 0;
	dlrhand = 0;
	cout << "initdealer\n";
}

void dealer::initdeck()
{	
	for(int i=0; i<52; i++)
		deck[i] = 1;
}

void dealer::dlrplay()
{
	while(showhand() < 17)
		dlrcard(deal());
}


int dealer::showhand()
{
	return dlrhand;
}

void dealer::dlrcard(int card)
{
	int suit;
	int value;
	
	suit = 52/card;
	value = 52%card;
	cout <<"Dealer gets " << value << " of " << suit << endl;
	if(value  == 0)
		value = 10;		//this is the king
	if(value > 10)		
		value = 10;		//this is the jack or queen
	else if(value ==1)
	{
		aces++;			//This is the aces.  Aces count as 11 unless that would push 
		value = 11;		//the hand value above 21.  
	}

	if(showhand() > 21 && aces > 0)
	{
		aces--;							//This counts the aces being tallied as 11.  
		dlrhand = dlrhand - 10;			//
	}
}

int dealer::deal()
{

	int i;

	do
	{
		i = 1 + int(52*rand()/(RAND_MAX + 1.0));	
	} while (deck[i] != 0);
	
	deck[i] = 0;		//1 is A of spades, 14 A of diamonds
	return(i);			//27 hearts, 40 clubs.  13 is king of spades.
}







player::player()
{
	bankroll = 100;
}


void player::initplayer()
{
	aces = 0;
	plrhand = 0;
	cardone = 0;
	cardtwo = 0;
}
	
int player::getbet()
{
	return bet;
	cout << "getbet " << bet << endl;
}

void player::makebet()
{
	cout << "How much would you like to bet?(0 to quit)\n";
	cin >> bet;
	cout << "You wagered " << bet << endl;
}

int player::showhand()
{
	return plrhand;
}

void player::plrcard(int card, int whichcard)
{
	int suit;
	int value;
	
	if(whichcard = 0)
		cardone = card;
	else 
		cardtwo = card;
	
	suit = 52/card;
	value = 52%card;

	cout <<"You get " << value << " of " << suit << endl;

	if(value  == 0)
		value = 10;		//this is the king
	if(value > 10)		
		value = 10;		//this is the jack or queen
	else if(value == 1)
	{
		aces++;			//This is the aces.  Aces count as 11 unless that would make 
		value = 11;		//the hand value greater than 21, which is dealt with next.
	}

	if(showhand() > 21 && aces > 0)
	{
		aces--;							//This counts the aces being tallied as 11.  
		plrhand = plrhand - 10;			//
	}
}

char player::getplay()
{
	char ply = 'u';
	while(ply != 'h' || ply != 's')
	{
		cout << "What play? h= hit, s = stay\n";
		cin >> ply;
	}

	return ply;
}

char player::getfirstplay()
{
	char ply = 'u';
	while(ply != 'h' || ply != 's' || ply != 'd' || ply != 'p')
	{
		cout << "What play? h= hit, s = stay, d = double, p = split\n";
		cin >> ply;
	}

	if (ply == 'd')
	{
		bet = 2*bet;
	}
		
	return ply;
}

void player::won()
{
	bankroll = bankroll + bet;
}

void player::lost()
{
	bankroll = bankroll - bet;
}

int player::getbankroll()
{
	return bankroll;
}

Share this post


Link to post
Share on other sites
SirKnight    316
Your problem is in this function: int dealer::deal()

You check while deck[i] is not equal to 0 then loop. Well every single value in deck is a 1 because of the function void dealer::initdeck(). So this will ALWAYS be the case, thus you have an infinite loop.

I would highly suggest to learn how to use the Visual Studio debugger. It's what I used to figure out why your program just sits there. Set a breakpoint at a particular point in your code, hit run then you can step through each line of code with F10. Or if you want to jump inside a function and execute each of its lines, use F11. Anyway, just mess around with it and google for visual studio debugger.


-SirKnight

Share this post


Link to post
Share on other sites
Zahlman    1682
The reason you didn't see the "wtf?" output, BTW (even though there is stuff going on between there and the infinite loop) is that there is no endl. The standard output stream 'cout' is line-buffered by default; so nothing shows up until the next buffer flush ("endl" is a newline and a "flush" combined, basically).

Debugging messages should go to cerr (which does not have this buffering by default), anyway. I am guilty of not practicing what I preach, though. :)

Yeah, you want to loop while deck[i] == 0; that is, keep looping *until* you find a valid card. I am understanding things such that your "deck" is an array of 1 or 0 values indicating whether the card is still there. You also don't want to add 1, because 0 is a valid array index.

This is not very elegant though, especially if you're going to play several games without refreshing the deck. (Or alternatively, think about reusing your "card" code for card games that use the whole deck). And if you run out of cards, there's no check for that, so you find out "the hard way". :)

This page provides some good ideas about the problem of "shuffling". My favourite idea is to do the shuffling "on demand". Here is a sketch of one possible implementation:


class Deck {
vector<char> cards; // values 0 to 51
// I am using the actual card values, rather than assigning
// meaning to array positions. I'm also using a vector to allow
// for "future expansion". And trust me, you want your "card
// values" to start at 0 if you're doing arithmetic to
// translate them.
int num_remaining;

public:
Deck(int num_cards = 52): cards(vector<char>(num_cards)) {
for (int i = 0; i < num_cards; i++) {
cards[i] = i;
}
reset();
}
void reset() {
// Reclaim all cards as being undealt.
num_remaining = cards.size();
// Now, previous getCard() calls may have reordered things
// all over the place, but that doesn't matter for our
// purposes since we're shuffling things anyway - we still
// have all values from 0 to num_cards-1 once each, in
// some order.
}
Card getCard() {
// Deal a random card.
// Here is the tricky part, and what makes 'reset()' work.
// We are going to pick a card index from 0 to
// num_remaining-1, and *swap* it with card num_remaining-1.
// The card that we're "moving to the front" is the dealt
// card; we put the card that was in that spot back into the
// middle of the deck so it can be dealt later.
if (num_remaining == 0) throw OhTehNos();
// OK, so there is at least one card. Choose one of them
int selection = int(rand()/(RAND_MAX / num_remaining));
// Adding 1 to RAND_MAX might not be a good idea, because it
// *could* be int-sized. I think this way works...
std::swap(cards[selection], cards[num_remaining - 1]);
// if that is the same card, that's ok. Yay std::swap.
// Anyway. That cards[num_remaining - 1] is the card we want
num_remaining--;
// Make a Card represented by the number
return Card(cards[num_remaining]);
}
}

Share this post


Link to post
Share on other sites
kSquared    1356
I'm not sure that HN is necessarily a good choice here. Especially for beginners who may be frequently changing data types as they learn how to use the language, Hungarian notation can lead to nightmares of name-changing to reflect the new types. Indeed, a lot of reputable people now say it's a poor design technique because it overemphasizes the importance of a variable's type.

Additionally, since the OP says he has Visual Studio, a lot of the need for HN can be obviated by the IDE. IntelliSense is a good thing.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this