Programming Project Help

Hello c++,
This is my first post, so I figure I would start by saying Hello. I'm a student at Auburn University in a C++ class, and I've come here to get some advice as I am new to the C language. I'm almost done with my project, which is a text based video game. I currently have 4 classes to run this program. Player, Hall, Menu and Engine. The class Menu is a class to display the options available in the menu based game, and return the value entered by the user. Currently, if you enter a value that is not contained in the menu, my program goes haywire in a infinite loop that I can't figure out. I need to filter the input of the user to make sure that they enter a desired value so I wrote a function called bool isValidInput(int input). I can't figure out why my function isn't looping until the input I enter is valid. I think it has to do something with the fact that it gets the input from cin, and if that input it wrong it can't reset menuChoice using cin again because it already set menuChoice??? Help please!!! Here is a snippit of my code so you can get an idea of whats going on:

bool Menu::isValidInput(int input)
{
bool valid;
if (input == 1)
{
valid = true;
}
else if (input == 2)
{
valid = true;
}
else if (input == 3)
{
valid = true;
}
else if (input == 4)
{
valid = true;
}
else if (input == 5)
{
valid = true;
}
else
{
valid = false;
}
return valid;
}


int Menu::gameMenu()
{
int menuChoice = 0;

cout << "1) Move (takes time, could be risky...) " << endl;
cout << "2) Read technical papers (boost intelligence, takes time) " << endl;
cout << "3) Search for loose change (boost money, takes time) " << endl;
cout << "4) View Character " << endl;
cout << "5) Quit the game " << endl;
cout << "\nPlease choose an action: ";
do
{
cin >> menuChoice;
}
while(isValidInput(menuChoice) == false);
return menuChoice;
}
Make sure to add a cin.clear(); cin.sync(); in the do-while loop after the input. That way if they enter a character instead of an int, it can still recover from the error that occurs.
Thanks! Now it works fine for all integers that are inputted. But what about if a char or string is entered on accident? Say you enter 'c', then try and enter 1 to start the game. It won't change the value of menuChoice from c to 1. Is there a way to make menuChoice a general type so it can change from all variable types, but since i'm using isValidInput() it will only be set to a integer.....??
Last edited on
When you enter c, that is invalid input, and the stream goes into a state of error when trying to extract an integer. cin.clear() clears that state of error so you can use the stream again, then cin.sync() lines it back up again for the second go. Because you started your menuChoice at 0, and the extraction failed, it should still be 0, thus the isValidInput(menuChoice) should return false. This means that the loop should go around and try to take input again, thus you *should* be able to just type 1. If it doesn't work, then I'm not sure why, and I'll have to do a bit more testing.
I tried putting cin.clear(); cin.sync(); before and after the cin >> menuChoice; and neither worked. Heres a sample of my interactions:

MAIN MENU:
1) Start a New Game of Dunstan and Dragons!
2) View top 5 High Scores
3) Quit

Please choose an option: x
2
2
2

