Jump to content
  • Advertisement
Sign in to follow this  
mastern200

C++ tic tac toe help (true noob)

This topic is 4052 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

Hello. I need help creating a tic tac toe program using vectors. I am confused with the whole thing in general and not sure how to complete it. My problem is when player one says to put X in row 0, column 0, the X doesnt show up (obviously, because i havent put the code there). and that is just the start of my problems. I would appreciate it if someone could help me complete this program, with hints, or the whole code, whatever works :) thank you
#include <iostream>
#include <vector>
using namespace std;

void displayBoard(const vector< vector<char> > &table);
void getMove(vector< vector<char> > &table, char turn);

int main()
{
    char turn;
    
    vector<char>column(3,' ');
    vector< vector<char> > table(3,column);
    
    displayBoard(table);
    getMove(table, turn);
    
    cin.get();
    cin.get();
    return 0;
}


void displayBoard(const vector< vector<char> > &table)
{
	cout << endl;

		for(int row=0;row<table.size();row++)
		{
			for(int col=0;col<table[row].size();col++)
			{
				cout << "[" << table[row][col] << "] ";
			}
			cout << endl;
		}

}



void getMove(vector< vector<char> > &table, char turn)
{
     int row=0;
     int col=0;
     int x=0;
     int y=0;

     cout << turn << ", please enter row of move <0, 1, or 2>: ";
     cin >>row;

     cout << turn << ", please enter column of move <0, 1, or 2>: ";
     cin >> col;


     table[row][col] = x;
}

Share this post


Link to post
Share on other sites
Advertisement
try to think of your game somewhat like this: you want a player to enter a number, wich should be equal to a space on the board. before you can place the X/O, you need to check to see if there is allready placed a X/O. After each turn you should also check if there is 3 in a row. Instead of using vectors on this particulair project, you should use arrays.
try organizing your tic-tac-toe board like this:

(position)

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


hope this helps :) try writing down on paper what you want to do codewhise (= psedocode).

Share this post


Link to post
Share on other sites
No one is going to complete your program for you.

However, we will be more than willing to help if you show a little more enthusiasm towards working out some of your problems on your own.

I can see one problem with your code already, where you have "table[row][col] = x;" you probably meant "table[row][col] = 'x';". With the quotes you are assigning the character x to the row and column. Without the quotes, it is the contents of variable x, which you set to 0 at the start of the function.

Added to that, you will need a loop to make your game playable. We could add a control variable to tell us when the game is over, and loop until its false.


int main()
{
char turn;

vector<char>column(3,' ');

vector< vector<char> > table(3,column);

bool gameRunning = true;

while(gameRunning)
{
displayBoard(table);
getMove(table, turn);
}
cin.get();
cin.get();

return 0;
}



Note, until we actually add code to detect when a player has won that loop will never end. But its a start.

We also want to alternate between player one and player two. I assume that is the "turn" variable. Lets store instead an enumeration, which is more meaningful:



enum Player {
ONE,
TWO
};

// other stuff omitted

int main()
{
Player player = ONE;

vector<char>column(3,' ');

vector< vector<char> > table(3,column);

bool gameRunning = true;

while(gameRunning)
{
displayBoard(table);
getMove(table, player);
if(player == ONE)
{
player = TWO;
}
else // player must be equal to TWO
{
player = ONE;
}
}
cin.get();
cin.get();

return 0;
}



We will need to modify getMove to take account of this change:


void getMove(vector< vector<char> > &table, Player player )
{
int row=0;

int col=0;

// these are no longer used.
// int x=0;
// int y=0;



cout << player << ", please enter row of move <0, 1, or 2>: ";

cin >>row;



cout << player << ", please enter column of move <0, 1, or 2>: ";

cin >> col;

if( player == ONE )
{
table[row][col] = 'x';
}
else
{
table[row][col] = 'o';
}
}



This gives us enough to make an interactive game with.

#include <iostream>
#include <vector>
using namespace std;

enum Player {
ONE,
TWO
};

void displayBoard(const vector< vector<char> > &table)
{
cout << endl;
for(int row=0;row<table.size();row++)
{

for(int col=0;col<table[row].size();col++)
{

cout << "[" << table[row][col] << "] ";

}
cout << endl;
}
}


void getMove(vector< vector<char> > &table, Player player )
{
int row=0;
int col=0;

// these are no longer used.
// int x=0;
// int y=0;

cout << player << ", please enter row of move <0, 1, or 2>: ";

cin >>row;


cout << player << ", please enter column of move <0, 1, or 2>: ";

cin >> col;

if( player == ONE )
{
table[row][col] = 'x';
}
else
{
table[row][col] = 'o';
}
}

