console not returning expected number of characters in cin buffer

I am creating a console version of "Bull Cow Game". In the game, the user has a certain number of tries to guess what the secret word is. Every time they guess, the program returns the number of "Bulls" and "Cows" they guessed correctly. The user gets a "Bull" for every character that they guess in the right place and a "Cow" for every character that they guess correctly but is not in the right place.

My problem is in "main.cpp" in the getGuess() function. In the do-while loop, the program is supposed to loop if the user inputs anything other than the number of characters in "answer". When I run my program, I get some unexpected and confusing results:

1) No matter what I input for the FIRST "guess", the program tells me that cin's gcount() is 0 or 1 characters after setw(). I could input 50 characters or 2 and the program would output the same result. If the gcount is 1, then this counts as one of the allotted guesses which is an undesirable result. If the cin.gcount() is 0, the program correctly does not count the guess as valid but I am still confused as to why the cin.gcount() is 0 at all.

2) If I change the number of characters in my guess from the PREVIOUS guess, the program tells me that the cin.gcount() is whatever the cin.gcount() was after the PREVIOUS guess instead of after current guess. This is also an undesirable result since if the user decides to input the correct number of characters, the program will not accept the user's guess as valid.

I am confused as to why this is happening since isn't cin.ignore() supposed to dump all of the extraneous characters that setw() doesn't accept? Why would the number of characters in the cin buffer carry over from one guess to the other?

Please let me know if any of you can illuminate what is going on.

Here are the relevant files:

main.cpp
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#include <iostream>
#include <limits>
#include <iomanip>
#include <algorithm>
#include <string>
#include "BullCowGame.h"

using namespace std;

void printIntro();
string getGuess();
void playGame();
void gameLoop(const int NUM_OF_TURNS, string answer);
bool askToPlayAgain();
void winStatement();

int main()
{
	printIntro();

	playGame();
	
	return 0;
}


void printIntro()
{
	constexpr int WORD_LENGTH = 4;

	cout << "Welcome to Bulls and Cows, a fun word game.\n" << endl;
	cout << "Can you guess the " << WORD_LENGTH << " letter isogram I am thinking of?\n" << endl;
	cout << "Note: Enter 'exit' to exit the game at any time. No questions asked\n" << endl; 
}

void playGame()
{
	constexpr int NUM_OF_TURNS = 3;
	string answer = "milk";

	cout << endl;

	//user guesses until success or failure
	gameLoop(NUM_OF_TURNS, answer);

	bool playAgain = askToPlayAgain();

	//if user selects to play again, recurse and play the game again
	if (playAgain == true)
	{
		playGame();
	}

}

string getGuess()
{
	string guess = "";
	
	const int MAX_LENGTH = 4; 

	/*ensures that "guess" is the same length as answer. This
	will make it so that the program avoids comparing "guess"
	to "answer" if "guess" has more characters than "answer".
	*/
	
	bool endLoop = false; 

	do {
		cout << "Enter a word containing exactly " << MAX_LENGTH << " characters: ";

		cin >> setw(MAX_LENGTH) >> guess;

		cout << "cin.gcount() after 
setw(): " << cin.gcount() << " characters" << endl;

		/*ensures that the only character in the cin is '\n'. Otherwise
		do-while loop continues*/
		if (cin.gcount() != 1)
		{
			cout << "Invalid number 
of characters. Please input exactly " << MAX_LENGTH << " characters" << endl;
		}
		else
		{
			endLoop = true; 
		}

		cin.ignore(numeric_limits<streamsize>::max(), '\n');

		cout << "cin.gcount() after cin.ignore(): " << cin.gcount() << 
" characters" << endl;

		cout << "guess: " << guess << endl;

		cout << endl; 

	} while ( endLoop == false );


	cout << endl;


	return guess; 
}

