basic blackjack game in C++ ...help?

Started by
8 comments, last by andrewk3652 19 years, 4 months ago
EDIT: new code in a newer post below -------------------------- I have to make a blackjack game for my intro to C++ class, but I couldn't afford to buy a textbook, and I may have missed some class discussions that would have helped me out with this. I haven't started coding the main program yet, but I was hoping that one of you kind souls might be willing to look at my classes at least and tell me if I'm heading in the right direction. I know very little about C++, so any advice anyone has, especially about how to make a deal function, would be appreciated. -------

class Card
{
private:
	char face;
	char suit;
	int value;
public:
	Card();
	void getcard(char face, char suit, int value);
	void getvalue(int value);
	bool ace(char face);
};   
--------- this is my card class. teacher's instructions were: The Card class should have at least the following functions: · An appropriate constructor function. · A mutator function for setting the type of card (e.g., A, 2, …) · An accessor function that returns the integer value of the card. · A function that returns a Boolean value (true or false) depending on whether the current card object is an ace or not. -----

class Hand
{
private:
	int handvalue;
	int carsdealt;
	
public:
	Hand();
	void gethandvalue(int handvalue);
	void deal();
	void hit();
	void display(int handvalue);
};
------ hand class. teacher's instructions: Develop a class that represents a “hand” of up to 5 cards. This class should maintain: · An integer variable representing the number of cards dealt to the hand. · Five Card objects, created from the Card class defined above. · An integer variable representing the value of the hand (i.e., the sum of the card values). The Hand class should have at least the following functions: · An appropriate constructor function. · An accessor function that returns the value of the hand. · A function that deals the first two cards. · A function that deals a single card when a “hit” is requested. · A function to display the hand to the user. Thanks in advance. [Edited by - pg043 on December 8, 2004 11:31:16 AM]
Advertisement
Remove the semicolon after class Card;. Thats shouldn't be there, and wont compile.

Quote:
A mutator function for setting the type of card (e.g., A, 2, …)


You dont seem to have this at all. Unless getcard(..) should be named setcard(..) (after all, it wouldn't make much sense to have a getcard function which you have to pass details of the card into).

Quote:
An accessor function that returns the integer value of the card.

void getvalue(int value);


So how exactly is this function going to return the value of the card? And what value are you going to be passing it?

Quote:
A function that returns a Boolean value (true or false) depending on whether the current card object is an ace or not.

bool ace(char face);


Why do you need to pass face into this function? Doesn't the card know what face it is?

This is all pretty basic stuff. If you cant afford a text book try the library, or a google search. Theres tons of introductory information available on the internet.

Alan
"There will come a time when you believe everything is finished. That will be the beginning." -Louis L'Amour
OK - here goes:

Quote:
An appropriate constructor function


You've got the basis of a constructor (ctor) function there; I just think you need to think about how to build it. When you create a new card, do you want to create a blank card and then use mutators to specify it's type? Or would you rather create the card and its data-members all in one go. If it's the second, then you need some parameters in the ctor function.

[qoute]
A mutator function for setting the type of card (e.g., A, 2, …)


I think this is what you're trying to do with your getvalue function. A mutator is normally called 'Set...', not 'Get...' (that's an accessor). There are a number of ways you could do this. You could do each data-member one at a time, or do all 3 at once. It looks like the way you're planning on doing this is all 3 at once; just need to write the function body now!

Quote:
An accessor function that returns the integer value of the card.


Again, I assume this is your getvalue function. Quick question : why do you need 'int value' as a parameter to this function? What is it doing?

Quote:
A function that returns a Boolean value (true or false) depending on whether the current card object is an ace or not


And this is your ace function, yeah? Again, I think you need to think about what the parameter is doing in the function call.

I'm going to help out a little bit here (although I'm not going to give you an exact answer). When you declare / define a function, you've got the following parts:

return-type function-name ( parm-type1 parm-name1, parm-type2 parm-name2 , ...)

