Home > front end >  Relationship between classes and header files
Relationship between classes and header files

Time:04-03

I'm trying to learn how to use classes in C . This is my file structure.

main.cpp (sueca.cpp)

#include "Card.h"
#include "Deck.h"
#include "Player.h"
#include "Turn.h"
#include "Game.h"

int main ()
{
    std::cout << "\t\t\t.:: Sueca Game ::." << std::endl;

    Game sueca;
    //sueca.startGame();
    
    return 0;
}

Card.h:

#ifndef CARD_H
#define CARD_H

#include <iostream>             // std::cout
#include <string>               // std::string

class Card {
    public:
        Card();
        Card(int&, int&);
        ~Card();
        int getSuit() const;
        int getRank() const;
        int getPoints() const;
        void printCard () const;
        void setSuit(int&); 
        void setRank(int&);
        void setCard(int&, int&);

    private:
        int suit;
        int rank;
};

#endif

Card.cpp

#include "Card.h"

Card::Card ()
{
    suit = -1;
    rank = -1;
}

Card::Card (int &isuit, int &irank)
{
    suit = isuit;
    rank = irank;
}

Card::~Card ()
{

}

int Card::getSuit () const
{
    return suit;
}

int Card::getRank () const
{
    return rank;
}

void Card::setSuit (int &isuit) 
{
    suit = isuit;
    return;
}

void Card::setRank (int &irank) 
{
    rank = irank;
    return;
}

void Card::setCard (int &isuit, int &irank)
{
    suit = isuit;
    rank = irank;
}


int Card::getPoints () const
{
    if (rank <= 4)
        return 0;
    else if (rank <= 7)
        return rank-3;
    else
        return rank 2;
}

void Card::printCard () const
{
    std::string naipe, nome;
    switch (suit) 
    {
        case 0: 
            naipe = "HEARTS";
            break;
        case 1:
            naipe = "DIAMONDS";
            break;
        case 2:
            naipe = "CLUBS";
            break;
        case 3:
            naipe = "SPADES";
            break;
    }
    switch (rank)
    {
        case 0: 
            nome = "TWO";
            break;
        case 1:
            nome = "THREE";
            break;
        case 2:
            nome = "FOUR";
            break;
        case 3:
            nome = "FIVE";
            break;
        case 4:
            nome = "SIX";
            break;
        case 5:
            nome = "QUEEN";
            break;
        case 6:
            nome = "JACK";
            break;
        case 7:
            nome = "KING";
            break;
        case 8:
            nome = "SEVEN";
            break;
        case 9:
            nome = "ACE";
            break;
    }

    std::cout << nome << " of " << naipe;
    return;
}

Deck.h:

#ifndef DECK_H
#define DECK_H

#include <iostream>             // std::cout
#include <algorithm>            // std::shuffle
#include <array>                // std::array
#include <string>               // std::string
#include <random>               // std::default_random_engine
#include <chrono>               // std::chrono::system_clock

#include "Card.h"

class Deck : public Card{
    public:
        Deck();
        ~Deck();
        void shuffleDeck(int&); 
        void printDeck();   

    private:
        std::array<Card,40> element;         
};

#endif

Deck.cpp:

#include "Deck.h"

Deck::Deck ()
{
    auto i = 0;
    for (auto s = 0; s < 4;   s)
    {
        for (auto r = 0; r < 10;   r)
        {
            element[i].setCard(s, r);
              i;
        }
    }
}

void Deck::shuffleDeck (int &times)
{
    for (auto i = 0; i < times;   i)
    {
        unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
        std::shuffle(element.begin(), element.end(), std::default_random_engine(seed));
    }
    return;
}

void Deck::printDeck ()
{
    for (auto c = 0; c < element.size();   c)
    {
        std::cout << "card\t(" << c << ")\t";
        element[c].printCard();
    }
    return;
}

Player.h:

#ifndef PLAYER_H
#define PLAYER_H

#include <iostream>             // std::cout
#include <string>               // std::string
#include <array>                // std::array

#include "Card.h"

class Player : public Card {
    public:
        Player();
        Player(int&, std::string&);
        ~Player();
        int getID() const;
        std::string getName() const;
        int getPoints() const;
        int printHand() const;
        void setID(int&);
        void setName(std::string&);
        void setPoints(int&);

    private:
        int id;
        std::string name;
        int points = 0;
        std::array<Card,10> hand;         
};

#endif

Player.cpp

#include "Player.h"

Player::Player ()
{
    id = -1;
    points = 0;
}

Player::Player (int &iid, std::string &iname)
{
    id = iid;
    name = iname;
    points = 0;
}

Player::~Player ()
{
    
}

int Player::getID () const
{
    return id;
}

std::string getName () const
{
    return name;
}

int Player::getPoints () const
{
    return points;
}

