crcvd
crcvd

Reputation: 1535

Friend Class Function For Another Class?

I'm trying to program a Texas Hold'em game in C++ as practice. I've just started reading about friend functions, and thought about using them to allow players to draw cards from the deck.

I have currently defined two classes as follows:

#include <string>
#include <vector>
#include <stdio.h>
typedef unsigned int uint;    

class deck

{
private:
    std::vector<card> cards;
public:
    void initialize(void)
    {
        char suits[] = { 'H', 'C', 'D', 'S' };
        uint values[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
        for (uint i = 0; i != 4; i++)
        {
            for (uint j = 0; j != 13; j++)
            {
                cards.push_back(card(suits[i], values[j]));
            }
        }
    }
    void shuffle(void)
    {
        uint i = cards.size(), random_index;
        card shuffled_card;
        while (i > 0)
        {
            random_index = rand() % (i + 1);
            shuffled_card = cards[random_index];
            cards[random_index] = cards[i];
            cards[i] = shuffled_card;
            i--;
        }
    }
};

class player
{
private:
    std::string name;
    uint chips;
    std::vector<card> hand;
public:
    player(std::string set_name, uint set_chips) { name = set_name; chips = set_chips; }
    void draw(deck& target_deck, uint number)
    {
        // Draw cards from the top of the 
        // target deck.
    }
};

I'd like the draw() method of the player class to take a reference to a member of the deck class, and to be able to remove number cards from cards of deck. Since cards is a private element of deck, I can't reference it in draw() as target_deck.cards. I've tried adding a friend function into the deck class:

friend void player::draw(deck&target_deck, uint number);

This, however, doesn't solve the problem. Is there something wrong with the code, or are the only solutions (a) defining a friend function outside of player or (b) making the entire player class a friend of deck?

Thanks in advance for any pointers!

Upvotes: 2

Views: 139

Answers (2)

Tahlil
Tahlil

Reputation: 2731

You have to put player's definition before deck. And also try defining the draw function after defining deck class.

#include <string>
#include <vector>
#include <stdio.h>
typedef unsigned int uint;    

class deck;

class player
{
private:
    std::string name;
    uint chips;
    std::vector<card> hand;
public:
    player(std::string set_name, uint set_chips) { name = set_name; chips = set_chips; }
    void draw(deck& target_deck, uint number); // define it outside.

};


class deck    
{
private:
    std::vector<card> cards;
public:
    friend void draw(deck& target_deck, uint number);
    void initialize(void)
    {
        char suits[] = { 'H', 'C', 'D', 'S' };
        uint values[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
        for (uint i = 0; i != 4; i++)
        {
            for (uint j = 0; j != 13; j++)
            {
                cards.push_back(card(suits[i], values[j]));
            }
        }
    }
    void shuffle(void)
    {
        uint i = cards.size(), random_index;
        card shuffled_card;
        while (i > 0)
        {
            random_index = rand() % (i + 1);
            shuffled_card = cards[random_index];
            cards[random_index] = cards[i];
            cards[i] = shuffled_card;
            i--;
        }
    }
};

 void player::draw(deck& target_deck, uint number)
 {
      // Draw cards from the top of the 
      // target deck.
 }

Upvotes: 0

Greg Hewgill
Greg Hewgill

Reputation: 994619

I would solve this by providing a public function deck::draw(), which returns the top card from the deck (and removes it from the deck). Then you can implement player::draw() in terms of deck::draw() by calling it as many times as needed.

If you implement a deck::draw(), then you will probably want deck::initialize() to clear the deck before pushing 52 new cards onto it.

As a minor style note, the notation of putting void in the parameter list for a function that takes no arguments is supported in C++ for backwards compatibility with C, but is not commonly used in new C++ code. The reason C supports it is because a function declaration (prototype) foo() says nothing about the arguments the function takes, while foo(void) says that the function takes no arguments. C++ always treats foo() as taking no arguments.

Upvotes: 4

Related Questions