Failing Tictactoe in c++ - c++

I'm a beginner in c++, i'm trying to make a tictactoe. My program fails at the part acfter i enter input. When I enter an input, there is no next action from the program like i expected it to ("unvalid", check if win or loose, ask for input again). It only shows blank. like below: after I enter "1", nothing happens, and I can keep enter more input.
terminal example photo
I know it is a simple activity but I just ca't figure it out ToT. Thank you for helping!
//tictactoe
#include <iostream>
#include <vector>
using namespace std;
//declared variables
vector<char> out = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
int in = 2;
char player_out;
bool loose = false;
char x;
bool filled = false;
bool end(){ //won yet?
bool loose = false;
//horizontal
if (out[1] == out[2] && out[3] == out[2]){
loose = true;
}
else if (out[4] == out[5] && out[6] == out[5]){
loose = true;
}
else if (out[7] == out[8] && out[9] == out[8]){
loose = true;
}
//vertical
else if (out[1] == out[4] && out[7] == out[1]){
loose = true;
}
else if (out[2] == out[5] && out[8] == out[2]){
loose = true;
}
else if (out[3] == out[6] && out[9] == out[3]){
loose = true;
}
else if (out[1] == out[5] && out[9] == out[5]){
loose = true;
}
else if (out[3] == out[5] && out[7] == out[5]){
loose = true;
}
else{
loose = false;
}
return loose;
}
void game_start_display(){ //display the board
cout << "TIC TAC TOE\n";
cout << " | | \n";
cout << " " << out[1] << " | " << out[2] << " | " << out[3] << " \n";
cout << "______|______|______\n";
cout << " | | \n";
cout << " " << out[4] << " | " << out[5] << " | " << out[6] << " \n";
cout << "______|______|______\n";
cout << " | | \n";
cout << " " << out[7] << " | " << out[8] << " | " << out[9] << " \n";
cout << " | | \n\n";
}
int change_player(){ //take turn 1st and 2nd player
if (in == 1){
in++;
}
else{
in--;
}
return in;
}
bool filled_f() { //check if the spot is filled
if (out[x] != 'X' and out[x] != 'O'){
filled = true;
out[x] = player_out; //fill the input into the spot
}
else if (out[x] == 'X' or out[x] == 'O')
cout << "The square has already been used!\n";
filled = false;
return filled;
}
char player_out_f(){ //change output sign for each players (X, O)
if (in == 1){
player_out = 'X';
}
else if (in == 2){
player_out = 'O';
}
return player_out;
}
void c_player_display(){ //tell players to enter a number
cout << "Player " << in << "'s turn, please enter a number:\n";
}
int main(){
//intro
int loose = false;
game_start_display();
while(loose == false){ //when the game is still happening
change_player(); //change player (player start is set 2 so this comes first and change it to 1)
player_out_f(); //change player output sign (X, O)
c_player_display(); //print the line to ask for input
while(filled == false){ //when the there is no input yet (the spot is not filled)
cin >> x; // input
if (x > 0 && x < 10){ //check if input is in range 1-9
filled_f(); //check if the spot is occupied
}
else if(x < 0 && x > 10) { //if input is out of range
cout << "Invalid! Enter again!\n";
filled = false; //repeat the asking input circle (the while)
}
}
game_start_display(); //output the board again with new char (X or O)
end(); //check if anyone's won yet, if no, repeat the circle
}
cout << "Player " << in << " won! GG";
}

