Member Avatar for Sallad

Hello, my name is Dallas. I'm (obviously) new to the site. I've spent the past couple of days doing absolutely nothing but trying to work on this program. I usually don't like trying to get help, but I've spent so much time on it by myself that I have no other choice but to ask for help. So here we go!

The assignment is to create a Poker game using 3 classes - a Card class, a Deck Class, and a Player Class. So far, all I've been able to manage is to create a card, create a deck of 52 cards, shuffle that deck, and print the deck out. Obviously I have a LONG ways to go, but what I'm working on now is dealing the 5 cards from the deck to the player's hands (in this program, there are 2 hands/players - one is the user and the other is the "computer", although there is no AI implemented). What seems to be happening is that even though the deck has been shuffled, the player's hand consists of the 1st 5 cards from the deck when it was unshuffled.


Card.h

#ifndef CARD_H
#define CARD_H

#include <iostream>
#include <cstdlib>
#include <string>

using namespace std;

class Card
{
	public:
		Card();
		int getCard();
		void setCard(int);
		void displayCard(Card);
	protected:
		int value;
		int suit;  
		int cardID;  
};

#endif

Card.cpp

#include "card.h" 

Card::Card() : value(0), suit(0), cardID(0)
{}

int Card::getCard()
{
	return cardID;
}

void Card::setCard(int newID)
{
	 if (newID >= 0 && newID < 52)
	 {
		 cardID = newID;
		 value = cardID%13;
		 suit = cardID/13;
	 }
	 else
	 {
		 cardID = 0;
		 value = 0;
		 suit = 0;
	 }
}

void Card::displayCard(Card ID)
{
	 string Suits[] = {"Diamonds", "Hearts", "Clubs", "Spades"};
	 string Values[] = { "Ace", "Two", "Three", "Four", "Five", "Six", "Seven",
						 "Eight", "Nine", "Ten", "Jack", "Queen", "King"};
	 
	 cout << Values[ID.value] << " of " << Suits[ID.suit] << endl;
}

Deck.h

#ifndef DECK_H
#define DECK_H

#include "card.h"

using namespace std;

class Deck : public Card
{
	friend ostream& operator <<(ostream&, const Card&);
	public:
		Deck();
		void shuffleDeck();
		void displayDeck();
		int dealCard();
		void swapCards(int,int);
	protected:
		Card aDeckOfCards[52]; // create a deck 52 cards
		int deckTop;
};

#endif

Deck.cpp

#include "deck.h"

Deck::Deck()
{
	deckTop=0;
	for(int i=deckTop; i < 52; i++)
		aDeckOfCards[i].setCard(i);	 // pass a unique value to setCard 
			
}

void Deck::shuffleDeck()
{
	cout << "\nDeck after shuffling: " << endl << endl;
	for (int i = 0; i < 100; i++)
	{
		int index1 = rand()%52;
		int index2 = rand()%52;
		swapCards(index1, index2);
	}   
}

void Deck::displayDeck()
{
	for (int i = deckTop; i < 52; i++)
	{
		Card j = aDeckOfCards[i];
		displayCard(j);
	}
	 
}

int Deck::dealCard()
{
	if (deckTop < 51)
	{
		deckTop++;
	}
	
	else
	{
		shuffleDeck();
		deckTop = 1;
		dealCard();
	}
	
	return aDeckOfCards[deckTop-1].getCard();
}

void Deck::swapCards(int first, int second)
{
	 Card temp = aDeckOfCards[first];
	 aDeckOfCards[first] = aDeckOfCards[second];
	 aDeckOfCards[second] = temp;
}

ostream& operator <<(ostream& out, const Card& c)
{
	out << c;
	return out;
}

Player.h

#ifndef PLAYER_H
#define PLAYER_H

#include "card.h"
#include "deck.h"

class Player: public Deck 
{
	public:
		Player();
		void showHand();
		void addCard(int);
		void showCard(int);
		void deleteCard();
	private:
		Card aHand[5];
		int currentCard;
};

#endif

Player.cpp

#include "player.h"

const int HAND_SIZE = 5;

Player::Player()
{
	for (int i = 0; i < HAND_SIZE; i++)
	{
		addCard(i);
		deckTop++;
	}
			  
}

void Player::addCard(int cardNum)
{
	aHand[cardNum] = aDeckOfCards[cardNum];			 
}

void Player::deleteCard()
{
					
}

void Player::showCard(int id)
{
	Card j = aHand[id];
	displayCard(j);					   
}

void Player::showHand()
{
	for (int i = 0; i < HAND_SIZE; i++)
		showCard(i);			
}

