1
//Game Lobby
//Simulates a game lobby where players wait

#include <iostream>
#include <string>

using namespace std;

class Player
{
public:  
    Player(const string& name = "");
    string GetName() const;
    Player* GetNext() const;
    void SetNext(Player* next);

private:
    string m_Name;
    Player* m_pNext;  //Pointer to next player in list
};

Player::Player(const string& name): 
    m_Name(name), 
    m_pNext(0) 
{}

string Player::GetName() const
{
    return m_Name;
}

Player* Player::GetNext() const
{
    return m_pNext;
}

void Player::SetNext(Player* next)
{
    m_pNext = next;
}

class Lobby
{
    friend ostream& operator<<(ostream& os, const Lobby& aLobby);

public:
    Lobby();
    ~Lobby();
    void AddPlayer();
    void RemovePlayer();
    void Clear();

private:
    Player* m_pHead;  
};

Lobby::Lobby():
    m_pHead(0)
{}

Lobby::~Lobby()
{
    Clear();
}

void Lobby::AddPlayer()
{
    //create a new player node
    cout << "Please enter the name of the new player: ";
    string name;
    cin >> name;
    Player* pNewPlayer = new Player(name);

    //if list is empty, make head of list this new player
    if (m_pHead == 0)
    {
        m_pHead = pNewPlayer;
    }
    //otherwise find the end of the list and add the player there
    else
    {
        Player* pIter = m_pHead;
        while (pIter->GetNext() != 0)
        {
            pIter = pIter->GetNext();       
        }
        pIter->SetNext(pNewPlayer);
    }
}

void Lobby::RemovePlayer()
{
    if (m_pHead == 0)
    {
        cout << "The game lobby is empty.  No one to remove!\n";
    }
    else
    {
        Player* pTemp = m_pHead;
        m_pHead = m_pHead->GetNext();
        delete pTemp;
    }
}

void Lobby::Clear()
{
    while (m_pHead != 0)
    {
        RemovePlayer();
    }
}

ostream& operator<<(ostream& os, const Lobby& aLobby)
{
    Player* pIter = aLobby.m_pHead;

    os << "\nHere's who's in the game lobby:\n";
    if (pIter == 0)
    {
        os << "The lobby is empty.\n";
    }
    else
    {
        while (pIter != 0)
        {   
            os << pIter->GetName() << endl;
            pIter = pIter->GetNext();
        }
    }

    return os;
}

int main()
{
    Lobby myLobby;
    int choice;

    do
    {
        cout << myLobby;
        cout << "\nGAME LOBBY\n";
        cout << "0 - Exit the program.\n";
        cout << "1 - Add a player to the lobby.\n";
        cout << "2 - Remove a player from the lobby.\n";
        cout << "3 - Clear the lobby.\n";
        cout << endl << "Enter choice: ";
        cin >> choice;

        switch (choice)
        {
            case 0: cout << "Good-bye.\n"; break;
            case 1: myLobby.AddPlayer(); break;  
            case 2: myLobby.RemovePlayer(); break;
            case 3: myLobby.Clear(); break;
            default: cout << "That was not a valid choice.\n";
        }
    }
    while (choice != 0);

    return 0;
}

Hello all! I am a beginner in C++ and doing this problem. The problem mentions the following code and asks for certain solutions.

The problem asks for:

  • Driver File (Main Program) that tests the class (playerTest.cpp)
  • Player Class Header and Implementation Files -- separate interface and implementation (player.h & playerImp.cpp)
  • Lobby Class Header and Implementation Files -- separate interface and implementation

Since this is an implementation and header problem, I tried researching the topic. I watched YouTube videos by thenewboston (Bucky), MissouriSandTCourses, MicrosonicDev, and more but I couldn't get any concept. The book (Beginning c++ through game programming) does not help at all on this topic.

I also tried reading some articles but nothing helped.

