Sign in to follow this  

sorry it's alot to ask but...

This topic is 4583 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i know this is alot to ask. but does anyone mind telling me where i went wrong? in this code? i'm not online anymore so i have to come to my brother's house to check up on my email and forum posts and it's also probably why i havent debugged this code yet. this is for a tic tac toe game. i think my problem is in the enum syntax. wich was barely even explained to me in the book iu'm reading. but found several explanations(short ones) inother books i use for refference. please don't stone mefor asking for such a request. i dunno if people help others debug code yet. this is the first time i've asked for help debbugin. this is always the reason for the longest delays in my c++ learning process.... #include <iostream> #include <string> #include <stdlib.h> using namespace std; //introduces namespace std; enum SquareState { blank = ' ', x = 'X', O= 'O'}; class gameBoard { private: const int WIDTH; const int HEIGHT; int* GameBoard; public: gameBoard() : WIDTH(3), HEIGHT(3) ( GameBoard = new int[9]; for (int i = 0; i < 9; i++) *(GameBoard + i) = blank; } ~gameBoard() {delete[] GameBoard;} void setX(int h, int w); void setO(int h, int w); bool isTaken(int h, int w); SquareState isLine(); void draw(); }; void gameBoard::setX(int h, int w) { *(GameBoard + h*HEIGHT + w) = X; } void gameBoard::set0(int h, int w); { *(GameBoard + h*HEIGHT + w) = O; } bool gameBoard::isTaken (int h, int w) { return *(GameBoard + h*HEIGHT + w) != ' '; } SquareState gameBoard::isLine() { if(*GameBoard==X && *(GameBoard +1)==X && *(GameBoard +2)==X) return X; if(*GameBoard==O && *(GameBoard +1)==O && *(GameBoard +2)==O) return O; if(*(GameBoard +3)==X && *(GameBoard +4)==X && *(GameBoard +5)==X) return X; if(*(GameBoard +3)==O && *(GameBoard +4)==O && *(GameBoard +5)==O) return O; if(*(GameBoard +6)==X && *(GameBoard +7)==X && *(GameBoard +8)==X) return X; if(*(GameBoard +6)==O && *(GameBoard +7)==O && *(GameBoard +8)==O) return O; if(*GameBoard==X && *(GameBoard +3)==X && *(GameBoard +6)==X) return X; if(*GameBoard==O && *(GameBoard +3)==O && *(GameBoard +6)==O) return O; if(*(GameBoard +1)==X && *(GameBoard +4)==X && *(GameBoard +7)==X) return X; if(*(GameBoard +1)==O && *(GameBoard +4)==O && *(GameBoard +7)==O) return O; if(*(GameBoard +2)==X && *(GameBoard +5)==X && *(GameBoard +8)==X) return X; if(*(GameBoard +2)==O && *(GameBoard +5)==O && *(GameBoard +8)==O) return O; if(*GameBoard==X && *(GameBoard +4)==X && *(GameBoard +8)==X) return X; if(*GameBoard==O && *(GameBoard +4)==O && *(GameBoard +8)==O) return O; if(*(GameBoard +2)==X && *(GameBoard +4)==X && *(GameBoard +6)==X) return X; if(*(GameBoard +2)==O && *(GameBoard +4)==O && *(GameBoard +6)==O) return O; return blank; } void gameBoard::draw()// proofread here { cout << endl; for(int i=0; i < HEIGHT; i++) { cout << (char)*(GameBoard + i*HEIGHT); for(int c=1; c < WIDTH; c++) cout << " | " << (char)*(GameBoard + i*WIDTH + c); cout << endl << "-------"<< endl; } } class Game { public: gameBoard* doInput(string player, gameBoard* gb); bool inRange(int test); }; gameBoard* Game::doInput(string player, gameBoard* gb) { gb->draw(); string letter; if(player.compare("one") == 0) letter = "X"; else if (player.compare("two") == 0) letter = "O"; else return gb; int input1, input2; do{ do{ cout << "\nPlayer " << player.c_str() << ", please enter a row number to put an " << letter.c_str() << ": "; cin >> input1; }while(!inRange(input1)); do { cout << "\nPlease enter a column number to put an " << letter.c_str() << ": "; cin << input2; }while(!inRange(input2)); }while(gb->isTaken(input1, input2)); if (player.compare("one") == 0) gb->setX(input1, input2); else gb->set0(input1, input2); return gb; } bool Game::inRange(int test) { return test > -1 && test < 3; } int main( void ) { gameBoard* gb = new gameBoard; Game g; string player1, player2; cout << "Welcome to Tic Tac Toe!" << "\nPlayer one, please enter your name: "; cin >> player1; cout << "\nPlayer two, please enter your name: "; cin >> player2; while (gb->isLine() == ' ') { gb = g.doInput("one",gb); gb = g.doInput("two",gb); } gb->draw(); if(gb->isLine()==X) cout << "\nPlayer one, you win!" << "\nGame Over."; else cout << "\nPlayer two, you win!" << "\nGame Over."; system("pause"); return 0; }

