Hello,
I am writing an assignment for a tic-tac-toe game. I am trying to use cin.fail() in an if/else clause to check for invalid input. In my code, I use if( cin.fail() ), then cin.clear(), then while( cin.get() != '\n' ) ; to clear the input buffer. Then I have an else block. I am using cin to get an integer. If I enter just letters for input (which should change cin to the fail state), everything works fine. However, if I enter a number followed by a letter (which should also change cin to the fail state), the execution jumps directly to the else block, cycles back to the beginning of the program loop, and then prints my error message again as if the letter had never been removed from the input buffer. The if block I am referring to starts at line 78. The else block follows at line 97. I have tried (and commented out) cin.ignore(80), and while( cin.get(ch) && ch != '\n' ) ; , as well to clear the input buffer. I do not understand why it is jumping to the else block after entering the if block on condition of cin.fail(). My doing cin.clear() should not cause it to do this should it? I have included some cout statements that help you see the flow of execution. Please, can somebody help me?
If the input is invalid, such as "6a", I don't want it to assign the tic-toe-board's position #6, as it is doing now. The assignment statement for the positions of the board is in the else block, and this should not be executing if cin.fail() was true, correct? Please help.
Code:
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstdio>
int main() {
bool validInput = false;
bool winner = false;
bool boardFull = false;
char player[2];
char board[3][3][2];
int input = 0, x, y, p = 0;
player[0] = 'X';
player[1] = 'O';
// populate board array with numbers 1-9
int count = 1;
for( x=0; x < 3; x++ ) {
for( y=0; y < 3; y++, count++ )
sprintf( board[x][y], "%d", count );
}
while( validInput == false || ( winner == false && boardFull == false ) ) {
// display board
system("clear");
std::cout << "beginning of loop\n";
for( x=0; x < 3; x++ ) {
std::cout << std::endl;
for( y=0; y < 3; y++ )
std::cout << std::setw(5) << board[x][y];
}
// check each horizontal row to see if there is a winner
for( x=0, y=0; x < 3; x++, y=0 ) {
while( y < 2 && board[x][y][0] == board[x][y+1][0] )
y++;
if( y == 2 )
winner = true;
}
// check each vertical column to see if there is a winner
for( x=0, y=0; y < 3; y++, x=0 ) {
while( x < 2 && board[x][y][0] == board[x+1][y][0] )
x++;
if( x == 2 )
winner = true;
}
// check downward diagonal to see if there is a winner
x = y = 0;
while( x < 2 && board[x][y][0] == board[x+1][y+1][0]) {
x++;
y++;
}
if( x == 2 )
winner = true;
// check upward diagonal to see if there is a winner
x = 2;
y = 0;
while( x && board[x][y][0] == board[x-1][y+1][0] ) {
x--;
y++;
}
if( !x )
winner = true;
if( winner == true )
std::cout << "\n\nPlayer " << player[!p] << " has won the game.\n\n";
else {
// check to see if board is full
x = 0;
y = 3;
for( x=0; x < 3 && y == 3; x++ ) {
for( y=0; y < 3 && ( board[x][y][0] == 'X' || board[x][y][0] == 'O' ); y++ )
;
}
if( x == 3 && y == 3 ) {
boardFull = true;
std::cout << "\n\nThe board is full. Stalemate. Game Over.\n\n";
}
else {
std::cout << "\n\nPlayer " << player[p] << ", enter your choice from 1-9.\n";
std::cin >> input;
if( std::cin.fail() || input < 1 || input > 9 ) {
// clear fail flag so can use cin again
std::cin.clear();
// flush keyboard input buffer
// char ch;
while( std::cin.get() != '\n' )
;
// std::cin.ignore(80);
// while( std::cin.get(ch) && ch != '\n' )
// ;
std::cout << "\nYou must enter a number from 1-9.\n";
// set input back to an invalid value so if, say it was
// assigned the '6' from input such as "6a"
std::cout << "input is being assigned 0\n";
input = 0;
std::cout << "input is now " << input << std::endl;
p = !p;
system("read");
}
else {
for( x=0, count=1; x < 3; x++ ) {
for( y=0; y < 3; y++, count++ ) {
if( count == input ) {
if( board[x][y][0] == 'X' || board[x][y][0] == 'O' ) {
std::cout << "\nThat place has already been taken."
<< "Choose a different one.\n\n";
p = !p;
system("read");
}
else {
validInput = true;
std::cout << "board array is assigned. input is "
<< input << " and count is " << count << std::endl;
system("read");
board[x][y][0] = player[p];
}
}
}
}
}
}
}
// switch players
p = !p;
std::cout << "gone through loop\n";
system("read");
}
}