Originally Posted by
iMalc
Well first I have to say - well done. It's always more satisfying when you figure things out on your own.
Also, we're sort of both right about the need to change RemovePlayer. You're right in that it wont currently have any ill-efect considering the rest of the program as it currently stands. However, initialliy m_pHead and m_pTail are both NULL, then say you call AddPlayer once and then RemovePlayer once.
What values do those member variables have now?...
m_pHead is NULL, but m_pTail is not. This could very easily lead to a bug later on as you make further changes.
I've done it, and more. I added the option of deleting it from either the head of the list, or the tail (depending on user choice). It may be a little ugly, but suffice to say, it works. Players get added, and deleted properly and allocate correctly. I pretty much figured this out on my own. It was an awesome brain exercise for me, and I feel like I'm a lot more comfortable with pointers than I have ever been. But again, there might be some mistakes in there, just let me know of anything I could improve upon.
Player Class:
Code:
class Player
{
public:
Player(const string& name = "");
string GetName() const;
Player* GetNext() const;
void SetNext(Player* next);
Player* GetPrev() const;
void SetPrev(Player* prev);
private:
string m_Name;
Player* m_pNext; // Pointer to next player in list
Player* m_pPrev; // Pointer to previous player in list
};
Player::Player(const string& name):
m_Name(name),
m_pNext(0),
m_pPrev(0)
{}
string Player::GetName() const
{
return m_Name;
}
Player* Player::GetNext() const
{
return m_pNext;
}
void Player::SetNext(Player* next)
{
m_pNext = next;
}
Player* Player::GetPrev() const
{
return m_pPrev;
}
void Player::SetPrev(Player* prev)
{
m_pPrev = prev;
}
Lobby Class:
Code:
class Lobby
{
friend ostream& operator<<(ostream& os, const Lobby& aLobby);
public:
Lobby();
~Lobby();
void AddPlayer();
void RemovePlayer();
void Clear();
private:
Player* m_pHead;
Player* m_pTail;
Player* m_pCurrent;
};
Lobby::Lobby():
m_pHead(0),
m_pTail(0),
m_pCurrent(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;
m_pTail = m_pHead;
}
//otherwise find the end of the list and add the player there
else
{
m_pTail->SetPrev(m_pCurrent);
m_pTail->SetNext(pNewPlayer);
m_pCurrent = m_pTail;
m_pTail = m_pTail->GetNext();
m_pTail->SetPrev(m_pCurrent);
}
}
void Lobby::RemovePlayer()
{
int choice;
cout << "Select from which position you'd like to delete\n";
cout << "0 - Cancel\n";
cout << "1 - From the Bottom\n";
cout << "2 - From the Top\n";
cout << endl << "Enter choice: ";
cin >> choice;
switch (choice)
{
if (m_pHead == 0)
{
cout << "The game lobby is empty. No one to remove!\n";
}
else
{
case 0:
cout << "Cancelling Request.\n";
break;
case 1:
if ( (m_pTail == m_pHead) )
{
delete m_pTail;
m_pCurrent = 0;
m_pHead = 0;
m_pTail = 0;
}
else
{
Player* pTemp = m_pTail;
m_pTail = m_pCurrent;
m_pCurrent = m_pCurrent->GetPrev();
delete pTemp;
}
break;
case 2:
if ( (m_pTail == m_pHead) )
{
delete m_pTail;
m_pCurrent = 0;
m_pHead = 0;
m_pTail = 0;
}
else
{
Player* pTemp = m_pHead;
m_pHead = m_pHead->GetNext();
delete pTemp;
}
}
break;
default:
cout << "That is not a valid choice!" << endl;
}
}
void Lobby::Clear()
{
while (m_pHead != 0)
{
if ( (m_pTail == m_pHead) )
{
delete m_pTail;
m_pCurrent = 0;
m_pHead = 0;
m_pTail = 0;
}
else
{
Player* pTemp = m_pHead;
m_pHead = m_pHead->GetNext();
delete pTemp;
}
}
}
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 != aLobby.m_pTail->GetNext())
{
os << pIter->GetName() << endl;
pIter = pIter->GetNext();
}
}
return os;
}
Main:
Code:
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;
}
Also, I'm aware of stl::list and I'm also aware that the program is not a true linked list. Once I get into more advanced template class creation, I'll try my hand at it.