Share this post


Link to post
Share on other sites
It would help if you told us what kind of error you are getting. Does the program not compile? Does it crash when you run it? If so, when does it crash? Does it not print the correct output?

I just noticed one thing that might be a reason why it won't compile. The '(' must be a '{' on the line after: "gameBoard() : WIDTH(3), HEIGHT(3"

Share this post


Link to post
Share on other sites
sorry using my brother's compiler i'm getting lots of new errors. and i have to go now too cause they're going to sleep. i can let you know what happens tomorrow and check for replies. i've also cleaned the code up a bit.(i think)


 
#include <iostream>
#include <string>
#include <stdlib.h>

using namespace std; //introduces namespace std;
enum SquareState { blank = ' ', x = 'X', O= 'O'};
class gameBoard
{
private:
const int WIDTH;
const int HEIGHT;
int* GameBoard;
public:
gameBoard() : WIDTH(3), HEIGHT(3)
{
GameBoard = new int[9];
for (int i = 0; i < 9; i++)
*(GameBoard + i) = blank;

}
~gameBoard() {delete[] GameBoard;}
void setX(int h, int w);
void setO(int h, int w);
bool isTaken(int h, int w);
SquareState isLine();
void draw();
};
void gameBoard::setX(int h, int w)
{
*(GameBoard + h*HEIGHT + w) = X;

}
void gameBoard::setO(int h, int w);
{
*(GameBoard + h*HEIGHT + w) = O;
}
bool gameBoard::isTaken (int h, int w)
{
return *(GameBoard + h*HEIGHT + w) != ' ';
}

SquareState gameBoard::isLine()
{
if(*GameBoard==X && *(GameBoard +1)==X && *(GameBoard +2)==X)
return X;
if(*GameBoard==O && *(GameBoard +1)==O && *(GameBoard +2)==O)
return O;
if(*(GameBoard +3)==X && *(GameBoard +4)==X && *(GameBoard +5)==X)
return X;
if(*(GameBoard +3)==O && *(GameBoard +4)==O && *(GameBoard +5)==O)
return O;
if(*(GameBoard +6)==X && *(GameBoard +7)==X && *(GameBoard +8)==X)
return X;
if(*(GameBoard +6)==O && *(GameBoard +7)==O && *(GameBoard +8)==O)
return O;

if(*GameBoard==X && *(GameBoard +3)==X && *(GameBoard +6)==X)
return X;
if(*GameBoard==O && *(GameBoard +3)==O && *(GameBoard +6)==O)
return O;
if(*(GameBoard +1)==X && *(GameBoard +4)==X && *(GameBoard +7)==X)
return X;
if(*(GameBoard +1)==O && *(GameBoard +4)==O && *(GameBoard +7)==O)
return O;
if(*(GameBoard +2)==X && *(GameBoard +5)==X && *(GameBoard +8)==X)
return X;
if(*(GameBoard +2)==O && *(GameBoard +5)==O && *(GameBoard +8)==O)
return O;

if(*GameBoard==X && *(GameBoard +4)==X && *(GameBoard +8)==X)
return X;
if(*GameBoard==O && *(GameBoard +4)==O && *(GameBoard +8)==O)
return O;
if(*(GameBoard +2)==X && *(GameBoard +4)==X && *(GameBoard +6)==X)
return X;
if(*(GameBoard +2)==O && *(GameBoard +4)==O && *(GameBoard +6)==O)
return O;
return blank;

}

void gameBoard::draw()// proofread here
{
cout << endl;
for(int i=0; i < HEIGHT; i++)
{
cout << (char)*(GameBoard + i*HEIGHT);
for(int c=1; c < WIDTH; c++)
cout << " | " << (char)*(GameBoard + i*WIDTH + c);
cout << endl << "-------"<< endl;
}
}

class Game
{
public:
gameBoard* doInput(string player, gameBoard* gb);
bool inRange(int test);
};

gameBoard* Game::doInput(string player, gameBoard* gb)
{
gb->draw();

string letter;
if(player.compare("one") == 0)
letter = "X";
else if (player.compare("two") == 0)
letter = "O";
else return gb;

int input1, input2;

do{

do{
cout << "\nPlayer " << player.c_str()
<< ", please enter a row number to put an "
<< letter.c_str() << ": ";
cin >> input1;
}while(!inRange(input1));

do {
cout << "\nPlease enter a column number to put an "
<< letter.c_str() << ": ";
cin << input2;
}while(!inRange(input2));

}while(gb->isTaken(input1, input2));

if (player.compare("one") == 0)
gb->setX(input1, input2);
else gb->setO(input1, input2);

return gb;

}

bool Game::inRange(int test)
{
return test > -1 && test < 3;
}



int main( void )
{
gameBoard* gb = new gameBoard;
Game g;
string player1, player2;
cout << "Welcome to Tic Tac Toe!"
<< "\nPlayer one, please enter your name: ";
cin >> player1;
cout << "\nPlayer two, please enter your name: ";
cin >> player2;

while (gb->isLine() == ' ')
{
gb = g.doInput("one",gb);
gb = g.doInput("two",gb);
}

gb->draw();
if(gb->isLine()==X)
cout << "\nPlayer one, you win!"
<< "\nGame Over.";
else cout << "\nPlayer two, you win!"
<< "\nGame Over.";
system("pause");
return 0;
}

Share this post


Link to post
Share on other sites
I didn't look over all your code, but in your enum declaration you have 'x', as opposed to the rest of the code in which you have 'X'.

HTH,
nilkn

Share this post


Link to post
Share on other sites
Not that bad! You are actually really close to being done. Take a look at a few things I have marked, there is a lot more that should be fixed in terms of handling proper input and stuff, but for now it's good.


#include <iostream>
#include <string>

//#include <stdlib.h>
//// We can use the modern version as well
#include <cstdlib>

//introduces namespace std;
//using namespace std;
//// For now, I did not

//// Good idea, but needs revision
//enum SquareState { blank = ' ', x = 'X', O= 'O'};
enum SquareState { Blank = ' ', X = 'X', O = 'O' };

class gameBoard
{
private:
const int WIDTH;
const int HEIGHT;
int* GameBoard;
public:
gameBoard() : WIDTH(3), HEIGHT(3)
{
//// Oh no, what happened here!?!
/*GameBoard = new int[9];
for (int i = 0; i < 9; i++)
*(GameBoard + i) = blank;*/


//// Since we have a width and height, use it!
//// I also changes the blank to Blank for consistancy
GameBoard = new int[ WIDTH * HEIGHT ];
for (int i = 0; i < WIDTH * HEIGHT; i++)
*(GameBoard + i) = Blank;
}

//// Good! But you always want to change the memory first!
//// Yes I know this will only fail if the ctor fails, but
//// always be prepeared
~gameBoard()
{
if( GameBoard )
delete[] GameBoard;
}

void setX(int h, int w);
void setO(int h, int w);
bool isTaken(int h, int w);

SquareState isLine();

void draw();
};

void gameBoard::setX(int h, int w)
{
*(GameBoard + h*HEIGHT + w) = X;

//// More friendly, but to each his own [smile]
//// GameBoard[h*HEIGHT + w] = X;
}

void gameBoard::setO(int h, int w)
{
*(GameBoard + h*HEIGHT + w) = O;

//// More friendly, but to each his own [smile]
//// GameBoard[h*HEIGHT + w] = 0;
}

bool gameBoard::isTaken (int h, int w)
{
return *(GameBoard + h*HEIGHT + w) != ' ';
}

//// Looks like it should work...
SquareState gameBoard::isLine()
{
if(*GameBoard==X && *(GameBoard +1)==X && *(GameBoard +2)==X)
return X;
if(*GameBoard==O && *(GameBoard +1)==O && *(GameBoard +2)==O)
return O;
if(*(GameBoard +3)==X && *(GameBoard +4)==X && *(GameBoard +5)==X)
return X;
if(*(GameBoard +3)==O && *(GameBoard +4)==O && *(GameBoard +5)==O)
return O;
if(*(GameBoard +6)==X && *(GameBoard +7)==X && *(GameBoard +8)==X)
return X;
if(*(GameBoard +6)==O && *(GameBoard +7)==O && *(GameBoard +8)==O)
return O;

if(*GameBoard==X && *(GameBoard +3)==X && *(GameBoard +6)==X)
return X;
if(*GameBoard==O && *(GameBoard +3)==O && *(GameBoard +6)==O)
return O;
if(*(GameBoard +1)==X && *(GameBoard +4)==X && *(GameBoard +7)==X)
return X;
if(*(GameBoard +1)==O && *(GameBoard +4)==O && *(GameBoard +7)==O)
return O;
if(*(GameBoard +2)==X && *(GameBoard +5)==X && *(GameBoard +8)==X)
return X;
if(*(GameBoard +2)==O && *(GameBoard +5)==O && *(GameBoard +8)==O)
return O;

if(*GameBoard==X && *(GameBoard +4)==X && *(GameBoard +8)==X)
return X;
if(*GameBoard==O && *(GameBoard +4)==O && *(GameBoard +8)==O)
return O;
if(*(GameBoard +2)==X && *(GameBoard +4)==X && *(GameBoard +6)==X)
return X;
if(*(GameBoard +2)==O && *(GameBoard +4)==O && *(GameBoard +6)==O)
return O;
return Blank;

}

void gameBoard::draw()// proofread here
{
std::cout << std::endl;
for(int i=0; i < HEIGHT; i++)
{
std::cout << (char)*(GameBoard + i*HEIGHT);
for(int c=1; c < WIDTH; c++)
std::cout << " | " << (char)*(GameBoard + i*WIDTH + c);
//std::cout << std::endl << "-------"<< std::endl;
//// You just needed two more here ;)
std::cout << std::endl << "---------"<< std::endl;
}
}

class Game
{
public:
gameBoard* doInput(std::string player, gameBoard* gb);
bool inRange(int test);
};

gameBoard* Game::doInput(std::string player, gameBoard* gb)
{
gb->draw();

std::string letter;
if(player.compare("one") == 0)
letter = "X";
else if (player.compare("two") == 0)
letter = "O";
else return gb;

int input1, input2;

do{
do{
std::cout << "\nPlayer " << player.c_str()
<< ", please enter a row number to put an "
<< letter.c_str() << ": ";
std::cin >> input1;
}while(!inRange(input1));

do {
std::cout << "\nPlease enter a column number to put an "
<< letter.c_str() << ": ";
//// Eeeek!! Wrong way!
//std::cin << input2;
std::cin >> input2;
}while(!inRange(input2));

}while(gb->isTaken(input1, input2));

if (player.compare("one") == 0)
gb->setX(input1, input2);
else gb->setO(input1, input2);

return gb;

}

bool Game::inRange(int test)
{
return test > -1 && test < 3;
}

int main( void )
{
gameBoard* gb = new gameBoard;
Game g;
std::string player1, player2;
std::cout << "Welcome to Tic Tac Toe!" << "\nPlayer one, please enter your name: ";
std::cin >> player1;
std::cout << "\nPlayer two, please enter your name: ";
std::cin >> player2;

while (gb->isLine() == ' ')
{
gb = g.doInput("one",gb);
gb = g.doInput("two",gb);
}

gb->draw();
if(gb->isLine()==X)
std::cout << "\nPlayer one, you win!" << "\nGame Over.";

else std::cout << "\nPlayer two, you win!" << "\nGame Over.";

system("pause");
return 0;
}




That runs for me just fine, the main thing that you do need to fix is to check for a win after each player move, not after both players have gone their turn.

With that program, there's a mixture of C and Standard C++, I would reccomend using all standard C++ stuff to take care of it (such as use a vector rather than int*).

Once you look over that, you can get more ideas of what to do to improve from the community. So good job almost getting it all done, keep at it!

Share this post


Link to post
Share on other sites
Quote:
Original post by Drew_Benton
//// Good! But you always want to change the memory first!
//// Yes I know this will only fail if the ctor fails, but
//// always be prepeared
~gameBoard()
{
if( GameBoard )
delete[] GameBoard;
}


I don't think the check is EVER necessary. Consider the three possible cases:

If you don't initialize your pointer, it will have garbage data and the if statement will evaluate to true anyway ( since it's not equal to zero ), causing your program to crash and having the same effect as not including the if statement at all

If you DO initialize it with new memory then it will of course delete it correctly.

Finally, if you initialize it to zero then the delete[] will have no effect whatsoever since deleting a null pointer is a NO-OP

I used to do this too, until I realized that it is completely useless.
Why do people always do this? Was delete[] not always a NO-OP with a NULL pointer? Anyone know?

Share this post


Link to post
Share on other sites
Quote:
Original post by Drew_Benton
Not that bad! You are actually really close to being done. Take a look at a few things I have marked, there is a lot more that should be fixed in terms of handling proper input and stuff, but for now it's good.

*** Source Snippet Removed ***

That runs for me just fine, the main thing that you do need to fix is to check for a win after each player move, not after both players have gone their turn.

With that program, there's a mixture of C and Standard C++, I would reccomend using all standard C++ stuff to take care of it (such as use a vector rather than int*).

Once you look over that, you can get more ideas of what to do to improve from the community. So good job almost getting it all done, keep at it!



read over the code and it looks interesting. sorry to disapoint you but i only copied that out of a book as part of an assignmet and couldnt even retype what i've read right!!! unless theyve intentionaly put errors in the code so i can fix it. funny thing wass that there were a whole buncha errors in visualstudio but i also edited it in codeblocks as well and fixed some errors and it xecuted. but still wouldnt execute in visual studio. very weird.

i think i will be looking over this code and figuring out why it works for a while. i read somewhere on this forum that it's not that important to know thw syntax of the code as long as you know what it does. i kinda know what things do but i dont always recognise them when i'm doing assignments. c++ is kinda hard. i have lots of studying to do. maybe the book i'm reading is so straight foreward to the point that i'm taking in too much at one time and not really learning how to use the stuff??

Share this post


Link to post
Share on other sites
Quote:
Original post by averisk
Quote:
Original post by Drew_Benton
//// Good! But you always want to change the memory first!
//// Yes I know this will only fail if the ctor fails, but
//// always be prepeared
~gameBoard()
{
if( GameBoard )
delete[] GameBoard;
}


I don't think the check is EVER necessary. Consider the three possible cases:

If you don't initialize your pointer, it will have garbage data and the if statement will evaluate to true anyway ( since it's not equal to zero ), causing your program to crash and having the same effect as not including the if statement at all