Jarod42
  • 173,454
  • 13
  • 146
  • 250
  • I don't get your question. Can you please specify it? What are you trying to achieve? What is your problem? – hellow Jul 24 '18 at 13:51
  • related/dupe, I think: https://stackoverflow.com/questions/9579930/separating-class-code-into-a-header-and-cpp-file – NathanOliver Jul 24 '18 at 13:53
  • The problem is asking for creating separate header and implementation files: • Driver File (Main Program) that tests the class (playerTest.cpp) • Player Class Header and Implementation Files -- separate interface and implementation (player.h & playerImp.cpp) • Lobby Class Header and Implementation Files -- separate interface and implementation – James Stewart Jul 24 '18 at 13:53
  • 1
    You already have it pretty much separate. Now simply copy and paste `class` blocks into `.h` files and function implementations into `.cpp` files. Include `.h` files in `.cpp` files and main. That's it. – Yksisarvinen Jul 24 '18 at 13:54
  • Also: https://stackoverflow.com/questions/625799/resolve-build-errors-due-to-circular-dependency-amongst-classes – NathanOliver Jul 24 '18 at 13:54
  • Possible duplicate of [Separating class code into a header and cpp file](https://stackoverflow.com/questions/9579930/separating-class-code-into-a-header-and-cpp-file) – A_Singh7 Jul 24 '18 at 15:03

2 Answers2

0

Start with your current source file and make incremental changes.

First, move the definition of class Player into a file named player.h; that's a header file. Then move the definitions of the member functions of Player into a file named player.cpp; that's an implementation file.

Now your current file won't compile, because it doesn't know about class Player. So add `#include "player.h" to it.

Now do the same thing for class Lobby.

Now all that's left in your original source file is int main() and a few #include directives. That's your driver file.

Pete Becker
  • 69,019
  • 6
  • 64
  • 147
  • Thank you for your answer. When moving into separate files, do I have to include `#include `, `#include ` and `using namespace std;` in every file? – James Stewart Jul 24 '18 at 14:32
  • @JamesStewart -- you need to `#include` whatever headers are needed in the file you're writing. If you get it wrong, the compiler will tell you. As a general rule, you should not add `using namespace std;`; use fully qualified names (e.g., `std::cout`). – Pete Becker Jul 24 '18 at 16:05
0

The following are your files seperated into headers and implementation. Follow the simple principle of declarations comes before the definition here. Included #pragma once for header files as include guard, in any case these are included multiple times to a source file. I do not recommend using namespace std in header files, Try to move them to source files and use the namespace qualified names in headers like std::string.

player.h

#pragma once

#include <iostream>
#include <string>

using namespace std;

class Player
{
public:  
    Player(const string& name = "");
    string GetName() const;
    Player* GetNext() const;
    void SetNext(Player* next);

private:
    string m_Name;
    Player* m_pNext;  //Pointer to next player in list
};

playerImp.cpp

#include "player.h"

Player::Player(const string& name): 
    m_Name(name), 
    m_pNext(0) 
{}

string Player::GetName() const
{
    return m_Name;
}

Player* Player::GetNext() const
{
    return m_pNext;
}

void Player::SetNext(Player* next)
{
    m_pNext = next;
}

lobby.h

#pragma once

#include <iostream>
#include <string>

using namespace std;

class Player;

class Lobby
{
    friend ostream& operator<<(ostream& os, const Lobby& aLobby);

public:
    Lobby();
    ~Lobby();
    void AddPlayer();
    void RemovePlayer();
    void Clear();

private:
    Player* m_pHead;  
};

lobbyImp.cpp

#include "lobby.h"
#include "player.h"

Lobby::Lobby():
    m_pHead(0)
{}

Lobby::~Lobby()
{
    Clear();
}

void Lobby::AddPlayer()
{
    //create a new player node
    cout << "Please enter the name of the new player: ";
    string name;
    cin >> name;
    Player* pNewPlayer = new Player(name);

    //if list is empty, make head of list this new player
    if (m_pHead == 0)
    {
        m_pHead = pNewPlayer;
    }
    //otherwise find the end of the list and add the player there
    else
    {
        Player* pIter = m_pHead;
        while (pIter->GetNext() != 0)
        {
            pIter = pIter->GetNext();       
        }
        pIter->SetNext(pNewPlayer);
    }
}

void Lobby::RemovePlayer()
{
    if (m_pHead == 0)
    {
        cout << "The game lobby is empty.  No one to remove!\n";
    }
    else
    {
        Player* pTemp = m_pHead;
        m_pHead = m_pHead->GetNext();
        delete pTemp;
    }
}

void Lobby::Clear()
{
    while (m_pHead != 0)
    {
        RemovePlayer();
    }
}

playerTest.cpp

#include "player.h"
#include "lobby.h"

ostream& operator<<(ostream& os, const Lobby& aLobby)
{
    Player* pIter = aLobby.m_pHead;

    os << "\nHere's who's in the game lobby:\n";
    if (pIter == 0)
    {
        os << "The lobby is empty.\n";
    }
    else
    {
        while (pIter != 0)
        {   
            os << pIter->GetName() << endl;
            pIter = pIter->GetNext();
        }
    }

    return os;
}

int main()
{
    Lobby myLobby;
    int choice;

    do
    {
        cout << myLobby;
        cout << "\nGAME LOBBY\n";
        cout << "0 - Exit the program.\n";
        cout << "1 - Add a player to the lobby.\n";
        cout << "2 - Remove a player from the lobby.\n";
        cout << "3 - Clear the lobby.\n";
        cout << endl << "Enter choice: ";
        cin >> choice;

        switch (choice)
        {
            case 0: cout << "Good-bye.\n"; break;
            case 1: myLobby.AddPlayer(); break;  
            case 2: myLobby.RemovePlayer(); break;
            case 3: myLobby.Clear(); break;
            default: cout << "That was not a valid choice.\n";
        }
    }
    while (choice != 0);

    return 0;
}

EDITED

Please read following articles to understand C++ compilation more.

https://en.wikipedia.org/wiki/Include_directive

http://faculty.cs.niu.edu/~mcmahon/CS241/Notes/compile.html

https://www.toptal.com/c-plus-plus/c-plus-plus-understanding-compilation

PraAnj
  • 839
  • 1
  • 9
  • 25
  • Don't use angle brackets for user-written headers. That's what `#include "player.h"` is for. Yes, angle brackets work, but they're there primarily for compiler-supplied headers. You should also mention that `#pragma once` is not standard C++. It's a common extension. – Pete Becker Jul 24 '18 at 16:15
  • Thank you for pointing this out. Answer edited to use `#include "player.h"` format. – PraAnj Jul 24 '18 at 16:24