You have infinite loop at while (filled == false) { ... }, because filled_f always sets filled to false (and the else if branch of the condition inside this loop as well does so). It's because you most likely missed figure brackets when writing else if block in filled_f. Your indentation hints that you wanted 2 statements to be in that block, but as of now, only the first is executed conditionally, and the second (filled = false;) is executed after the branch. In other words, with intuitive indentation this function looks like this:
bool filled_f() { //check if the spot is filled
if (out[x] != 'X' and out[x] != 'O') {
filled = true;
out[x] = player_out; //fill the input into the spot
}
else if (out[x] == 'X' or out[x] == 'O')
cout << "The square has already been used!\n";
filled = false;
return filled;
}
It sets filled = false; in any case, since if/else execute (depending on condition) the statement immediately following one of them (see here), and indentation is ignored (unlike in, e.g., Python, where indentation alone determines boundaries of conditions, loops, function etc), so only cout << ... is conditionally executed. To do what you want put figure brackets around appropriate statements the same way you already did for the first if branch to create compound statement (block) from them, which is a statement itself and does what you want - groups several other statements within it, executed in sequence:
bool filled_f() { //check if the spot is filled
if (out[x] != 'X' and out[x] != 'O') {
filled = true;
out[x] = player_out; //fill the input into the spot
}
else if (out[x] == 'X' or out[x] == 'O') {
cout << "The square has already been used!\n";
filled = false;
}
return filled;
}
Additional remarks
Note that logically it's not needed to have if condition in else since if the first if condition is dissatisfied, else if condition is definitely satisfied (look De Morgan's Laws) and you can just write else:
// ...
else {
cout << "The square has already been used!\n";
filled = false;
}
// ...
Also in your main loop, you use this:
if (x > 0 && x < 10){ //check if input is in range 1-9
filled_f(); //check if the spot is occupied
}
else if(x < 0 && x > 10) { //if input is out of range
cout << "Invalid! Enter again!\n";
filled = false; //repeat the asking input circle (the while)
}
to test whether x is within range, but your condition in else if is wrong (should be x <= 0 || x >= 10 instead of x < 0 && x > 10) and can be omitted altogether (again see De Morgan's Laws) by using just else.

Related

calling function on while loop

I'm making a calculator program but I already encounter a problem. Well, my code is in a loop that will call a function to display the choices and then ask the user to pick, a/s/m/d are the choices. If the input is on the choices, it will proceed to the next step. Otherwise, it will loop and then call the function again.
#include <iostream>
using namespace std;
void home()
{
cout << "\nChoose your operation:" << endl;
cout << "\tType [A] for Addition" << endl;
cout << "\tType [S] for Subtraction"<< endl;
cout << "\tType [M] for Multiplication" << endl;
cout << "\tType [D] for Division" << endl;
}
int main()
{
char operation;
bool no_operator = true;
int design = 73;
for (int i = 0; i < design; i++){
if (i == 25){
cout << " WELCOME TO CALCULATOR ";
i += 22;
}
else i == 72 ? cout << "*\n" : cout << "*";
}
while (no_operator){
home();
cout << "\nOperation: ";
cin >> operation;
if (operation == 'A' || operation == 'a')
{
cout << "\nIt will going to add numbers";
no_operator = false;
}
else if (operation == 'S' || operation == 's')
{
no_operator = false;
cout << "\nIt will going to subtract numbers";
}
else if (operation == 'M' || operation == 'm')
{
no_operator = false;
cout << "\nIt will going to multiply numbers";
}
else if (operation == 'D' || operation == 'd')
{
no_operator = false;
cout << "\nIt will going to divide numbers";
}
else
{
cout << "\tInvalid Input: You must enter A/S/M/D only\n";
//home();
}
}
return 0;
}
My problem is it will run the '''home()''' in else statement even if the input is correct on the second loop.
I want to stop the '''home()''' to be called when the input is correct
Your code works perfectly fine. Make sure you're inputting the correct letters.
Also for this code, a "do while()" loop would be better.
You program is working perfectly fine as the input is correct it does not show the home rather print the message it will going to divide etc.

Why does my game keep going even when there is no more spaces to fill

So, to further explain my question, when I fill my whole board in tic tac toe with "X" and "O" and there is no winner, the game keeps on playing even when the spaces are filled. It just keeps saying enter a row and column still. It doesn't know when to stop. I'm not sure whats wrong with my code.
Problems where I think it is: I think my problem lies in my checkWinner function because my bool winner = false is suppose return my statement "Its a tie" if every space on my board is filled but it doesn't output that. It also may be my main function.
How do I fix this problem because I've been stuck trying to figure it out. So if anyone can help, I appreciate it. Thanks!
#include <iostream>
#include <string>
using namespace std;
const int ROWS = 3; // For the number of rows.
const int COLS = 3; // For the number of columns.
void showBoard(char[][COLS], int); // Shows the board.
void playerChoice(char[][COLS], char); // shows the player choice.
bool checkWinner(char[][COLS], string&); // check the winner.
char board[ROWS][COLS] = { { '*', '*', '*' }, { '*', '*', '*' }, { '*', '*', '*' } };
int main()
{
char board[ROWS][COLS] = { { '*', '*', '*' }, { '*', '*', '*' }, { '*', '*', '*' } }; // displays
whats inside the board.string gwinner = " "; // holds the winner until there is a winner.
bool winner;
int counter = 1;
showBoard(board, 3); // displays the board.
playerChoice(board, 'X');
showBoard(board, 3);
while (counter) {
playerChoice(board, 'O');
showBoard(board, 3);
if (winner = checkWinner(board, gwinner))
break;
playerChoice(board, 'X');
showBoard(board, 3);
if (winner = checkWinner(board, gwinner))
break;
}
cout << gwinner;
}
void showBoard(char arr[][COLS], int SIZE) // Displays the board.
{
for (int row = 0; row < SIZE; row++) {
for (int col = 0; col < SIZE; col++)
cout << '|' << arr[row][col];
cout << '|' << endl;
}
}
void playerChoice(char arr[][COLS], char name) // what row and column the user wants.
{
int row, columns; // for the user to enter the row and column.
int occupied;
do {
cout << "What row would you like?\n";
cout << "Row: ";
cin >> row;
while (row < 1 || row > 3) // input validation.
{
cout << "Error please pick a row between 1 and 3.\n";
cout << "Row: ";
cin >> row;
cout << endl;
}
cout << "What column would you like?\n";
cout << "Column: ";
cin >> columns;
while (columns < 1 || columns > 3) // input validation.
{
cout << "Error,please pick a column between 1 and 3.\n";
cout << "Column: ";
cin >> columns;
cout << endl;
}
if (arr[row - 1][columns - 1] == '*') // checks to see if * is empty
{
arr[row - 1][columns - 1] = name; // diplays either X or O
occupied = 1;
}
else {
cout << "\nThis space is occupied.\n";
cout << "Please select again\n";
occupied = 0;
}
} while (occupied == 0);
}
bool checkWinner(char arr[][COLS], string& gwinner) // Check if the winner met the right conditions
{
bool winner = false;
if ((arr[0][0] == arr[0][1]) && (arr[0][1] == arr[0][2]) && (arr[0][1] != '*')) // checks row
{
winner = true;
cout << "The winner is:" << arr[0][0] << endl;
}
else if ((arr[1][0] == arr[1][1]) && (arr[1][1] == arr[1][2]) && (arr[1][1] != '*')) // checks row
{
winner = true;
cout << "The winner is:" << arr[1][0] << endl;
}
else if ((arr[2][0] == arr[2][1]) && (arr[2][1] == arr[2][2]) && (arr[2][1] != '*')) // checks row
{
winner = true;
cout << "The winner is:" << arr[2][0] << endl;
}
else if ((arr[0][0] == arr[1][0]) && (arr[1][0] == arr[2][0]) && (arr[1][0] != '*')) // checks columns
{
winner = true;
cout << "The winnner is:" << arr[0][0] << endl;
}
else if ((arr[0][1] == arr[1][1]) && (arr[1][1] == arr[2][1]) && (arr[1][1] != '*')) // checks
columns
{
winner = true;
cout << "The winnner is:" << arr[0][1] << endl;
}
else if ((arr[0][2] == arr[1][2]) && (arr[1][2] == arr[2][2]) && (arr[1][2] != '*')) // checks
columns
{
winner = true;
cout << "The winnner is:" << arr[0][2] << endl;
}
else if ((arr[0][0] == arr[1][1]) && (arr[1][1] == arr[2][2]) && (arr[1][1] != '*')) // checks
diagonal
{
winner = true;
cout << "The winnner is:" << arr[0][0] << endl;
}
else if ((arr[2][0] == arr[1][1]) && (arr[1][1] == arr[0][2]) && (arr[1][1] != '*')) // checks
diagonal
{
winner = true;
cout << "The winnner is:" << arr[2][0] << endl;
}
else {
gwinner = "It's a Tie."; // else if the winner is a tie.
winner = false;
}
return winner; // returns the winner
}

How to compare char array to cstring and loop program

My program is supposed take a user input to create a password. There's specific criteria.
The user should be able to retry up five times to create a "good" password. If they make a "good" password, the program should just end. If they don't make a password within the 5 tries, then the program should end. I tried using do-while and a for loop, but it won't break or end the program.
I have a text file with 5 passwords. The user can't use those 5 passwords. I put the passwords into an char array. I'm not sure how to compare the passwords in the file to the user input.
I can only use cstrings for this program. I'm not allowed to use any strings.
"prevPswds.txt"
2347UCDa!
PassUCD97~
#489sqUCD
123AaaUCD$%
UCDAsue1,
main.cpp:
#include <iostream>
#include <cstring>
#include <cctype>
#include <fstream>
//#include <string.h>
using namespace std;
int main()
{
//Initialize variables
const int size = 15;
char* check = NULL;
char checkUCD[] = "UCD";
char specialChar[] = { '~', '!', '#', '#', '$', '%', '^', '&', '*', '-', '_', '?' };
char password[size];
int counter=0;
bool length = false;
bool uppercase = false;
bool lowercase = false;
bool number = false;
bool special = false;
bool ucd = false;
bool previous = false;
bool lower = false;
bool upper = false;
bool num = false;
//bool done = false;
ifstream file("prevPswds.txt");
const int arraySize = 150;
char myArray[arraySize];
char current_char;
int count = 0;
//Read in file
for (int k = 0; k < arraySize; k++)
{
if (file.is_open())
{
int c = 0;
while (!file.eof())
{
file.get(myArray[c]);
c++;
count++;
}
}
}
for (int i = 0; i < 5; i++)
{
cout << "----CREATE A PASSWORD----" << endl;
cout << "Password requires:" << endl;
cout << "-8 to 12 characters" << endl;
cout << "-At least 1 uppercase letter" << endl;
cout << "-At least 1 lowercase letter" << endl;
cout << "-At least 1 number" << endl;
cout << "-At least 1 special character (~, !, #, #, $, %, ^, &, *, -, _, ?)" << endl;
cout << "-'UCD' \n" << endl;
cout << "Password cannot include:" << endl;
cout << "-Lowercase letters 'l,' 'i,' 'o,' or 'z'" << endl;
cout << "-Uppercase letters 'I,' 'O,' or 'S'" << endl;
cout << "-Numbers '0,' '1,' or '5'" << endl;
cout << "-------------------------" << endl;
//Get user input
cout << "Please enter a password." << endl;
cin.getline(password, size);
cout << endl;
counter++;
//Check requirements
if (strlen(password) < 8 || strlen(password) > 12)
{
cout << "-Password must be 8 - 12 characters." << endl;
}
else
{
length = true;
}
for (int i = 0; i < size; i++)
{
if (isupper(password[i])) //Check for uppercase
{
uppercase = true;
}
if (islower(password[i])) //Check for lowercase
{
lowercase = true;
}
if (isdigit(password[i])) //Check for numbers
{
number = true;
}
if (password[i] != 'l' || password[i] != 'i' || password[i] != 'o' || password[i] != 'z') //Check for exceptions
{
lower = true;
}
if (password[i] != 'I' || password[i] != 'O' || password[i] != 'S') //Exceptions
{
upper = true;
}
if (password[i] != '0' || password[i] != '1' || password[i] != '5') //Exceptions
{
num = true;
}
}
for (int i = 0; i < size; i++) //Check for special characters
{
if (specialChar[i])
{
if (ispunct(password[i]))
{
special = true;
}
}
}
check = strstr(password, checkUCD); //Check for 'UCD'
if (check)
{
ucd = true;
}
//Give feedback and suggestion
if (uppercase == false)
{
cout << "Password must contain at least 1 uppercase letter." << endl;
}
if (lowercase == false)
{
cout << "Password must contain at least 1 lowercase letter." << endl;
}
if (number == false)
{
cout << "Password must contain at least 1 number." << endl;
}
if (special == false)
{
cout << "Password must contain at least 1 special character." << endl;
}
if (ucd == false)
{
cout << "Password must contain 'UCD.'" << endl;
}
if (lower == false)
{
cout << "Password cannot contain 'l', 'i', 'o', or 'z.'" << endl;
}
if (upper == false)
{
cout << "Password cannot contain 'I', 'O', or 'S.'" << endl;
}
if (num == false)
{
cout << "Password cannot contain '0', '1' or '5.'" << endl;
}
}
if (length == true || uppercase == true || lowercase == true || number == true || special == true || ucd == true || previous == true || lower == true || upper == true || num == true)
{
return 1;
}
}
This is getting a bit long, so I have tried to add some small headers so you can jump to the next issue easier.
First thing first: Why is “using namespace std;” considered bad practice? Do yourself a favor and stop using it. It will be much harder to change if you let it become an ingrown habit, and at some point you will run into trouble and be forced to change.
Secondly, you have also run somewhat afoul of: Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong? I think that your code actually does work, but I also think that it is a bit by chance.
for (int k = 0; k < arraySize; k++)
{
if (file.is_open())
{
int c = 0;
while (!file.eof())
{
file.get(myArray[c]);
c++;
count++;
}
}
}
The outer loop starts at k=0, then we arrive at the inner loop, where you read all the characters in the file - and then you read one character more, because eof is only set when you try to read beyond the end (with get). However, since you don't try to process that character here, you don't notice that the last read failed - though your count may be off by one.
Once the inner loop terminates, you then go back to the outer loop and set k=1. But since you have already read the whole file, the inner loop is simply skipped. And so on for k=2 to arraySize.
As you can see, the file reading has some problems, so don't do it like that. :)
Another consideration is that you probably don't want a single array of characters mashed together, it may be more desirable to have the five old passwords individually - and they are nicely all on their own line in the file.
My suggestion is that since you have 5 old passwords (can this number change?) that can be up to 12 or size (can this number change?) characters long, then you change myArray to char myArray[5][size]{}. Then use getline to read the old passwords, like so:
for (int k = 0; k < 5 && file.getline(myArray[k], size); k++)
{}
I think this will make your compare job easier, as you only have to loop over the five arrays, and compare myArray[k][i] == password[i].
Third issue is your checks. I would simplify them - unless you have a good reason for wanting to be able to see which ones failed later. Instead of:
if (isupper(password[i])) //Check for uppercase
{
uppercase = true;
}
if (islower(password[i])) //Check for lowercase
{
lowercase = true;
}
...
if (uppercase == false)
{
cout << "Password must contain at least 1 uppercase letter." << endl;
}
if (lowercase == false)
{
cout << "Password must contain at least 1 lowercase letter." << endl;
}
...
if (length == true || uppercase == true || lowercase == true || number == true || special == true || ucd == true || previous == true || lower == true || upper == true || num == true)
{
return 1;
}
Change it to:
if (!isupper(password[i])) //Check for uppercase
{
passwordIsGood = false;
cout << "Password must contain at least 1 uppercase letter." << endl;
}
if (!islower(password[i])) //Check for lowercase
{
passwordIsGood = false;
cout << "Password must contain at least 1 lowercase letter." << endl;
}
...
if (passwordIsGood)
{
return 1;
}
It will make your code more unified, and easier to read.
Fourth: It will also make it easier to fix the bug that you don't reset the booleans on each "create password" loop. You set f.ex. length = false when you declare the variable, then length = true after checking that it is correct. But then if that password fails on some other issue length is never reset, so the next password can be the wrong length but length is already true so the check fails.
The fifth problem is that you have placed your check if outside the password loop. The structure of your program is:
for (int i = 0; i < 5; i++)
{
cout << "----CREATE A PASSWORD----" << endl;
... lots of lines ...
}
if (length == true || uppercase == true || lowercase == true || number == true || special == true || ucd == true || previous == true || lower == true || upper == true || num == true)
{
return 1;
}
So you always loop five times through "CREATE A PASSWORD" before you check if the requirements are fulfilled.
My recomendation here is to refactor.
Move all your password checking into a function of its own:
bool checkPassword(char* password, int size)
{
if (strlen(password) < 8 || strlen(password) > 12)
{
cout << "-Password must be 8 - 12 characters." << endl;
return false;
}
for (int i = 0; i < size; i++)
{
if (!isupper(password[i])) //Check for uppercase
{
cout << "Password must contain at least 1 uppercase letter." << endl;
return false;
}
...
}
...
return true;
}
Then your loop becomes:
for (int i = 0; i < 5; i++)
{
cout << "----CREATE A PASSWORD----" << endl;
...
//Get user input
cout << "Please enter a password." << endl;
cin.getline(password, size);
cout << endl;
counter++;
//Check requirements
bool passwordIsGood = checkPassword(password, size);
if (passwordIsGood)
{
return 1;
}
}
Now it suddenly is much easier to see what is going on.
The sixth problem is that some of your checks don't do what you want. Specifically the ones like this:
if (password[i] != 'l' || password[i] != 'i' || password[i] != 'o' || password[i] != 'z')
Note that only one of the conditions in an OR has to be true for the OR to be true. If a=1, then a!=1 is false, but a!=2 is true. This means that a != 1 || a != 2 is true. a would have to be both 1 and 2 at the same time for a != 1 || a != 2 to be false.
One option for getting the behavior you want is to change the check to:
if (!(password[i] == 'l' || password[i] == 'i' || password[i] == 'o' || password[i] == 'z'))
That became way longer than I had intended... I hope it helps you at least some. :)
if (length == true || uppercase == true || lowercase == true || number == true || special == true || ucd == true || previous == true || lower == true || upper == true || num == true)
{
//return 1; take this line out and place after all {}
i = 5; //should end the for loop
}
}
return 1;