int main()
{
Player player = ONE;

vector<char>column(3,' ');

vector< vector<char> > table(3,column);

bool gameRunning = true;

while(gameRunning)
{
displayBoard(table);
getMove(table, player);
if(player == ONE)
{
player = TWO;
}
else // player must be equal to TWO
{
player = ONE;
}
}
cin.get();
cin.get();

return 0;
}



You can "play" this game, but you will need to add logic to:

0) prevent players putting a token on a box thats in use
1) detect when the game is over
2) make sure that the player enters a valid row and column

Share this post


Link to post
Share on other sites
WOW thanks ripoff! That explains a lot. At first glance, i only have one question. What is enum and how does it work into the functions?


enum Player {
ONE,
TWO
};

Share this post


Link to post
Share on other sites
Quote:
Original post by mastern200
WOW thanks ripoff! That explains a lot. At first glance, i only have one question. What is enum and how does it work into the functions?


enum Player {
ONE,
TWO
};


Use [source][/source] to get pretty source boxes [smile].

enum is short for an enumeration. An enumeration is a list of constant values (from the compilers point of view), that are given names meaningful to use.

For example, in a card game we may wish to represent the various suits. We can use an enumeration rather than try remember some obscure convention like heart = 1, spade = 3 etc:

enum Suit {
SPADE, HEART, CLUB, DIAMOND
};

Suit suit = SPADE;




In our case we have 2 players. You wanted to store the current player in a char variable "turn" for some reason. I assume you were going to set that variable to 1 during player one's turn and 2 during player two's turn. This would have worked, but the more general solution is to use an enumeration (its not so obvious as to which Suit should comes first, in the above list for example).

I think you'll find it easier to work with the symbolic names ONE and TWO. You can test for equality just like you would test an integer (as you have seen already in my code).

As for how they work with functions, they work exactly the same as any other type. We can pass them to functions, return them from functions.

Here is a function you may find useful soon:


#include <string>
std::string playerName( Player player )
{
if( player == ONE ) {
return "Player One";
} else {
return "Player Two";
}
}



We could use that in the getMove function, to print out a more meaningful promt rather than "0, please enter..." we could use

cout << playerName(player) << ", please enter...\n"





This next bit is a bit advanced and slightly irrelevant right now, but is included for completeness.

When compiling, the compiler will give the value 0 to the first element of an enumeration by default. Every subsequent element will have the value of the last one + 1. So in the Suit example SPADE will be 0, and HEART 1, CLUB 2 and DIAMOND 3. We can change the values by manually giving them a number. For example, if for some reason we wished the values to start at 1 we could do this:

enum Suit {
SPADE = 1,
HEART = 2,
CLUB = 3,
DIAMOND = 4
};



However, the compiler still follows the rule that if you don't specify a value for an element, it uses the value of the previous one + 1. Knowing this we could re-write the above to get the same effect:

enum Suit {
SPADE = 1,
HEART, // will be 2
CLUB, // will be 3
DIAMOND // will be 4
};



However, right now I'm guessing you don't really care what the value of ONE and TWO are, only how to tell which player is currently moving [smile].

Share this post


Link to post
Share on other sites
thanks! I have i think one more question. I am confused when to use ==, =, |, and ||. Whenever i use one in one place and one in another place, i get a "non lvalue in assignment" error.


#include <iostream>
#include <vector>
using namespace std;

void displayBoard(const vector< vector<char> > &table);
void getMove(vector< vector<char> > &table);
void winner(vector< vector<char> > &table);

int main()
{
int x=0;

vector<char>column(3,' ');
vector< vector<char> > table(3,column);

for(x=0;x<=9;x++){
displayBoard(table);
getMove(table);
winner(table);
}

cin.get();
cin.get();
return 0;
}


void displayBoard(const vector< vector<char> > &table)
{
cout << endl;

for(int row=0;row<table.size();row++)
{
for(int col=0;col<table[row].size();col++)
{
cout << "[" << table[row][col] << "] ";
}
cout << endl;
}

}

