Archived

This topic is now archived and is closed to further replies.

hellz

Tic Tac Toe input problem

Recommended Posts

hellz    356
Hey all, Got a slight problem with the input handling in my Tic Tac Toe game. Before I explain it, here's the code that's relevant:
/*
** getPlayerMove()
**
** Get the player's next move, and test that it's valid. 
*/
void getPlayerMove()
{
	bool invalidMove = false;
	int row, column, nextMove;

	// Only allow valid input to be stored in nextMove.
	if (!(cin >> nextMove))
		clearInvalidStream();

	// Calculate where nextMove lies on the grid.
	row    = (nextMove - 1) / 3;
	column = (nextMove - 1) % 3;

	// Ensure the nextMove is relative to a grid coordinate.
	if (nextMove < 1 || nextMove > 9)
		invalidMove = true;
	// See if a move has already been made on that grid position.
	else if (tttGrid[row][column] != 0)
		invalidMove = true;
	// It's a valid move.
	else
		tttGrid[row][column] = 1; // Test value, not done this yet.

	// If an invalid move has been found, inform the user.
	if (invalidMove)
	{
		cout << "\nInvalid move.  Press enter to continue.\n";
		getchar();             // Grab a keypress.
		drawGrid();            // Re-draw the grid.
		displayGridUsage();    // Display movement usage.
	}
}

/*
** clearInvalidStream()
**
** Used to clear the cin stream to prevent input logic errors.
*/
void clearInvalidStream()
{
	// Clear any invalid input from the stream.
	cin.clear();
	while (cin.get() != '\n')
		continue;
}
 
The problem is, let's say the user chooses square 1 to move to (1 = top left, 2 top middle, 3 top right, 4 middle left, etc.). Then say the other player tries to move onto that square. If they try to do that, it displays the "Invalid move press enter to continue" message, but instead of waiting for getchar(), it ignores it and carries on. However, if someone enters an invalid move entirely, like for example 'd', then the getchar() fires and correctly waits for a key press. What am I missing here? Can't work out why it's doing it (I'd imagine it's possibly because I'm using the wrong function to deal with the input?). Thanks in advance. --hellz Edit: Bah, had to change from source tags to code tags. Something keeps breaking them when I use them, so only some of the code is displayed. :| [edited by - hellz on August 12, 2003 7:33:02 PM]

Share this post


Link to post
Share on other sites
quant    100
Not sure what your asking for, but if you just want to make sure its a number between 0 and 9, you can use the isdigit() function

Share this post


Link to post
Share on other sites
hellz    356
It''s not that, but thanks for the reply.

Basically, I''ve laid my TTT grid out like so:

1|2|3
-----
4|5|6
-----
7|8|9

Each number corresponds with a move the user can make. So, I prompt them for their next move (which lies between 1 and 9). Imagine someone enters 1 as their move, the grid at the start looks like this:

X| |
-----
| |
-----
| |

Now, if someone enters 1 again, the program should indicate that the move is invalid. It does this, but it doesn''t wait for a key press to then attempt to move again.

Output (haven''t fixed the layout yet, so excuse the debuginess ):

| |
-----
| |
-----
| |

1|2|3
-----
4|5|6
-----
7|8|9

Make your next move (1-9): 1

Now the next move:

X| |
-----
| |
-----
| |

1|2|3
-----
4|5|6
-----
7|8|9

Make your next move (1-9): 1

It displays the "Invalid move. Press enter to continue." message, but it doesn''t wait for getchar(). It just carries on into the next iteration of the main game loop. Only reason you can see the invalid move message, is because you see it flicker on the screen.

However, if you enter a completely invalid move, like the following:

X| |
-----
| |
-----
| |

1|2|3
-----
4|5|6
-----
7|8|9

Make your next move (1-9): d

Invalid move. Press enter to continue.

It displays the message *and* waits for the keypress. Not sure why entering a normal move doesn''t. Bit baffled actually. lol

Hope that''s made it a little clearer.

--hellz

Share this post


Link to post
Share on other sites
ISOPimp    122
What if someone enters something like 77? Does the message disappear right away? I think it will, because you are not clearing the buffer after getting this error. I think that when you enter a number with cin << nextMove; the ''\n'' character stays in the buffer all the way until you get to getchar() which then takes ''\n'' char from the buffer and keeps going.

K, that might have been confusing, but just try putting a cin.clear(); before getchar();

Share this post


Link to post
Share on other sites
hellz    356
Hmm, I see where you''re heading (thanks for the reply btw ). I infact just put cin.ignore(1, ''\n''); after the first if statement (as you''re right, I''m not catching the newline - can''t believe I didn''t see that, lol). It fixes the problem of when a number is entered, but if a character is entered, you have to press enter twice for it to recognise it''s an invalid move. The first keypress skips to a newline, then the second makes the program display the error message.

Quite odd, but there''s obviously a logic error in my code with my error handling. I tried using cin.clear() before getchar() but that didn''t have any affect.

Just gonna try something, be back in a few minutes. Thanks again.

--hellz

Share this post


Link to post
Share on other sites
hellz    356
I'm a silly bugger. Just added an ignore() as an else condition, and it's working now:


// Only allow valid input to be stored in nextMove.
if (!(cin >> nextMove))
clearInvalidStream();
else
cin.ignore(1, '\n');


Thanks a lot guys. Sorry for being a pain; my own fault for coding well into the night I guess.

--hellz

[edited by - hellz on August 12, 2003 8:24:17 PM]

Share this post


Link to post
Share on other sites