how to get output when user just presses enter in c++

I am trying to build a simple code that gives the coordinates in two dimensions after you put some direction input.
The problem is I don't know how to give the proper output when the user just presses enter. This should be (0,0) because if the user just presses enter it means he has not changed the coordinates. How can I know if the user has just pressed enter and give the proper output accordingly?
This is the code I have done:
#include <iostream>
using namespace std;
int main ()
{
int a = 0, b = 0;
string direction;
if( cin >> direction) {
if( !direction.empty() ) {
// handle input correctly
// Interpret directions
for (int i = 0; i < direction.length(); i++) {
if (direction[i] == 'e') a++;
else if (direction[i] == 's') b++;
else if (direction[i] == 'w') a--;
else if (direction[i] == 'n') b--;
}
}
else if (direction.empty()) cout << "(0,0)" << endl;
}
// Output coordinates
cout << "(" << a << "," << b << ")" << endl;
}
The operation cin >> direction; ignores spaces and also empty lines. Here the string direction is not empty whitespace terminated word.
It is possible to read entire line using std::getline. This function reads line from stream and also it reads empty lines.
So, the solution:
int a = 0, b = 0;
string direction;
getline(cin, direction);
if(!direction.empty()) {
// Interpret directions
for (int i = 0; i < direction.length(); i++) {
if (direction[i] == 'e') a++;
else if (direction[i] == 's') b++;
else if (direction[i] == 'w') a--;
else if (direction[i] == 'n') b--;
}
}
// else is not needed, since here a = 0 and b = 0.
// Output coordinates
cout << "(" << a << "," << b << ")" << endl;
What you need to do is wrap an if around your attempt to get input, then if that succeeds, check whether or not the string the input is put in is empty or not. If it is empty you know that the user pressed enter without giving any other input. In code that would be something like:
if( cin >> input) {
if( !input.empty() ) {
// handle input correctly
}
}
If you want to know why it's done that way, google it in the "C++ super FAQ" at isocpp.org.