void getMove(vector< vector<char> > &table)
{
int row=0;
int col=0;

cout << "X , please enter row of move <0, 1, or 2>: ";
cin >> row;

cout << "X , please enter column of move <0, 1, or 2>: ";
cin >> col;

if(row<0 | row>2 | col<0 | row>2)
{
if(table[row][col]=='x' | table[row][col]=='o'){
cout<<"Sorry, this cannot be accepted. Try again.";
cout<<endl;

cout << "X , please enter row of move <0, 1, or 2>: ";
cin >> row;

cout << "X , please enter column of move <0, 1, or 2>: ";
cin >> col;}}


table[row][col] = 'x';

displayBoard(table);

cout << "O , please enter row of move <0, 1, or 2>: ";
cin >> row;

cout << "O , please enter column of move <0, 1, or 2>: ";
cin >> col;

if(row<0 | row>2 | col<0 | row>2)
{
if(table[row][col]='x' || table[row][col]='o'){
cout<<"Sorry, this cannot be accepted. Try again.";
cout<<endl;

cout << "O , please enter row of move <0, 1, or 2>: ";
cin >> row;

cout << "O , please enter column of move <0, 1, or 2>: ";
cin >> col;}}

table[row][col] = 'o';
}

void winner(vector< vector<char> > &table)
{
if('x' == table[0][0] & 'x' == table[0][1]& 'x' == table[0][2])
{
cout<<"X is the winner!;";
}

if(table[1][0] == 'x' & table[1][1] == 'x' & table[1][2] == 'x')
{
cout<<"X is the winner!;";
}

if(table[2][0] == 'x' & table[2][1] == 'x' & table[2][2] == 'x')
{
cout<<"X is the winner!;";
}

if(table[0][0] == 'x' & table[1][0] == 'x' & table[2][0] == 'x')
{
cout<<"X is the winner!;";
}

if(table[0][1] == 'x' & table[1][1] == 'x' & table[2][1] == 'x')
{
cout<<"X is the winner!;";
}

if(table[0][2] == 'x' & table[1][2] == 'x' & table[2][2] == 'x')
{
cout<<"X is the winner!;";
}

if(table[0][0] == 'x' & table[1][1] == 'x' & table[2][2] == 'x')
{
cout<<"X is the winner!;";
}

if(table[2][0] == 'x' & table[1][1] == 'x' & table[0][2] == 'x')
{
cout<<"X is the winner!;";
}

if(table[0][0] == 'o' & table[0][1] == 'o' & table[0][2] == 'o')
{
cout<<"O is the winner!;";
}

if(table[1][0] == 'o' & table[1][1] == 'o' & table[1][2] == 'o')
{
cout<<"O is the winner!;";
}

if(table[2][0] == 'o' & table[2][1] == 'o' & table[2][2] == 'o')
{
cout<<"O is the winner!;";
}

if(table[0][0] == 'o' & table[1][0] == 'o' & table[2][0] == 'o')
{
cout<<"O is the winner!;";
}

if(table[0][1] == 'o' & table[1][1] == 'o' & table[2][1] == 'o')
{
cout<<"O is the winner!;";
}

if(table[0][2] == 'o' & table[1][2] == 'o' & table[2][2] == 'o')
{
cout<<"O is the winner!;";
}

if(table[0][0] == 'o' & table[1][1] == 'o' & table[2][2] == 'o')
{
cout<<"O is the winner!;";
}

if(table[2][0] == 'o' & table[1][1] == 'o' & table[0][2] == 'o')
{
cout<<"O is the winner!;";
}
}