void gameLoop(const int NUM_OF_TURNS, string answer)
{
	for (int i = 0; i < NUM_OF_TURNS; i++)
	{
		/*user is asked to input guess again if they enter
		an invalid string*/
		bool correctInput = false;
		
		do {
			BullCowGame bullCowGame;

			string guess = getGuess();

			//if user inputs "exit", game exits
			if (guess == "exit")
			{
				i = NUM_OF_TURNS - 1;
				correctInput = true; 
			}
			//checks to ensure user is 
inputting only alphabetic characters
			else if (all_of(guess.begin(), guess.end(), isalpha) == false)
			{
				cout << "Please input valid 
guess. Guess may only contain alphabetical characters" << endl;
			}
			//if user inputs anything other than "exit" and
 the string is valid, the game continues
			else
			{

				bullCowGame.setNumOfCows(guess, answer);
				bullCowGame.setNumOfBulls(guess, answer);

				cout << "Number of Bulls: " 
<< bullCowGame.getNumOfBulls() << "  Number of Cows: " << bullCowGame.getNumOfCows() << endl;

				if (bullCowGame.getNumOfBulls() == answer.size())
				{
					winStatement();
					//if user has won, then for loop ends
					i = NUM_OF_TURNS - 1;
				}

				cout << endl;

				correctInput = true; 
			}
		} while (correctInput == false);

	}
}

bool askToPlayAgain()
{
	bool correctEntry = false;
	bool playAgain = false;
	
	//if incorrect input is given, ask for answer again
	while (correctEntry == false)
	{
		cout << "Do you want to play again?";
		string response = "";
		getline(cin, response);

		if (response == "yes" || response == "Yes")
		{
			playAgain = true;
			correctEntry = true;
		}
		else if (response == "no" || response == "No")
		{
			playAgain = false;
			correctEntry = true;
		}
		else
		{
			//if incorrect input is given, 
ask for answer again
			cout << "Please input either 
'yes' or 'no'\n" << endl;

		}
	}
	
	return playAgain;
	
}


void winStatement()
{
	cout << "YOU WIN!!!!!!!" << endl;
	cout << endl; 
}


BullCowGame.h
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
#ifndef BULL_COW_GAME_H
#define BULL_COW_GAME_H

#include <string>

using namespace std; 

class BullCowGame
{
public:
	BullCowGame() = default;
	BullCowGame(int initialBull, int initialCow);
	
	void setNumOfCows(string guess, string answer);
	int getNumOfCows();
	void setNumOfBulls(string guess, string answer);
	int getNumOfBulls();


		
private:
	int storedBulls = 0;
	int storedCows = 0;
	
	
};

#endif	 


BullCowGame.cpp
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
48
49
50
51
52
53
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include "BullCowGame.h"

using namespace std;

BullCowGame::BullCowGame(int initialBull = 0, int initialCow = 0)
	:storedBulls{ initialBull }, storedCows{ initialCow } {}

void BullCowGame::setNumOfCows(string guess, string answer)
{
	/*examines each character index location in both strings
	to see if there are two characters that are common
	in both words, albeit located at different index locations*/
	for (unsigned int i = 0; i < guess.size(); i++)
	{
		if (guess[i] != answer[i])
		{
			for (unsigned int j = 0; j < guess.size(); j++)
			{
				if (guess[i] == answer[j])
				{
					storedCows++;
				}

			}
		}
	}

}

int BullCowGame::getNumOfCows()
{
	return storedCows;
}

void BullCowGame::setNumOfBulls(string guess, string answer)
{
	for (unsigned int i = 0; i < answer.size(); i++)
	{
		if (guess[i] == answer[i])
		{
			storedBulls++;
		}
	}
}

int BullCowGame::getNumOfBulls()
{
	return storedBulls;
}
Last edited on
I really don't understand why you're making your getGuess() function so difficult. Why not something simpler, maybe something like:

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
#include <iostream>
#include <string>

std::string getGuess(size_t answer_length)
{
	std::string guess;

	/*ensures that "guess" is the same length as answer. This
	will make it so that the program avoids comparing "guess"
	to "answer" if "guess" has more characters than "answer".
	*/
    while(guess.length() != answer_length)
    {
        std::cout << "Please enter your guess, must be " << answer_length << " long: ";
        getline(std::cin, guess);
    }


	return guess;
}

int main()
{
    std::cout << getGuess(4) << std::endl;
}

Last edited on
They pointed that out on Stack Overflow too. After they posted it, I realized there was no reason for it to be so complex anymore since I don't have to worry about too many characters being placed in the cin buffer.
Topic archived. No new replies allowed.