C++ Function being called when it isn't supposed to

I'm nearly finished working on a small guessing game, but i have run into a problem I don't know how to work around.
The problem is with the check_guess function that is checking to make sure the guess being input is a number between 1 and 100.
When running the program the first time, everything works fine.
http://i.imgur.com/pprunDT.png (I would post images if my reputation weren't so low)
But every time after, where yes to play again is chosen, the program runs through the check_guess function and displays "Invalid Input" when it shouldn't
http://i.imgur.com/8OSnSJt.png
I'm not sure why the program is behaving this way.
The code for the entire program is here:
#include <iostream>
#include <cstdlib> //for rand
#include <ctime> //for time
#include <string>
#include <sstream> //for conversions from string to int
using namespace std;
int check_guess(int tries) { //function for limiting the input of guess
string guess = "";
int result = 0;
do {
getline (cin, guess);
istringstream convert(guess);
if ( !(convert >> result) || (result < 1 || result > 100) ) {
result = 0;
cout << "Invalid Input.\n" << endl;
cout << "You have " << tries << " tries: ";
}
} while (result == 0);
return result;
}
bool play_again() { //function for limiting the input of mode
bool quit;
string yn;
do {
cin >> yn;
if ( yn == "y" || yn == "yes" ) {
quit = false;
}
else if ( yn == "n" || yn == "no" ) {
quit = true;
}
else {
yn = "invalid";
cout << "Invalid input.\n\nEnter 'y' or 'n': ";
}
} while ( yn == "invalid" );
return quit;
}
int main()
{
srand(time(0)); //sets seed to be random
int mystery = 0; //defines mystery number
int guess = 0; //defines guess
int tries = 5; //defines trys
bool quit = false; //defines replay or quit
cout << "----------------------------------\n";
do { //while mode is not set to quit, keep playing
tries = 5; //resets tries each new game
mystery = rand() % 100 + 1; //sets mystery number to be random
guess = 0;
cout << "Pick a number between 1 and 100.\n\nYou have 5 tries: ";
while (tries != 0) { //loops until you have no tries left
guess = check_guess(tries);
if (guess == mystery) { tries = 0; } //if you guess right it ends the loop
else { tries--; } //guessing wrong lowers tries by 1
if ( tries != 0 && guess > mystery) {
cout << guess << " is too high.\n" << endl;
cout << "You have " << tries << " tries: ";
}
if ( tries != 0 && guess < mystery) {
cout << guess << " is too low.\n" << endl;
cout << "You have " << tries << " tries: ";
}
}
if (guess == mystery) { //if guess == mystery by time loop ends you win
cout << "Got it! You Win!\n" << endl;
}
else { //if not, you lose
cout << "You Lose! The number was: " << mystery << ".\n" <<endl;
}
cout << "-------------------\n";
cout << "Play Again?(y/n): "; //ask user to play again
quit = play_again();
cout << "-------------------\n";
if (quit == false)
cout << endl;
} while (quit == false);
cout << "----------------------------------" << endl;
return 0;
}
I'm not sure how to fix this.
this line:
cin >> yn;
only reads the 'y' but not the end of line. As a result, the next execution of this instruction
getline (cin, guess);
initializes guess to an empty string.
On line 19, import the code "cin.ignore();" without quotations.
So your code reads as
`int check_guess(int tries) { //function for limiting the input of guess
string guess = "";
int result = 0;
do {
getline (cin, guess);
istringstream convert(guess);
if ( !(convert >> result) || (result < 1 || result > 100) ) {
result = 0;
cin.ignore();
cout << "Invalid Input.\n" << endl;
cout << "You have " << tries << " tries: ";
}
} while (result == 0);
return result;
}
`
and so on. This stops input into the console briefly. You're code is reading the 'y' to try again as the input for the number when you restart as well. Putting in the little line cin.ignore(), stops it from inputting y twice.
Change play_again() to:
bool play_again() { //function for limiting the input of mode
bool quit;
string yn;
do {
getline (cin, yn);
if ( yn == "y" || yn == "yes" ) {
quit = false;
}
else if ( yn == "n" || yn == "no" ) {
quit = true;
}
else {
yn = "invalid";
cout << "Invalid input.\n\nEnter 'y' or 'n': ";
}
} while ( yn == "invalid" );
return quit;
}