Jump to content

  • Log In with Google      Sign In   
  • Create Account

14 years ago on June 15th Gamedev.net was first launched! We want to thank all of you for being part of our community and hope the best years are ahead of us. Happy birthday Gamedev.net!

#ActualChad Smith

Posted 22 December 2012 - 03:37 PM

I haven't done a lot of C++ Command Line I/O in quite a while so I have forgotten a couple of things.  

 

Anyway I started to work on a game just for the command line because I wanted to work on my code design skills more.  I felt having to worry about a graphics API would only get in the way.  The code design would be close to the same and I'd just have to trade in graphics when I felt like it mostly.

 

Well the game ended up getting bigger than I thought it would for such a simple game and now I find myself posing this question.  I have a game that has a lot of "menus" (with the command line that's almost all their can be) and I find myself repeating a lot of code in places just to wait until I get valid input from the user.  Meaning making sure the user inputs an integer (that's no problem) but also making sure the user does a valid selection for that menu.  Quick example of some code from a menu in my game.

 

From the menu from where the user is selecting their game mode:

//GetMode asks the user what mode they want to play on and returns mode selected
GameMode Game::GetGameMode()
{
	bool validInput=false;
	GameMode gameMode;

	while(!validInput)
	{
		int choice=ToInt(StringInput());

		switch(choice)
		{
		case GameMode::COMPUTER_PLAYER:
			gameMode=GameMode::COMPUTER_PLAYER;
			validInput=true;
			break;
		case GameMode::PLAYER_COMPUTER:
			gameMode=GameMode::PLAYER_COMPUTER;
			validInput=true;
			break;
		default:
			std::cout<<"Please enter a valid choice using the number next to your desired game mode."<<std::endl;
			std::cout<<"Press ENTER to try again..."<<std::endl;
			std::cin.get();
			DisplayGameMode();
		}
	}
	return gameMode;
}

 

Also here is an example when the user is selecting their difficulty:
Difficulty Game::GetDifficulty()
{
	bool validInput=false;
	Difficulty gameDifficulty;

	while(!validInput)
	{
		int choice=ToInt(StringInput());
		switch(choice)
		{
			case Difficulty::EASY:
			{
				gameDifficulty=Difficulty::EASY;
				validInput=true;
				break;
			}
			case Difficulty::MEDIUM:
			{
				gameDifficulty=Difficulty::MEDIUM;
				validInput=true;
				break;
			}
			case Difficulty::HARD:
			{
				gameDifficulty=Difficulty::HARD;
				validInput=true;
				break;
			}
			case Difficulty::EXPERT:
			{
				gameDifficulty=Difficulty::EXPERT;
				validInput=true;
				break;
			}
			case Difficulty::GOD:
			{
				gameDifficulty=Difficulty::GOD;
				validInput=true;
				break;
			}
			default:
			{
				std::cout<<"Please enter a valid choice using the number next to your desired difficulty."<<std::endl;
				std::cout<<"Press ENTER to try again..."<<std::endl;
				std::cin.get();
				DisplayDifficulty();
			}
		}
	}
	return gameDifficulty;
}

 

 

 
As you can see they both share A LOT of things in common.  Only difference is what they return and the different cases.  I feel I am repeating entirely too much code over and over just to make sure the user selects valid input.  I know I could easily write a function that checks to see if the input is an integer.  That's no problem.  Though because every menu is different and every menu doesn't have the same amount of choices to chose from what could I do to keep from repeating the same valid Input code and the user did valid input for that given menu?
 
I might not just be thinking in a Command Line I/O mindset right now which might be why I'm stumped by something so easy.  Though from what I've been taught in programming that once you start repeating the same type of code it usually means it could somehow be wrapped into a function.  That's not the only place I repeat it.  I repeat it in multiple places.
 
Is their something I'm missing?  What would be the best way to make sure the user selected a valid input for that menu without having to repeat code over and over?
 
Thanks for any help!
 
EDIT: ToInt and StringInput are both functions that I wrote myself.  StringInput just gets the input as a string and returns in.  ToInt just takes a string and returns an int from it using a std::stringstream
 
EDIT 2: switched to using code tags, forgot source tags were removed.

#2Chad Smith

Posted 22 December 2012 - 03:34 PM

I haven't done a lot of C++ Command Line I/O in quite a while so I have forgotten a couple of things.  

 