If you DO initialize it with new memory then it will of course delete it correctly.

Finally, if you initialize it to zero then the delete[] will have no effect whatsoever since deleting a null pointer is a NO-OP

I used to do this too, until I realized that it is completely useless.
Why do people always do this? Was delete[] not always a NO-OP with a NULL pointer? Anyone know?

You are right. The destructor won't be called if the constructor fails (throws an error). Checking if the pointer is not null before delete is pointless because delete/free does this for you.
Initializing it to null would be pointless in this case too. The destructor would only be called if the constructor succeeded, and if the constructor succeeded the pointer would be valid. Thus is it pointless.

I don't know why people keep on checking if the pointer is not null before they delete it. Probably just a bad habit learned by some online code/tutorial.

Share this post


Link to post
Share on other sites
I recomend you pick one compiler/IDE to learn on. Buoncing back and forth will confuse you, they all have their own nuances and all compilers are not the same.

Share this post


Link to post
Share on other sites
what are you writing your code in? you might think of trying textpad if your having trouble catching your opening and closing curly brackets, I find that the microsoft c++ programs just dont have alot of things that it does...
oh and cstdlib doesnt have to have the .h :)

Share this post


Link to post
Share on other sites
Quote:
Original post by chad_420
I recomend you pick one compiler/IDE to learn on. Buoncing back and forth will confuse you, they all have their own nuances and all compilers are not the same.