int Player::printHand () const
{
    if (hand.size() == 0)
    {
        std::cout << "\t\t\tERROR: Player " << name << " has no cards (" << id << ")" << std::endl;
        return -1;
    }

    std::cout << "(" << id << ") " << name << "'s cards:" << std::endl;
    for (auto i = 0; i < 10;   i)
        hand[i].printCard();

    return 0;
}

void Player::setID(int &iid)
{
    id = iid;
    return;
}

void Player::setName(std::string &iname)
{
    name = iname;
    return;
}

void Player::setPoints(int &ipoints)
{
    points = ipoints;
    return;
}

Turn.h:

#ifndef TURN_H
#define TURN_H

#include <iostream>             // std::cout
#include <array>                // std::array

#include "Player.h"
#include "Card.h"

// NOTE: I'd like to access the variable "trump" from the class Game, making it the parent of this class (one game has many turns)

class Turn {
    public:
        Turn();
        Turn(int&, std::array<Player,4>&);
        ~Turn();
        int getID() const;
        int playTurn();
        int getTurnWinner();
        
    private:
        int id;
        //int trump; --> use the trump variable from the parent Game instead
        std::array<Player,4> gamer;
        std::array<Card,4> move;    
};

#endif

Turn.cpp:

#include "Turn.h"

Turn::Turn ()
{
    id = -1;
}

Turn::Turn (int &roundNO, std::array<Player,4> &players)
{
    id = roundNO;
    gamer = players;
}

int Turn::getID () const
{
    return id;
}

int Turn::playTurn ()
{   
    for (auto p = 0; p < 4;   p)
    {
        std::cout << "\t(" << p << ") " << gamer[p].getName() << "'s turn!" << std::endl;

        if (gamer[p].printHand() == -1)
            return -1;
        
        std::cout << "Pick the number of the card you want to play: ";

        int playcard;
        std::cin >> playcard;

        while (playcard > 10)
        {
            std::cout << "Invalid selection!\nPick the number of the card you want to play: ";
            std::cin >> playcard;
        }
        
        //move[p] = gamer[p].hand[playcard];
    }    

    return 0;
}

int Turn::getTurnWinner ()
{
    Card max, maxtrunfo;
    int winner, winnertrunfo, points = 0;
    bool trunfo = false;

    if (move.size() < 4)
    {   
        std::cout << "\t\t\tERROR: Round " << id << " has" << move.size() << " cards." << std::endl;
        return -1;
    }
    if (gamer.size() < 4)
    {   
        std::cout << "\t\t\tERROR: Round " << id << " has" << gamer.size() << " cards." << std::endl;
        return -2;
    }

    for (auto i = 0; i < 4;   i)
    {
        if (move[i].getRank() > max.getRank())
        {
            max = move[i];
            winner = i;
        }
            
        if ((move[i].getSuit() == trump) && (move[i].getRank() > maxtrunfo.getRank()))                                                ///VER ISTO
        {
            maxtrunfo = move[i];
            trunfo = true;
            winnertrunfo = i;
        }

        points  = move[i].getPoints();
    }

    if (trunfo)
    {
        std::cout << "\t(" << winnertrunfo << ") " << gamer[winnertrunfo].getName() << " wins!" << std::endl;
        //gamer[winnertrunfo].getPoints() = points;
    }
    else
    {
        std::cout << "\t(" << winner << ") " << gamer[winner].getName() << " wins!" << std::endl;
        //gamer[winner].getPoints() = points;
    }

    return 0;
}

Game.h:

#ifndef GAME_H
#define GAME_H

#include <iostream>             // std::cout
#include <algorithm>            // std::shuffle
#include <array>                // std::array
#include <string>               // std::string
#include <random>               // std::default_random_engine
#include <chrono>               // std::chrono::system_clock

#include "Turn.h"
#include "Player.h"

class Game {
    public:
        //Game();
        //~Game();
        int startGame();
        int setTrump();

    private: 
        int trunfo;
        int duration;
        Deck gamedeck;
        std::array<Turn,10> round;
        std::array<Player,4> gamer;
};

#endif

Game.cpp

#include "Game.h"

/*Game::Game ()
{
    trunfo = -1;
    duration = 0;
}

Game::~Game ()
{

}*/

int Game::setTrump ()
{
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::default_random_engine generator(seed);
    std::uniform_int_distribution<int> gamer(0,3);
    int player = gamer(generator);
    
    return player;
}