[Edited by - mastern200 on June 12, 2007 3:33:49 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by mastern200
thanks! I have i think one more question. I am confused when to use ==, =, |, and ||. Whenever i use one in one place and one in another place, i get a "non lword in assignment" error.

*** Source Snippet Removed ***


== is the comparison operator. It compares two values and returns a true or false value that can be used in an expression. For instance, you can use the result in an if/while/for statements. Or you can store the result.

= is either the assignment operator or the initialization operator depending on context. That is:

int a = 10; // initialization
a = 20; // assignment

An l-value is something that you can assign something to. You can't assign a to 20 ( 20 = a; ) because 20 is a constant, for instance.

| and || are very different from each other. | is to be used with two integer types to compare individual bits while || compares two boolean expressions. Basically, don't use | unless you know about how to fiddle with bits. In your case, you won't to compare two expressions like so:

if(row<0 || row>2 || col<0 || row>2)

Same with with & and &&. You can &&. I don't want to go into explaining what & and | does, but I recommend looking up tutorials on 'bitwise operators' which should help you understand what's going on.

Another thing, you can pretty much make the code in your about half the size. Consider this: you check all 8 possible winning combinations for both 'x' and 'o'. Why not make one function that compares each winning combination with a variable? Then you only need to change that variable's contents. That's a little confusing so just see this:

// the const in 'const char plyr' isn't needed, but if you do something like:
// plyr = table[0][0] ...
// then the compiler will generate an error instead of working, which would
// assign the value in table[0][0] to plyr. Eg., if plyr had 'x' and
// table[0][0] had 'o', the code wouldn't work.
// Same thing with making the vector table const. We won't accidently
// change the contents of table.
void winner(const vector< vector<char> > &table, const char plyr)
{
if(plyr == table[0][0] && plyr == table[0][1] && plyr == table[0][2])
{
cout << plyr << " is the winner!;";
}
...



We can make the code even smaller though:
bool winner(const vector< vector<char> > &table, const char plyr)
{
if(plyr == table[0][0] && plyr == table[0][1] && plyr == table[0][2])
{
return true; // winner!
}
...
...
return false; // no winner!
}
// later:
if(winner(table, 'x') )
{
cout << "X is the winner!" << endl;
}


Hopefully that will give enough information to both fix and improve your code. If not, I'm rewriting it and will post it to a paste site in a little bit.

Share this post


Link to post
Share on other sites
Ahh ok i understand now. Thanks. The people in this forum are awesome! Two more questions though. Assuming that i use the same code i posted before (not the shorter, but better version posted above me. i am trying to get a feel for both ways), how would i get my winner function to work (the old one). i feel like its written correctly, but im missing something. and why wont the "Sorry, this space has been taken already" statement wont work when i run the program? ive been stuck on those two issues for a while...

Share this post


Link to post
Share on other sites
There are really 3 different things you're trying to do when making sure you have valid input.
1)Is the row in a valid range?
2)Is the column in a valid range?
3)Has anyone moved in this spot before?

What I think you should do is something like this:

do
while row is invalid
get row
while column is invalid
get column
while spot chosen isn't empty


Your logic right now is a little complicated and you don't really do any loops to make sure the input is correct.

Your winning function is pretty good, it could probably be simplified with loops. But not That much simpler. Anyway, I changed my mind with the code paste site because it's not that long and you can just ignore it.
#include <iostream>
#include <vector>
using namespace std;

void displayBoard(const vector< vector<char> > &table);
void getMove(vector< vector<char> > &table, const char player);
bool winner(const vector< vector<char> > &table, const char player);

int main()
{
vector<char> column(3,' ');
vector< vector<char> > table(3,column);

// By using an array we can switch between players
// programmatically instead of hard coding it
char player[2] = {'x', 'o'};
int cur_player = 0; // start with player 'x'
// there are 9 places on the board, so you get as much as 9 moves. Don't forget,
// zero is included so we stop before we get to 9
for(int x = 0; x < 9; x++){
displayBoard(table);
getMove(table, player[cur_player]);
// check for a winner. If there was, say so and break out of the loop
if( winner(table, player[cur_player]) )
{
cout << player[cur_player] << " is the winner!" << endl;
break; // there was a winner, quit playing
}
// switch between players 0 and 1. Do the math and you should figure it out!
cur_player = (cur_player + 1) % 2;
}
return 0;
}

void displayBoard(const vector< vector<char> > &table)
{
for(unsigned int row = 0; row < table.size(); row++)
{
for(unsigned int col = 0; col < table[row].size(); col++)
{ cout << "[" << table[row][col] << "] "; }
cout << endl;
}
}

void getMove(vector< vector<char> > &table, const char player)
{
int row=-1, col=-1;
bool running = true;

while(running)
{
while(row < 0 || row > 2)
{
cout << player << ", please enter row of move <0, 1, or 2>: ";
cin >> row;
}

while(col < 0 || col > 2)
{
cout << player << ", please enter column of move <0, 1, or 2>: ";
cin >> col;
}

// if spot was open, put the symbol at that place and exit loop
// otherwise, give an error and repeat
if(table[row][col] == ' ')
{
table[row][col] = player;
running = false;
}
else
{
cout<<"Sorry, this spot cannot be accepted. Try again." << endl;
}
}
}

bool winner(const vector< vector<char> > &table, const char player)
{
if(table[0][0] == player && table[0][1] == player && table[0][2] == player)
return true;
if(table[1][0] == player && table[1][1] == player && table[1][2] == player)
return true;
if(table[2][0] == player && table[2][1] == player && table[2][2] == player)
return true;
if(table[0][0] == player && table[1][0] == player && table[2][0] == player)
return true;
if(table[0][1] == player && table[1][1] == player && table[2][1] == player)
return true;
if(table[0][2] == player && table[1][2] == player && table[2][2] == player)
return true;
if(table[0][0] == player && table[1][1] == player && table[2][2] == player)
return true;
if(table[2][0] == player && table[1][1] == player && table[0][2] == player)
return true;
return false; // player didn't win.
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!