But if I were to enter a integer the entire time it wouldn't mess up at all. I think it is because once I initialize menuChoice as a char it freaks out and won't let me reinitialize it to an int??
anyone?
Last edited on
closed account (3hM2Nwbp)
(Bumping isn't really necessary here, topics not marked as resolved are distinguished on their own. Speaking of that, if this works for you can you tick the 'Resolved' button? Thanks :) )

Try this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <limits> // <-- for numeric_limits<T>::max()
bool Menu::isValidInput(int input)
{
  return input > 0 && input < 6; // <-- Instead of linked 'ifs'
}


int Menu::gameMenu()
{
int menuChoice = 0;

cout << "1) Move (takes time, could be risky...) " << endl;
cout << "2) Read technical papers (boost intelligence, takes time) " << endl;
cout << "3) Search for loose change (boost money, takes time) " << endl;
cout << "4) View Character " << endl;
cout << "5) Quit the game " << endl;
cout << "\nPlease choose an action: ";

cin >> menuChoice;
while(!cin || !isValidInput(menuChoice))
{
  cin.clear(); // <-- Reset the input stream's error flags
  cin.ignore(numeric_limits<streamsize>::max(), '\n'); // <-- Ignore everything remaining in the stream
  cin >> menuChoice;
}
return menuChoice;
} 
Last edited on
Hmm, still didn't seem to fix the problem. Thanks for the reply though... I tried making menuChoice char instead of int to see if it would work, but that didn't either. I feel like menuChoice needs to be some generic type instead of int so that if a char is inputted menuChoice won't freak out by being initialized to a char.
does anyone have any more advice??? i'm at a standstill here....
closed account (iw0XoG1T)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int Menu::gameMenu()
{
    int menuChoice = 0;

    std::cout << "2) Read technical papers (boost intelligence, takes time) " << endl;
    std::cout << "3) Search for loose change (boost money, takes time) " << endl;
    std::cout << "4) View Character " << endl;
    std::cout << "5) Quit the game " << endl;
    std::cout << "\nPlease choose an action: ";
    do
    {
        cin >> menuChoice;
        if(!menuChoice)
        {
            cin.clear();
            cin.ignore();
        }
    }
    while(!isValidInput(menuChoice));
    return menuChoice;
}
instead of making menuChoice an int, why not make it a char and test it like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
bool Menu::isValidInput(char input)
{
bool valid;

if (input == '1')
{
    valid = true;
}
else if (input == '2')
{
    valid = true;
}
else if (input == '3')
{
    valid = true;
}
else if (input == '4')
{
    valid = true;
}
else if (input == '5')
{
    valid = true;
}
else
{
    valid = false;
}
return valid;
}
char Menu::gameMenu()
{
char menuChoice = '0';

cout << "1) Move (takes time, could be risky...) " << endl;
cout << "2) Read technical papers (boost intelligence, takes time) " << endl;
cout << "3) Search for loose change (boost money, takes time) " << endl;
cout << "4) View Character " << endl;
cout << "5) Quit the game " << endl;
cout << "\nPlease choose an action: ";
do
{
cin >> menuChoice;
}
while(isValidInput(menuChoice) == false);
return menuChoice;
}



then add whatever cin.sync fixes or whatever you want, plus a converter that takes the char returned from gameMenu and turns it into a int like this:

1
2
3
4
5
char cChoice = gameMenu();
int nChoice;
if (cChoice=='1') nChoice=1;
if (cChoice=='2') nChoice=2;
// etc... 


i came into this conversation late, but you should get the basics of what im saying
closed account (S6k9GNh0)
Is the project small enough to send entirely? It's kinda hard to know exactly what's not working when we don't have a test case...
This worked fine for me:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//Example program

#include <iostream>

using namespace std;

//notice this is now a global function
bool isValidInput(int i) {
	return 1 <= i && i <= 5;
}

//same here
int gameMenu() {
	int menuChoice = 0;

	cout << "1) Move (takes time, could be risky...) " << endl;
	cout << "2) Read technical papers (boost intelligence, takes time) " << endl;
	cout << "3) Search for loose change (boost money, takes time) " << endl;
	cout << "4) View Character " << endl;
	cout << "5) Quit the game " << endl;
	cout << "\nPlease choose an action: ";
	do {
		cin.clear();
		cin.sync();
		cin >> menuChoice;
	} while( !isValidInput(menuChoice) );
	return menuChoice;
}

int main() {
	gameMenu(); //void context
	cout << "Done.";
	return 0;
}

Are you sure the problem is in this part of the code?
Last edited on
Thanks for all the responses! Making menuChoice a char type changed everything.... Now I can enter string and char values, before a int is entered and MenuChoice is set to the right value. Thanks again for all the responses! Sorry I didn't give more of my code, it's 900 lines almost and I didn't really think it was necessary to submit all of it.
Topic archived. No new replies allowed.