Anyway I started to work on a game just for the command line because I wanted to work on my code design skills more.  I felt having to worry about a graphics API would only get in the way.  The code design would be close to the same and I'd just have to trade in graphics when I felt like it mostly.

 

Well the game ended up getting bigger than I thought it would for such a simple game and now I find myself posing this question.  I have a game that has a lot of "menus" (with the command line that's almost all their can be) and I find myself repeating a lot of code in places just to wait until I get valid input from the user.  Meaning making sure the user inputs an integer (that's no problem) but also making sure the user does a valid selection for that menu.  Quick example of some code from a menu in my game.

 

From the menu from where the user is selecting their game mode

 
</p><div>//GetMode asks the user what mode they want to play on and returns mode selected</div>
<div>GameMode Game::GetGameMode()</div>
<div>{</div>
<div>bool validInput=false;</div>
<div>GameMode gameMode;</div>
<div> </div>
<div>while(!validInput)</div>
<div>{</div>
<div>int choice=ToInt(StringInput());</div>
<div> </div>
<div>switch(choice)</div>
<div>{</div>
<div>case GameMode::COMPUTER_PLAYER:</div>
<div>gameMode=GameMode::COMPUTER_PLAYER;</div>
<div>validInput=true;</div>
<div>break;</div>
<div>case GameMode::PLAYER_COMPUTER:</div>
<div>gameMode=GameMode::PLAYER_COMPUTER;</div>
<div>validInput=true;</div>
<div>break;</div>
<div>default:</div>
<div>std::cout<<"Please enter a valid choice using the number next to your desired game mode."<<std::endl;</div>
<div>std::cout<<"Press ENTER to try again..."<<std::endl;</div>
<div>std::cin.get();</div>
<div>DisplayGameMode();</div>
<div>}</div>
<div>}</div>
<div>return gameMode;</div>
<div>}</div>
<div>
Also here is an example when the user is selecting their difficulty:
</div>
<div>
<div>Difficulty Game::GetDifficulty()</div>
<div>{</div>
<div>bool validInput=false;</div>
<div>Difficulty gameDifficulty;</div>
<div> </div>
<div>while(!validInput)</div>
<div>{</div>
<div>int choice=ToInt(StringInput());</div>
<div>switch(choice)</div>
<div>{</div>
<div>case Difficulty::EASY:</div>
<div>{</div>
<div>gameDifficulty=Difficulty::EASY;</div>
<div>validInput=true;</div>
<div>break;</div>
<div>}</div>
<div>case Difficulty::MEDIUM:</div>
<div>{</div>
<div>gameDifficulty=Difficulty::MEDIUM;</div>
<div>validInput=true;</div>
<div>break;</div>
<div>}</div>
<div>case Difficulty::HARD:</div>
<div>{</div>
<div>gameDifficulty=Difficulty::HARD;</div>
<div>validInput=true;</div>
<div>break;</div>
<div>}</div>
<div>case Difficulty::EXPERT:</div>
<div>{</div>
<div>gameDifficulty=Difficulty::EXPERT;</div>
<div>validInput=true;</div>
<div>break;</div>
<div>}</div>
<div>case Difficulty::GOD:</div>
<div>{</div>
<div>gameDifficulty=Difficulty::GOD;</div>
<div>validInput=true;</div>
<div>break;</div>
<div>}</div>
<div>default:</div>
<div>{</div>
<div>std::cout<<"Please enter a valid choice using the number next to your desired difficulty."<<std::endl;</div>
<div>std::cout<<"Press ENTER to try again..."<<std::endl;</div>
<div>std::cin.get();</div>
<div>DisplayDifficulty();</div>
<div>}</div>
<div>}</div>
<div>}</div>
<div>return gameDifficulty;</div>
<div>}</div>
<div>
 
As you can see they both share A LOT of things in common.  Only difference is what they return and the different cases.  I feel I am repeating entirely too much code over and over just to make sure the user selects valid input.  I know I could easily write a function that checks to see if the input is an integer.  That's no problem.  Though because every menu is different and every menu doesn't have the same amount of choices to chose from what could I do to keep from repeating the same valid Input code and the user did valid input for that given menu?
 