And main.cpp

#include "card.h"
#include "deck.h"
#include "player.h"

int main()
{
	Deck d;
	d.shuffleDeck();
	d.displayDeck();
	
	cout << "\n\nPlayer1's hand is: " << endl;
	Player player1;
	player1.showHand();
	system("PAUSE");
	return 0;
}

Again, this is obviously not even closed to being finished, but I'm just trying to do this one step at a time and have each player draw 5 cards from the deck. The data members and functions shown are required, so I have to have them. And I've seen quite a few codes use vectors or something, but we haven't learned about those, so I don't think I can use them for this assignment.

Perhaps instead of doing aHand[cardNum] = aDeckOfCards[cardNum]; , make a function in Deck that returns the top card on the deck.

Here's what I would do. Make a function player.begin() (or use the constructor perhaps), which shuffles and displays the cards in Deck d (which is part of class Player) and then deals out the cards using a line like aHand[cardNum} = d.getTop(); , where get top takes the top card off the deck.

That's just my suggestion. Whenever I've dealt with crossing classes, I make sure one class calls the second to avoid trying to pass things.

Member Avatar for Sallad

I believe the dealCard function of Deck is supposed to be like the "getTop" function you suggested. However, whenever I try to call that Deck function from the Player class, it gives me an error saying that dealCard is not part of the Card class. I've tried calling it like so:

aHand[cardNum].dealCard();

but it gives me that aforementioned error. I'm very new to classes and calls and such, so it's possible that I'm simply calling it the wrong way. Speaking of which, where does the d come from in your d.getTop()? Is that the same d I have as an object of Deck?

Yeah, that's obvious that it wouldn't work because they aren't part of the same class. When you cross classes, it can be tricky, so I try to simplify it by adding the one classes variable to the other class.

What I was suggesting is instead of making your deck from the main, move the lines:

Deck d;
	d.shuffleDeck();
	d.displayDeck();

to somewhere in your class Player.

I haven't tested it, so heaven knows if it would work, but I would add Deck d to the variables in Player class. That would make your classes Player and Deck cross so you can access the functions from the Player class by calling d./*function call*/; . So, like I suggested above, just change your Player constructor and add card to something like what I have below and it might work.

Player::Player()
{	d.shuffleDeck();
       d.displayDeck();

    for (int i = 0; i < HAND_SIZE; i++)
	{ addCard(i);
	  deckTop++; }
			  
}

void Player::addCard(int cardNum)
{
	aHand[cardNum] = d.getTop();
}

getTop() is just what I'm calling it cause I didn't know what to suggest, but it just gets the top card, so if you have a function that does that, just put that there instead. Now, I've only crossed classes a few times, so I'm not that confident with it, but something like that should be fine.

Member Avatar for Sallad

I am still getting the same result. Every player object seems to have the output of "Ace of Diamonds, 2 of Diamonds, 3 of Diamonds....). I'm wondering if my dealCard() function is the culprit.

Card Deck::dealCard()
{
    if (deckTop < 51)
    {
        deckTop++;
        return aDeckOfCards[deckTop-1];
    }
   
    else
    {
        shuffleDeck();
        deckTop = 1;
        dealCard();
        return aDeckOfCards[0];
    }
}

To me, this looks fine. However, I can't figure out where else there could be a problem.

So, you changed everything and it's still giving you the wrong thing. Hmm.... So, the top card in the deck is at 0. My assumption is that either the deck isn't being saved after shuffling, or your getcard function is causing some kind of issue. Try what you put above and see if that clears it up.

Well, I believe the reason every player is getting those cards is because of

Player::Player()
{
	for (int i = 0; i < HAND_SIZE; i++)
	{
		addCard(i);
		deckTop++;
	}
			  
}

void Player::addCard(int cardNum)
{
	aHand[cardNum] = aDeckOfCards[cardNum];			 
}

The way you originally had it, it was sending the same numbers 0-4, thus never getting past the first 5 cards in the deck. I believe you need another variable in the addCard call, like deckTop or something. That should help with that part if you want to leave it like you had it originally.

Member Avatar for Sallad

The way my professor had it, we were to have 2 integer parameters in the addCard function. I put it to one simply because I couldn't think of another integer parameter that I needed. If I did pass in the deckTop variable into the addCard function, I don't see how exactly I can use that though...

Well, the variable i that you pass says which place in the hand gets the card. deckTop tells what place in the deck of cards you're at, thus moving you beyond the first 5 cards. You should be able to just change this line aHand[cardNum] = aDeckOfCards[cardNum]; to aHand[cardNum] = aDeckOfCards[deckTop]; and that will help with that part.