int Game::startGame ()
{
    int shuffle = 1;

    std::cout << "How many times do you want to shuffle the deck? ";
    std::cin >> shuffle;

    while (shuffle < 1)
    {
        std::cout << "Please insert an integer bigger than 0.\nHow many times do you want to shuffle the deck? ";
        std::cin >> shuffle;
    }

    gamedeck.printDeck();
    gamedeck.shuffleDeck(shuffle);

    std::cout << "Deck shuffled " << shuffle << " times!" << std::endl;
    std::cout << "\t * The player pairings will be (1 & 3) and (2 & 4). Let's proceed to name each player." << std::endl;

    std::string playername;
    for (auto i = 0; i < 4;   i)
    {
        std::cout << "Type the name of Player " << i 1 << ": ";
        std::cin >> playername;

        while (playername.size() == 0)
        {
            std::cout << "Please insert a readable name.\nType the name of Player " << i 1 << ": ";
            std::cin >> playername;
        }

        gamer[i].id = i;
        gamer[i].name = playername;
        
        for (auto c = 0; c < 10; c  )
            gamer[i].hand[c] = gamedeck.element[c i*10];                                                                        /// APRENDER A PASSAR O ENDEREÇO DA CARTA
    }

    // Set trump card & suit
    int trump_player, trump_card;
    trump_player = setTrump();

    std::cout << "The trump card is (" << trump_player << ") "<< gamer[trump_player].name << "'s ";
    gamer[trump_player].hand[0].print_card();
    trunfo = gamer[trump_player].hand[0].suit;

    return 0;
}

Terminal Error:

g   sueca.cpp -o sueca
/usr/bin/ld: /tmp/ccmCL0jl.o: in function `std::array<Turn, 10ul>::array()':
sueca.cpp:(.text._ZNSt5arrayI4TurnLm10EEC2Ev[_ZNSt5arrayI4TurnLm10EEC5Ev] 0x27): undefined reference to `Turn::Turn()'
/usr/bin/ld: sueca.cpp:(.text._ZNSt5arrayI4TurnLm10EEC2Ev[_ZNSt5arrayI4TurnLm10EEC5Ev] 0x7d): undefined reference to `Turn::~Turn()'
/usr/bin/ld: /tmp/ccmCL0jl.o: in function `std::array<Turn, 10ul>::~array()':
sueca.cpp:(.text._ZNSt5arrayI4TurnLm10EED2Ev[_ZNSt5arrayI4TurnLm10EED5Ev] 0x39): undefined reference to `Turn::~Turn()'
/usr/bin/ld: /tmp/ccmCL0jl.o: in function `std::array<Player, 4ul>::array()':
sueca.cpp:(.text._ZNSt5arrayI6PlayerLm4EEC2Ev[_ZNSt5arrayI6PlayerLm4EEC5Ev] 0x27): undefined reference to `Player::Player()'
/usr/bin/ld: sueca.cpp:(.text._ZNSt5arrayI6PlayerLm4EEC2Ev[_ZNSt5arrayI6PlayerLm4EEC5Ev] 0x76): undefined reference to `Player::~Player()'
/usr/bin/ld: /tmp/ccmCL0jl.o: in function `std::array<Player, 4ul>::~array()':
sueca.cpp:(.text._ZNSt5arrayI6PlayerLm4EED2Ev[_ZNSt5arrayI6PlayerLm4EED5Ev] 0x39): undefined reference to `Player::~Player()'
/usr/bin/ld: /tmp/ccmCL0jl.o: in function `Game::Game()':
sueca.cpp:(.text._ZN4GameC2Ev[_ZN4GameC5Ev] 0x1d): undefined reference to `Deck::Deck()'
/usr/bin/ld: sueca.cpp:(.text._ZN4GameC2Ev[_ZN4GameC5Ev] 0x75): undefined reference to `Deck::~Deck()'
/usr/bin/ld: /tmp/ccmCL0jl.o: in function `Game::~Game()':
sueca.cpp:(.text._ZN4GameD2Ev[_ZN4GameD5Ev] 0x40): undefined reference to `Deck::~Deck()'
collect2: error: ld returned 1 exit status

Additionally, I understand that these are very basic isses I've been reading "A tour of C " but it doesn't go into much detail on how some things are done so I browse the web looking for solutions to issues occuring in my code. Trying to learn C by myself with some prior C knowledge. If you could recommend me some ways to progress, I'd appreciate it (maybe another book I should buy?). This program is my attempt at coding a popular card game from my country.

CodePudding user response:

You may need to step back in your book a bit, but I'll explain a little bit.

Include (.h) files typically exist so that you can have 10 .cpp files that make use of the declared class. This is where you put class Foo { ... } stuff. Then anyone who wants to use Foo can include the .h file.

The .cpp files are where you implement the class. I think you understand this.

When you compile, you compile each of the .cpp's and then link them together. Or you can just do this:

g   --std=c  17 A.cpp B.cpp C.cpp -o MyProgram

This will program MyProgram (you can call it whatever you want) and include all the code from those three .cpp files.

It can be a lot more complicated than that, of course. But if you do a g line that is similar to the one I shows you, listing all of your .cpp files, then as long as you've implemented all the code that you've defined, it should build.

  • Related