I'm fairly sure you've got your head around the return-type for the function (your use of bool for the ace function suggests you have). The function-name is the obvious bit. The parameters (which are pairs of parm-type and parm-name) are pieces of information you are giving to the function to help it carry out that function's task. So, for example, when you're writing an accessor, we need to think about what task that function is performing. In the case of an accessor, all we want it to do is to provide a piece of information held inside the object. So - when you call that function, do you need to provide the function (and therefore the object, as it's a member function of that object) any more information?

The next step is providing some function bodies. Once you've done that, we can see if this is all going to work, and then see how to add extra functionality (like deal!).

As an overall comment, this appears to me to be a wierd way to do a blackjack game (not sure why you'd want mutators, for example - unless you're planning on cheating and making all your cards aces!).

Hope this helps somewhat, and isn't too confusing!
Jim.
I just got done (a month or so ago) doing a text based blackjack game in Java. The two languages are pretty similar, and aside from the interface there's not much in there that couldn't be replicated into C++, so maybe you could get some ideas from that (though please don't plaigerise, this is for school, be honest :-) ).

http://www.aklabs.net/index.php?akp=development&cat=3

The source code and documentation for it are linked to from that page. Feel free to use whatever from that is useful. let me know if it helped you out.

(some explanation of things I did that might help you specifically)

I designed Card objects so that they were objects with a single index (from 0 to the maximum passed to the Deck class's constructor (usually 52), discussed later). This index has various calculations performed on it to return its face value (2, 3, 10, ace, etc), to return its actual index (0-maximum), or to return a string representation of it ("Ace of Hearts" for example).

The Deck was designed as an object containing a Stack object and an ArrayList object (a linked list with random access functions). The constructor was passed a single value, the number of cards you wanted to have in the deck (for the purpose of my game 52 was always passed). New cards from 0-max are created and put into the list; then they are drawn at random and added to the stack, in order to shuffle them, until the list is empty. The deck has functions for combining the pile and shuffling the deck, adding a player's discarded card to the pile, and dealing a new card from the top of the stack.

Hand objects were designed to be able to hold cards, discard cards, and take cards. The only real functions they needed were to take cards, discard cards, and return the values of their totals. I gave the handTotal() function a boolean argument for whether or not you wanted the actual total (e.g., player is showing his cards, or for interal game calculations of bust and such) or just the total of the cards he was showing. Then there was a function to fold the hand (discarding all cards to the pile).

GamePlayer and GameDealer objects are pretty self explanatory. They have a hand each, and they perform blackjack specific operations on those hands. The only difference between the two is that GameDealer doesn't bet or fold and has an AI routine.

The interface on mine is slightly complex and could've been made easier to read, but that class was being written to work, not to be read by others. Enjoy it if you can understand it. :-)

The main game loop, all it really needs to do is grab the input from the user, determine what they want to do, apply that to the rules of the game, and perform the required operations. Or, more appropriately, tell the appropriate objects - the deck, the player, or the dealer - what the player is trying to do, and let them handle it.

Hope this helped out. Good luck
=========================Buildium. Codium. Fragium.http://www.aklabs.net/=========================
I can give you some tips since i have just completed a hi-lo game for a degree module. We had to program a full deck (without jokers) in a perfectly object oriented angle.

1. Dont worry about certain cards having certain face values, like AJQK. For now program everything in numbers. This makes it easier for comparison etc.

2. Classes u will need:

Card
Deck
Player
Dealer
Table
Game

3. For the deck created a static array of pointers to the Card class:

Card* pCards[52];

This means u can manage your cards on the heap and then as a dealer would move the cards from the deck to hand to table, u can effectively do the same, by just moving the pointer.

4. NO literals

int numberCards = 52; // BAD - What does 52 mean? what if you wanted to include jokers, u'd have to go thru the entire app changing all 52s to 54s or 56s.

do this:

const unsigned int NUMBER_OF_CARDS = 52;

unsigned int numberCards = NUMBER_OF_CARDS;

5. Might help to research a bit of UML to help get ur head around the class structure of the app.

6. A table class can do the conversion from 1 to Ace when u view the table.

7. In the Game class write a FSM (Finite State Machine). This simply means have a class that has a currentState, define some states and do a simple switch inside a game loop that runs certain parts of the app depending on what state its running in.
This makes it easier if u want to restart the game because u can create a restart state that handles everything for you.

8. For the card class u will need a default constructor with no params, but u could also have a constructor that accepts the parameters Value and Suit. This could mean that u can't create a card without setting the values.

9. In the game loop you should only ever be asking the Dealer, Player and the table to do anything. Like:

pDealer->DealCard();
pTable->DisplayTable();
pPlayer->TakeGo();

This opens up the whole idea of encapsulation/reusability and just OO in general.

This way makes the logic of the game incredibly easy to encode.

Hope this helps

ace
Quote:6. A table class can do the conversion from 1 to Ace when u view the table.


Actually I disagree. Mainly in that you should be checking aces when totaling the player's hand for any reason - whether it's to check for 21/bust, or to compare for winners. Your comparison function needs to be smart enough to know how to use the Ace in the hand, too - using it as a 1 and an 11. I did this by keeping track of how many aces were in the hand while looping through the hand, and then calculating each ace depending on the current total, after I'd done all the other cards.

I also don't agree with using a global constant for setting the size of the deck; this should be passed to the deck as a constructor argument. This way, you can use your deck class again later no matter what game it's in (as some games use decks of different sizes), or at least extend its basic functionality into subclasses (RumDeck, GoFishDeck, etc etc etc). And you can do it without using a global to define a class member's size (which, in my opinion, goes against OO anyways).

I don't really see a need for a Table object, as much as for an interface class that will handle all your update calls generically - paint the screen, update it with the player's cards, etc etc. This'll take the junk of displaying out of your main loop and let it focus on the logic (rules) of the game. The only thing I found that I needed to keep track of related to the table was how many games the player had won at the current table.

// ------------- things I noticed in particular about your code

If you're going to use a Card constructor with no parameters, then you should have a static variable inside the constructor that tells what card comes next in the logical progression. This way you won't break your code by accidentally not providing an argument. (This is a better method anyway, in my opinion - your deck constructor can just keep calling = new Card() on objects up until it reaches the size of the deck and you don't have to worry about your loop counting logic being wrong.)

With your Card class, what I would do is define a constant inside of that class (or global or something) that is an array of faces and values. That's what I did in my game; there were two arrays consisting of the face ("Two", "Three", "Ace", etc) and then the Suit. The modulo of the index by the faces array provides the char representation of the card's face, and index/faces.length provides the suit. This way you only have to store one copy of the faces/suits in memory, and you don't have to pass them to each card; you can have the cards handle their own descriptions and remove yourself from the equation, not to mention use less memory.

You shouldn't really need a function to return whether or not the card is an ace; this should be irrelevant, and if it is relevant it will be obvious if its value is 1 or if its value is 11 and its face is "Ace". (Though a simple distinction between 1 and 11, regardless of the face value, should be sufficient for whatever you're doing with it.) Tell your instructor I said he's overcomplicating things. :-)

Your hand class's requirements don't jive with me. Why does he want you to write two separate functions to do the same thing - take cards? Just write one hit function, and pass it a Card object. If you need to deal the initial two cards, just call it twice. Be sure to pass it a Card object from the Deck, otherwise you run the risk of duplicating cards (the game won't be very true if both players somehow wind up holding the Ace of Spades).
=========================Buildium. Codium. Fragium.http://www.aklabs.net/=========================
Well, I did a lot of research and this is where I'm at with it so far.

//blackjack.cpp#include <iostream>using namespace std;#include <ctime>#include <cstdlib>#include "Card.h"#include "Hand.h"int main(){int menuChoice, handValue;Hand h;	h.deal();	handValue=h.getHandValue();	h.display();do	{	cout<<"\n\n\nWhat would you like to do?"		<<endl		<<"\t1. Hit"		<<endl		<<"\t2. Stay"		<<endl;	cin>>menuChoice;				switch(menuChoice)		{		case 1:			h.hit();		case 2:			h.results(handValue);				default:			cout<<"Invalid selection.\n\n";		}				}while(menuChoice > 0 && menuChoice < 3);	return 0;}


I know it doesn't have many options, but the real purpose of this project is just to create proper card and hand classes.

//Hand.hclass Hand{private:	int cardsDealt;	int handValue;	Card card[5];public:	Hand();		int deal();	int hit();	int getHandValue();	void display();	void results(int handValue);	};Hand::Hand(){	}Hand::deal(){	srand((unsigned)time(0));	card[0].value=rand() % 13;	card[1].value=rand() % 13;	cardsDealt=2;		return 0;}Hand::hit(){	int i=cardsDealt;		card.value=rand() % 13;	cardsDealt++;	return 0;}Hand::getHandValue(){	int handValue=card[0].value+card[1].value+card[2].value+card[3].value+card[4].value;	return handValue;}void display(){			cout<<"\n\nYour Hand is:  "    		<<card[0].face<<"  "         //this section is giving me errors		<<card[1].face<<"  "         //when i try to build it.		<<card[2].face<<"  "        //i'm not sure if this is proper		<<card[3].face<<"  "        //syntax, but i thought it would 		<<card[4].face;             //work because i was using                                            //card[1].value and it compiled OK}void results(){	Hand handValue;	cout<<"Your final hand is ";		}


This class, I know, is also not completely finished. I've not yet coded a way to record the dealer's score and all that.

//Card.hclass Card{private:			public:	Card();	int setCard(char face, int value);	int getValue();	int value;	char face;	};Card::Card(){	value=0;	face=0;}Card::setCard(char face, int value){	char J,Q,K,A;	int handValue;	switch(face, value)	{	case 0:		value=2;		face=2;	case 1:		value=3;		face=3;	case 2:		value=4;		face=4;	case 3:		value=5;		face=5;	case 4:		value=6;		face=6;	case 5: 		value=7;		face=7;	case 6:		value=8;		face=8;	case 7:		value=9;		face=9;	case 8:		value=10;		face=10;	case 9:		value=10;		face=J;	case 10:		value=10;		face=Q;	case 11:		value=10;		face=K;	case 12:		if(handValue<=21)			value=11;		else			value=1;		face=A;    }	return 0;}Card::getValue(){	return value;}


My main question is the comment I added in Hand.h, so if anyone could point out my mistake I would appreciate it. This is my first OO program, and I know that I'm probably going about it backwards. Thanks



A brief tutorial on declarations, definitions and member & non-member functions:
class Class{	public:		returnType memberFunction(parameter)		{			// code		}};

This is a combined class and class member function definition. It contains the definition of the class and the definition of the class member function in one place.

class Class{	public:		returnType memberFunction(parameter);};returnType Class::memberFunction(parameter){	// code}

This is a class definition followed by a seperate class member function definition. The class definition contains only the declaration of the member function - the definition for the member function is given outside the class definition.

class Class{	public:		returnType memberFunction(parameter);};returnType memberFunction(parameter){	// code}

This is a class definition followed by a non-member function definition. The class definition contains only the declaration of the member function - the definition for the member function is not included in this code snippet. The function definition at the bottom of the code is a seperate function and has nothing to do with the class member function, despite sharing the same name and prototype.

Compare this to your definitions of Hand and its member functions.

Enigma
Are you saying that my writing "Hand::getValue()" is the wrong syntax for a member function definition? Sorry to seem dull, I've just really never done OO and I don't know the proper syntax for sure.
C++ can be a bit confusing at first.

First off, your class methods (functions inside the class) are jacked up. Specifically, the definitions do not match the declarations. Take the following code snippet:

class Hand{// data members snipped for brevitypublic:	Hand();		int deal();        //snip};Hand::Hand(){// snip}Hand::deal(){// snip}


See, your definition and declaration of the Hand constructor is good - it takes no arguments, is public and has no return type. So therefore
Hand::Hand()
is the proper way to begin the definition of the function (the definition being where the actual code lies). However, you've declared deal as a public function that returns an integer, and takes no arguments. However, you've got it defined as a public function of Hand that takes no arguments and returns nothing; this is no good. When the compiler reaches this function, it says "Hey wait a minute - the Hand class doesn't have a member function deal() that doesn't return anything. Let me schmack the programmer." There's other cases in your code where you've not only missed the return type, but you've also missed the argument list. Remember, your function definition needs to look exactly like the function declaration, with the exception of it including the class name and the access modifier. So the syntax is:
 <return type> <class name><access modifier><function name>(<argument list>)
where access modifier is : for private and :: for public. So your function definitions in the above snippet should've looked like this:

class Hand{// data members snipped for brevitypublic:	Hand();		int deal();        //snip};Hand::Hand(){// snip}int Hand::deal(){// snip}


There's numerous other errors in your source and violations of coding conventions :-), but this should be enough to get you started. I can send you corrected/commented source files if you want, just let me know.
=========================Buildium. Codium. Fragium.http://www.aklabs.net/=========================

This topic is closed to new replies.

Advertisement