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;
}
|