Member Avatar for Sallad

I tried what you said, but I still got the same results again. I then decided that to make sure that the deckTop variable was saving the increment, I made it static int deckTop;. I then initialized it to 0. I compiled the project again, and now I get the following results:

Player 1's Hand is:
Ace of Diamonds
Two of Diamonds
Three of Diamonds
Four of Diamonds
Five of Diamonds

Player 2's Hand is: 
Six of Diamonds
Seven of Diamonds
Eight of Diamonds
Nine of Diamonds
Ten of Diamonds

Now, I believe it is at least incrementing correctly. The problem (still) is that either the deck is not saving or that I am dealing from a wrong deck or something.

Wow, I can't believe I didn't see this. You have a function dealCard in your Deck class. What happens if you change your functions to this.

Player::Player()
{
	for (int i = 0; i < HAND_SIZE; i++)
	{
		addCard(i);
	}
			  
}

void Player::addCard(int cardNum)
{
	aHand[cardNum] = d.dealCard();
}

That way you don't have to worry about having an extra variable and your Deck class doesn't lose count of where the deckTop is.

A second catastrophe I just noticed could be happening is if you have Player one, two; because they each create a new deck and each would have their own select cards from their own deck... This is probably what has been happening, not that they are getting the same cards in the same deck. And that's probably why you have been shuffling a deck and it hasn't been doing anything. I'm sorry I didn't see that earlier.

Now, you can ignore this, cause I'm just trying to resolve what could be the issue (I'm not sure if it is), but perhaps you should add another class called Table or something, and within that have a Deck d and Player p (either a vector or list or whatever you feel comfortable with). That way you ensure that you have one deck and however many players you want. The problem with that is that basically your main would consist of calls to Table like

main() {
Table t; // construct shuffles and shows cards
t.detPlayers(); // asks the number of players and deals cards to each
// whatever else you want to happen during the rest of the game
}

It would be a bit of a pain, because you'd have to go through Table for all your calls involving deck and such and pass the variable every time I think. Like, for the above code I just suggested, I believe it would be something like this.

void Table::detPlayer()
{  cout << "How many players: ";
    cin >> num;
    Player (num, d);
}

// In Player Class
Player::Player(int x, Deck d )
{
    for (int y = 0; y < x; y++)
      {
	for (int i = 0; i < HAND_SIZE; i++)
	{
		addCard(i, y, d);
	}
     }		  
}

void Player::addCard(int cardNum, int plyNum, Deck d)
{
	aHand[plyNum][cardNum] = d.dealCard();
}

I'm not even sure if that's correct, I'd have to actually mess with your code to be sure, but I think that's how it would look. It means you'd have to rework your entire code, so if you are going to try this, save what you have elsewhere before you start messing with everything cause I would hate for you to mess with it and then realize you didn't need the extra class.

Member Avatar for Sallad

Holy cow, I think I figured it out! I used parts of what you suggested and I believe I got it. Although I've already tried it before countless times, I put back the aHand[cardNum] = d.dealCard(); in the addCard() function. I then looked at how you thought I should have a new class Table. Our professor only wants us to use the 3 classes and their functions, so I tried to dissect what you had to see if I could implement it otherwise.

What I particularly noticed was that you passed in the deck to the Player constructor. So I decided to go back to my main, create a Deck d, shuffle and display it, then when I instantiated my Player objects, I passed in the deck as a parameter like Player player1(d); . I then changed the player.h so that Player(); became Player(Deck &); . So then inside the Player(Deck &) function, I simply made Deck D (the deck object you suggested earlier that I make a part of class Player) equal to the deck object d that I passed in.

Here's my new main

int main()
{
    Deck d;
    d.shuffleDeck();
    d.displayDeck();
    
    cout << "\n\nPlayer1's hand is: " << endl;
    Player player1(d);
    player1.showHand();
    
    cout << "\n\nPlayer2's hand is: " << endl;
    Player player2(d);
    player2.showHand();
    system("PAUSE");
    return 0;
}

And here are my updates to the Player class

Player::Player(Deck &d)
{
    D = d;
    for (int i = 0; i < HAND_SIZE; i++)
	{ 
        addCard(i);
    }			  
}


void Player::addCard(int cardNum)
{
     aHand[cardNum] = D.dealCard();
}

I don't know if this will work in the long run, but I AM getting the results I should right now. Now my next step is to allow the player to get rid of however many cards they choose and draw that many back...

Member Avatar for Sallad