Well, the language will always be the same, but IDEs have various different ways to annoy you (I don't bother with them personally - I just use a text editor and the invoke the compiler at the command line - but to each his own), and compilers vary in their conformance to the language specification. :)

Anyway. Now that Drew's made it work, allow me to make it right (or at least begin that process):


#include <iostream>
#include <string>
#include <cstdlib>

// I'm going to use namespace std even if Drew doesn't, because it's a lot less
// repetitive typing of "std::". :)

enum SquareState { Blank = ' ', X = 'X', O = 'O' };

class gameBoard
{
private:
// I have made the constants static so that they can be used "before
// construction" i.e. to specify the array size
static const int WIDTH = 3;
static const int HEIGHT = 3;
static const int SIZE = WIDTH * HEIGHT;
// We don't need to allocate this data dynamically, because we always
// know what size it is. So let's keep things simple:
SquareState GameBoard[SIZE];
// Note that in C++, enumerations introduce a new type. Thus I have
// used it for the board square type; this helps the compiler check
// things, and is clearer about our intent.
public:
gameBoard()
{
for (int i = 0; i < SIZE; i++) { GameBoard[i] = Blank; }
// There is basically no reason to write things with the pointer
// arithmetic syntax here :)
}

// Don't need a dtor any more. As was correctly pointed out, the NULL
// check was not needed before :)

// I simplified things here by using the same method to set X and O.
// The caller specifies which one to set, with the extra parameter.
// That avoids some duplication. :) Also, the function now returns false
// if the space is taken, and otherwise sets and returns true. This is
// better encapsulation: the game board itself is what ought to be
// responsible for doing this checking logic.
bool placePiece(int h, int w, SquareState type);

SquareState winner();

void draw();
};

bool gameBoard::placePiece(int h, int w, SquareState type)
{
// Make sure we don't have a coding error
assert (type != Blank);
// Figure out what square of the board we're interested in.
int position = h * HEIGHT + w;
// Check if position is taken.
if (GameBoard[position] != Blank) { return false; }
else { GameBoard[position] = type; return true; }
}

SquareState gameBoard::winner()
{
// To avoid repeating similar logic, we'll create some data that
// represents the winning combinations, and then use it.
// This is an array of 8 arrays of 3 numbers each. The inner arrays
// specify a set of locations that form a line.
int wins[8][3] = { {0, 1, 2}, {3, 4, 5}, {6, 7, 8}, // rows
{0, 3, 6}, {1, 4, 7}, {2, 5, 8}, // columns
{0, 4, 8}, {2, 4, 6} }; // diagonals
for (int i = 0; i < 8; i++) {
// Now for each set of positions, we check the marks at those
// positions, and report a win for the player occupying them
// if they are non-blank and all the same.
SquareState first = GameBoard[wins[i][0]];
SquareState second = GameBoard[wins[i][1]];
SquareState third = GameBoard[wins[i][2]];
if (first == second && second == third && first != Blank) {
return first;
}
}
// Otherwise, no winner yet.
return Blank;
}

void gameBoard::draw()
{
cout << endl;
for(int i=0; i < HEIGHT; i++)
{
cout << (char)GameBoard[i*HEIGHT];
for(int c=1; c < WIDTH; c++)
// I think Drew got his HEIGHT and WIDTH confused here :)
cout << " | " << (char)*(GameBoard + i*HEIGHT + c);
cout << endl << "---------"<< endl;
}
}

class Game
{
gameBoard myBoard;
public:
// The Game really should have its *own* gameBoard; the old interface
// was really weird. Anyway, no ctor or dtor is needed for that; the
// default ctor will just invoke the gameBoard() ctor.
// Also, I'll use a SquareState to identify the player, and just
// translate that value when printing.
// Finally, part of handling a move is knowing if it resulted in a win,
// so I'll make the check and return the result here.
SquareState handleMove(int player);
// Instead of just moving the range check (which is simple) to a new
// function, I have the function handle the inner loop of prompting for
// an input.
private:
int getInput(string prompt);
// Also, I made this function private because it's a helper function,
// not meant to be called from outside.
};

SquareState Game::handleMove(SquareState player)
{
assert (player != Blank);
myBoard.draw();

// We just need a single character here for the player's "letter".
// The string idea is reasonable, but more than we need here - and a
// .c_str() definitely isn't needed for printing the string ;)

char letter = player; // implicit cast.
string playerId = (player == X) ? "one" : "two";

int row, column; // more descriptive names here

// I made the input process more robust; it will handle non-numeric
// garbage properly now too ;)

do {
row = getInput("\nPlayer " + playerId + ", please enter a row number to put an " + letter + ": ");
column = getInput("\nPlease enter a column number to put an " + letter + ": ");
} while (!myBoard.placePiece(row, column, player));
// i.e., it loops until piece placement is successful.
return myBoard.winner();
}

int Game::getInput(string prompt)
{
int result = -1;
do {
cout << prompt;
cin >> result;
// Ignore the rest of the line, and make sure cin is "clear"
// (when reading into result fails, e.g. something non-numeric
// is entered, the stream state is changed such that it won't
// read any more until you handle the error)
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
} while (result < 0 || result > 2);
return result;
}

int main() // Please don't use "(void)" prototypes in C++.
{
Game g; // inits its own gameBoard
string player1, player2;
cout << "Welcome to Tic Tac Toe!" << "\nPlayer one, please enter your name: " << flush;
cin >> player1;
cout << "\nPlayer two, please enter your name: " << flush;
cin >> player2;
// Todo: Make the rest of the code actually use those player names ;)
SquareState winner = Blank;
for (int i = 0; i < 9; i++) // put a limit on total moves
{
// Decide who moves this time
SquareState whoseTurn = (i % 2) ? X : O;
winner = g.handleMove(whoseTurn);
if (winner != Blank) break;
}

gb->draw();
switch (winner) {
case X:
cout << "\nPlayer one, you win!" << endl;
break;
case O:
cout << "\nPlayer two, you win!" << endl;
break;
default: // Blank - i.e., no winner - all spaces filled
cout << "\nCat's game!" << endl;
}
// And in all of those cases...
cout << "Game Over." << endl;

system("pause");
return 0;
}



Actually, there is still lots of cleanup work that can be done, but hopefully you have a few good ideas now ;) This is not tested, so beware.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman

