Hello,
It's pretty simple, I ask them for a #, and it put's my code into an infinite loop. Here's the specific function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
void One::myTurn(){
bool temp;
temp=false;
choice=0;
cout << "\t Player 1, it is your turn, pick an open space...\n\n\n\n\n\n\n";
cin >> choice;
temp = moveMe(choice);
while(!temp){
theBoard.drawBoard();
if(choice>0 && choice<10) cout << " That space is taken, please choose an open space, Player 1 it is your move...\n\n\n\n\n\n\n";
else cout << "Invalid move, please choose an open space... Player 1 it is your move...\n\n\n\n\n\n\n";
cin >> choice;
temp = moveMe(choice);
}
}
Just in case you were curious as to what the moveMe function did. It's for a Tic-Tac-Toe game I've been making, remaking, and changing with the knowlege I get as a programmer. I ask them for their move (1-9) and if it's taken, they get "It's taken move again..." otherwise it's "Invalid move, move again..." but (and I've verified this in debugging) the cin >> choice; statement is bypassed if a letter is inputed. I've tryed most kinds of loops even to the extend just making a goto loop to no avail, I've tried a union, no go there. also, I just tried a new data class to see if it would work...but I haven't gotten it compiled yet, any ideas in the mean time?
#ifndef INC_NOCHAR_H
#define INC_NOCHAR_H
#include <iostream>
#include <cstdlib>
// specific class/header to address the issue of asking for a number, getting a character, and going into an infinite loop
class noChar{
// this class is only to be used for the ttt project as it has hardcoded strings and does not follow the common syntax of operator overloading
char ch;
int in;
public:
intoperator<<(noChar &o);
};
int noChar::operator<<(noChar &o){
noChar temp;
cin >> this->ch;
temp.in = atoi(this->ch);
return temp.in;
}
#endif /* INC_NOCHAR_H */
Why not make choice a char, and convert to a number 0-9?
You would need to add a conditional to say 'Please enter a number', but it should solve your problem.
Faldrax is correct. Just to add more detail, when istream (in this case cin) sees a character in the input stream that does not match what is attempting to be read, it stops and leaves the character in the input stream.
Said another way, your line cin >> choice; is attempting to read an integer from the stream. Any character that is not '0'...'9' cannot be read into the integer, so cin >> choice; returns without actually consuming the bad character. The next time you do cin >> choice; it will again see the same bad character and again stop reading.
There are a couple of ways around the problem, one of which is to do as Faldrax says and make choice a char and convert. This avoids the problem because any character can be read into a char without problems. In your case, this is probably the simplest and best solution.
The most general solution is to flush the input stream to get rid of the bad character(s) and then retry the input.
How would I flush the input stream? Or how would I use a character, atoi()? atoi's parameter's are for a string though... and flush or endl are only for output streams... How would I go about doing that?
If the variable is a char you can just cast it to an integer type if you want. The atoi does not necessarily take an array; just a pointer to a character. So you could pass it the memory address of a single character. As for resetting cin's error, I am not quite sure but I think you would use cin.clear().
cin.clear() hasn't worked, and using atoi() has failed also. What do you think I could do? it seems like a simple issue, understanding what '0' is and converting it to an integer or clearing a stream, but It's giving me trouble...
Here's what I'm getting: error C2664: 'atoi' : cannot convert parameter 1 from 'int' to 'const char *'
Just to add a bit of explanation to jsmiths post, char is actualy a 1 byte integer which the compiler automatically converts to and from the ASCII equivelent (so '0' = 48).
So in the line int move = choice - '0';
If you entered '5', this would become
=> int move = '5' - '0';
=> int move = 53 - 48;
=> int move = 5;
By using '0' rather than 48 directly you are guarding against a machine where the character coding is not standard ASCII (IE '0' != 48) - provided the character code has 0123456789 as sequential it will work.
Okay, so I went over my code and added your suggestion. It seems like it will work and thanks for that.
I actually cut 2 headers out of my project because they were almost the same and I just changed a few functions to reuse a lot of code.
I am creating objects of type Player for both player1 and player2 and a pointer to point to them (don't need to know who's move it is).
I want to have variables called PLAYER1_SYM and PLAYER2_SYM. I need there to only be one copy of these variables, you do that with the static modifier in a class right?
Because now I'm getting: error LNK2001: unresolved external symbol "public: static char Player::PLAYER2_SYM" (?PLAYER2_SYM@Player@@2DA)
The static keyword will make it so there is one variable that exists for every instance of the class; sort of like a global variable accessible only using class_name::static_var. If that is what you want, go ahead.
On the error: Do you have something like this? It would be easier for me to figure out the problem if I could see the class code.
1 2 3 4 5
class Player {
public:
staticchar PLAYER1_SYM;
}
Player::PLAYER1_SYM = 'x';
Those are the only things that access PLAYER1_SYM I believe... also, it says the LINK error is in main.obj, does that mean main.cpp's causing the error?
Alright,
When I was posting above I realized I could make PLAYER1_SYM and PLAYER2_SYM global, which I just did and it works great. However, I would like to know who to fix the problem above because this is one of my first multi-file projects and it is imperative I learn how to control and eliminate linking errors, as virtually all projects in the professional world are more than one file. Also, I have noticed a considerable speed decrease (yeah, even in a command line tic tac toe game) since making those values global, is that because of it's location in the program or in the files? Thanks for the help so far, the character idea was great, and worked well, later,
I would probably make the symbol a member of the Player class.
1 2 3 4
class Player {
public:
char symbol;
}
Then you simply set and access player1.symbol and player2.symbol and avoid global variables.
I am surprised there is a noticable difference in performance by usign the Globals, but yuo could try eliminating them as above and see if that helps.