Well, I spoke with my professor, and he said that he wants me to do it differently. He frowned upon me making the Deck object a part of Player and setting it equal to the passed-in Deck object from main. He doesn't think Player should have control of the Deck. He also didn't like how my deleteCard function called addCard within it.

So, I (sorta) have to start from scratch. Or at least figure out another way of doing this. *sigh* Do you happen to have any more suggestions? :)

Well, you should be able to retain your classes if nothing else, and the functions will be similar. You just have to figure out what you are passing and make sure it is returned. I mean, he said he didn't like you making deck a part of Player, so don't. Either pass it in or write another function under the main that deals with what happens when you deal the hands, like:

main() {
// shuffle and show deck
// Initialize players
dealHand(deck, player);
// repeat for other character
p1.showHand();
p2.showHand();

// other code
}

void addToHand(deck& d, player& p)
{ // get players hand count, should be zero since player was just initialized
   x = // the top card of deck, d.dealCard() possibly
   p.addCard(x); 
   // loop till every position holds a card
};

By doing that, you can call that function whenever a player needs more cards (like after a discard). You could write another function to remove cards that would allow you to either remove one select card or clear the hand depending and all it does is call your function deleteCard or whatever you called it.

I've learned that when making a class to make the functions very simple cause if you can call it once, you can call it multiple times. You did a good job keeping it simple when you started so there isn't much you need to change. Just change parameters so your functions take in the right things and you should be able to reuse what you have already.

Member Avatar for Sallad

Yeah, I figured out a way to simplify my code even more. One thing I did was get rid of my addCard() and deleteCard() functions and "combined" them into a replaceCard() function. I noticed that my deleteCard() function just called addCard(), so it was pretty useless.

In this replaceCard function, I made it so that along with passing in cardNum - the place in aHand[] that I want to put a card - I pass in a Card as well. I just set aHand[cardNum] equal to the card that I passed in. In order to pass a Card in, I call my dealCard function in Deck. This is how I gain "access" to the Deck without having the Deck object created in Player and all.

void Player::replaceCard(int cardNum, Card t)
{
     aHand[cardNum] = t; // replace/draw card in specified spot in hand
}

Example call from main: player1.replaceCard( i , d.dealCard()); where i is simply the counter variable in a for loop (from 0 to 4).

I also decided to add error-checking in main, although it wasn't specifically asked for. I first check to make sure the user inputs a 'y' or 'n' for if they want to draw new cards. If they say yes, then I make sure they choose only between 1 and 5 cards to replace. Then I create a bool array of size 5 and initialize to 0 (because I don't remember if it does that automatically or not). For however many cards the user wants to replace, they input the card number they want to replace. Along with making sure the number is between 1-5, I use the bool array to ensure they don't try to replace the same card repeatedly. So say the user wants to replace the 1st card: the bool array[1] is set to 1, so when the for loop runs again, they can't replace that card again.

I don't know if I said it before, but thank you SO much for helping me! I remember asking for help on java forums (learned java in high school) and never getting any help whatsoever. Everyone was too uptight about not willing to help with assignments/projects, even if you had some code to work with and weren't just asking for someone to do it for you. That's why I was reluctant to join and ask for help here. But again, you proved my expectations wrong and helped out greatly! I'm glad that you didn't just give me the answer (whether that be intentional on your behalf or just because you didn't know haha) because it helped me teach myself. I hardly knew anything about classes going into this project, but I think I've gained a greater understanding about them after doing this program. I am forever in your debt lol :)

Well, that's great. Anytime you can find a way to refine your code and make your life easier is always a good thing. As one of my teachers told us, "it's not about the # of lines, it's how efficiently you use them." But yeah, it seems like you figured out what I was trying to say and made it even better so that's great.

And I'm glad I could be of help. My first year of programming, I took a class with a teacher who wouldn't answer questions about the assigned program and told us to consult our peers or the internet. Needless to say, since I was the only one in the class, that I went to the internet and I was so annoyed when all I got when asking was a paragraph on how to look up how to do it. You get that occasionally here (for questions that can be answered easily or have already been answered) but I've found that people tend to at least make me think about what I'm doing and even if they don't give me direction, after I explain it to them so much, I realize my own mistakes, so it works either way.

But yeah, it was sorta intentional cause giving out code is against the rules of this forum, but there is also that moment when you realize what you did and how to fix it. I love when I figure out how to do something on my own so I try to help nudge people in the right direction (or what I think is the right direction at the time >.< ) so that they can have that "eureka" moment as well. Tends to make them not hate programming so much afterward then. Good luck with the rest of your program.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.