I might not just be thinking in a Command Line I/O mindset right now which might be why I'm stumped by something so easy.  Though from what I've been taught in programming that once you start repeating the same type of code it usually means it could somehow be wrapped into a function.  That's not the only place I repeat it.  I repeat it in multiple places.
 
Is their something I'm missing?  What would be the best way to make sure the user selected a valid input for that menu without having to repeat code over and over?
 
Thanks for any help!
 
EDIT: ToInt and StringInput are both functions that I wrote myself.  StringInput just gets the input as a string and returns in.  ToInt just takes a string and returns an int from it using a std::stringstream
 
EDIT 2: switched to using code tags, forgot source tags were removed.

#1Chad Smith

Posted 22 December 2012 - 03:32 PM

I haven't done a lot of C++ Command Line I/O in quite a while so I have forgotten a couple of things.  

 

Anyway I started to work on a game just for the command line because I wanted to work on my code design skills more.  I felt having to worry about a graphics API would only get in the way.  The code design would be close to the same and I'd just have to trade in graphics when I felt like it mostly.

 

Well the game ended up getting bigger than I thought it would for such a simple game and now I find myself posing this question.  I have a game that has a lot of "menus" (with the command line that's almost all their can be) and I find myself repeating a lot of code in places just to wait until I get valid input from the user.  Meaning making sure the user inputs an integer (that's no problem) but also making sure the user does a valid selection for that menu.  Quick example of some code from a menu in my game.

 

From the menu from where the user is selecting their game mode

 
//GetMode asks the user what mode they want to play on and returns mode selected
GameMode Game::GetGameMode()
{
bool validInput=false;
GameMode gameMode;
 
while(!validInput)
{
int choice=ToInt(StringInput());
 
switch(choice)
{
case GameMode::COMPUTER_PLAYER:
gameMode=GameMode::COMPUTER_PLAYER;
validInput=true;
break;
case GameMode::PLAYER_COMPUTER:
gameMode=GameMode::PLAYER_COMPUTER;
validInput=true;
break;
default:
std::cout<<"Please enter a valid choice using the number next to your desired game mode."<<std::endl;
std::cout<<"Press ENTER to try again..."<<std::endl;
std::cin.get();
DisplayGameMode();
}
}
return gameMode;
}
 
Also here is an example when the user is selecting their difficulty:

Difficulty Game::GetDifficulty()
{
bool validInput=false;
Difficulty gameDifficulty;
 
while(!validInput)
{
int choice=ToInt(StringInput());
switch(choice)
{
case Difficulty::EASY:
{
gameDifficulty=Difficulty::EASY;
validInput=true;
break;
}
case Difficulty::MEDIUM:
{
gameDifficulty=Difficulty::MEDIUM;
validInput=true;
break;
}
case Difficulty::HARD:
{
gameDifficulty=Difficulty::HARD;
validInput=true;
break;
}
case Difficulty::EXPERT:
{
gameDifficulty=Difficulty::EXPERT;
validInput=true;
break;
}
case Difficulty::GOD:
{
gameDifficulty=Difficulty::GOD;
validInput=true;
break;
}
default:
{
std::cout<<"Please enter a valid choice using the number next to your desired difficulty."<<std::endl;
std::cout<<"Press ENTER to try again..."<<std::endl;
std::cin.get();
DisplayDifficulty();
}
}
}
return gameDifficulty;
}
 
As you can see they both share A LOT of things in common.  Only difference is what they return and the different cases.  I feel I am repeating entirely too much code over and over just to make sure the user selects valid input.  I know I could easily write a function that checks to see if the input is an integer.  That's no problem.  Though because every menu is different and every menu doesn't have the same amount of choices to chose from what could I do to keep from repeating the same valid Input code and the user did valid input for that given menu?
 
I might not just be thinking in a Command Line I/O mindset right now which might be why I'm stumped by something so easy.  Though from what I've been taught in programming that once you start repeating the same type of code it usually means it could somehow be wrapped into a function.  That's not the only place I repeat it.  I repeat it in multiple places.
 
Is their something I'm missing?  What would be the best way to make sure the user selected a valid input for that menu without having to repeat code over and over?
 
Thanks for any help!
 
EDIT: ToInt and StringInput are both functions that I wrote myself.  StringInput just gets the input as a string and returns in.  ToInt just takes a string and returns an int from it using a std::stringstream

 


PARTNERS