// I'm going to use namespace std even if Drew doesn't, because it's a lot less
// repetitive typing of "std::". :)



Thats not a habit you want to get into, it's a lot easier than writing std:: that is true, but if you put a using namespace std in header files then include those header files in other files the using will propogate through to that file also, even if you don't want that module to use the namespace. I just try and stick to writing std::vector std::string etc. It's a pain at first but you get used to it :P

I guess it's not too much of a problem to do it for .cpp files though.

Share this post


Link to post
Share on other sites
Well of course, don't do it in header files :) Within the .cpp (which won't get included anywhere else if you're doing things properly), you can start out with a top-level 'using namespace std;', and if it causes problems (and if such problems are not either immediately obvious or caught by the compiler then you are *really* unlucky), then restrict the declaration as needed.

Share this post


Link to post
Share on other sites
i think i'm gonna try using python for now i've got a book or two on it and i think it might be useful to actualy pogram on that. i've actualy had a little fun with a while loop todayin python. something i have never even thought of doing in c++ i got as far as classes and arrays in and data types in c++ so i think i can probably do some advanced things in python(at least for my level) fairly quickly and then go back to c++

Share this post


Link to post
Share on other sites
Quote:
Original post by moagstar
Thats not a habit you want to get into, it's a lot easier than writing std:: that is true, but if you put a using namespace std in header files then include those header files in other files the using will propogate through to that file also, even if you don't want that module to use the namespace. I just try and stick to writing std::vector std::string etc. It's a pain at first but you get used to it :P

I guess it's not too much of a problem to do it for .cpp files though.


Even better, if you really can't be bothered to spend the (extrememly) small time needed to fully qualify objects, you can simply typedef them to something quicker to write. Plus this way if you ever change the string class you wish to use, you can just change the typedef instead of changing a million references to the old string class in the code. (Provided of course that your new string class uses the same syntax as the old one)

[EDIT] Ooops, quoted wrong post.. Can't believe I didn't notice that as I was typing [smile]

Share this post


Link to post
Share on other sites

This topic is 4583 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this