Archived

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

TicTacToe Help...

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

Ok, well this is my first time post. And im getting to understand C++ a little better after some practice and i decided to try a simple TicTacToe game, but now i have some problems. I''ll ask for player1''s move, then ill draw the board, but it will assign that input to my Move[8] char variable for the board output along with assigning X to the number i selected. Ill show you the code, i''m a newb so and suggestions to what i should do to make the code more efficent would help too, thanks.
  

#include <iostream>

using namespace std;

class TicTacToe
{
public:
	TicTacToe();
	void SetVariables();
	void DrawBoard();
	void SetMove1();
	void SetMove2();
	void Player1();
	void Player2();
	void SetTurn1();
	void SetTurn2();

private:
	char Move[8];
	char Player1Move;
	char Player2Move;
	bool Player1turn;
	bool Player2turn;
};

void TicTacToe::SetVariables()
{
	Move[0] = ''1'';
	Move[1] = ''2'';
	Move[2] = ''3'';
	Move[3] = ''4'';
	Move[4] = ''5'';
	Move[5] = ''6'';
	Move[6] = ''7'';
	Move[7] = ''8'';
	Move[8] = ''9'';
	Player1turn = true;

} //End SetVariables


TicTacToe::TicTacToe()
{
} //End Constructor



void TicTacToe::DrawBoard()
{
	cout << " " << Move[0] << " | " << Move[1] << " | " << Move[2] << endl;
	cout << "---+---+---" << endl;
	cout << " " << Move[3] << " | " << Move[4] << " | " << Move[5] << endl;
	cout << "---+---+---" << endl;
	cout << " " << Move[6] << " | " << Move[7] << " | " << Move[8] << endl;

} //End DrawBoard


void TicTacToe::Player1()
{
	cout << "Player1 make a move: ";
	cin >> Player1Move;

} //End Player1


void TicTacToe::Player2()
{
	cout << "Player2 make a move: ";
	cin >> Player2Move;

} //End Player2


void TicTacToe::SetMove1()
{ 
	if (Player1turn == true)
	{

	switch (Player1Move)
	{

	case ''1'':
		Move[0] = ''X'';
		break;
	case ''2'':
		Move[1] = ''X'';
		break;
	case ''3'':
		Move[2] = ''X'';
		break;
	case ''4'':
		Move[3] = ''X'';
		break;
	case ''5'':
		Move[4] = ''X'';
		break;
	case ''6'':
		Move[5] = ''X'';
		break;
	case ''7'':
		Move[6] = ''X'';
		break;
	case ''8'':
		Move[7] = ''X'';
		break;
	case ''9'':
		Move[8] = ''X'';
		break;

	default:
		cout << "\nNot a valid move!" << endl;

	} //End Switch

	} //End if statement


} //End SetMove1


void TicTacToe::SetMove2()
{
	if (Player2turn == true)
	{

	switch (Player2Move)
	{

	case ''1'':
		Move[0] = ''O'';
		break;
	case ''2'':
		Move[1] = ''O'';
		break;
	case ''3'':
		Move[2] = ''O'';
		break;
	case ''4'':
		Move[3] = ''O'';
		break;
	case ''5'':
		Move[4] = ''O'';
		break;
	case ''6'':
		Move[5] = ''O'';
		break;
	case ''7'':
		Move[6] = ''O'';
		break;
	case ''8'':
		Move[7] = ''O'';
		break;
	case ''9'':
		Move[8] = ''O'';
		break;

	default:
		cout << "\nNot a valid move!" << endl;

	} //End Switch

	} //End if statement

}

void TicTacToe::SetTurn1()
{
	Player1turn = true;
	Player2turn = false;
} //End Setturn1


void TicTacToe::SetTurn2()
{
	Player2turn = true;
	Player1turn = false;
} //End Setturn2


int main()
{
	TicTacToe Game;

	Game.SetVariables();
	Game.DrawBoard();
	Game.Player1();
	Game.SetMove1();
	Game.SetTurn2();
	Game.DrawBoard();
	Game.Player2();
	Game.SetMove2();
	Game.SetTurn1();
	Game.DrawBoard();
	Game.Player1();
	Game.SetMove1();
	Game.SetTurn2();
	Game.DrawBoard();

	return 0;

}  //End Main


  
If you run the code and look you''ll understand better what im trying to say, heh. Thanks in advance.

Share this post


Link to post
Share on other sites
That should be Move[9], as the board has nine squares, numbered from 0 to 8.

You might want to loop over the game steps like while (game not finished) { ... } instead of having a huge list of all the steps.


Helpful links:
How To Ask Questions The Smart Way | Google can help with your question | Search MSDN for help with standard C or Windows functions

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I''m just a newbie myself too, but I think you don''t need to have seperate functions for the two players, you can combine them somehow so it will look a little smarter. Another thing, I think you could use the constructor for the game loop, I''m not sure about that, I haven''t studied program structure much yet. So, somebody please confirm this?

Share this post


Link to post
Share on other sites
In your class your define Move[8]. This is an 8-element array numbered from 0 to 7, which is not what you want. Overwriting the array memory like you''re doing could cause a crash.


Helpful links:
How To Ask Questions The Smart Way | Google can help with your question | Search MSDN for help with standard C or Windows functions

Share this post


Link to post
Share on other sites
Looks like your not doing any error checking to see if the spot was previously taken. Though I guess that will come later, along with checking for wins. I had to write a Tic-Tac-Toe program in May for a Computer Science course, so if you need any help, just ask and I can post some code.

|.dev-c++.|.the gimp.|.seti@home.|.try2hack.|.torn.|

Share this post


Link to post
Share on other sites
Please... at least start with replacing your Player1/2() and SetMove1/2() with a function like this:

    
void TicTacToe::Play(int nPlayer)
{
int nMove;

// Get move

cout << "Player" << nPlayer << " make a move: ";
cin >> nMove;

// Make it zero-based

nMove -= 1;

// Discard invalid move (also added collision checking)

if(nMove < 0 || nMove > 8 || this.Move[nMove] != (nMove + 0x30 + 1)) {
cout << "\nNot a valid move!" << endl;
return;
}

// Otherwise set move

this.Move[nMove] = (nPlayer == 1) ? 'X' : 'O';
}

Not tested though, but should clean up some.

EDIT: Ooopss, some errors there...

[edited by - CWizard on August 30, 2002 7:27:13 PM]

Share this post


Link to post
Share on other sites
Ohh, now i see siaspete, yeah now it works now, thanks alot. Yes its very basic right now and later on ill make more enhancements to it, i just wanna get it to be a working game right now. CWizard ill try your code out, i kinda see what your doing ill work on it. Thanks to everyone who replied.

Share this post


Link to post
Share on other sites
Ok CWizard i got your code in and working, i understand how it works and all except this part..

Move[nMove] != (nMove + 0x30 + 1

Could you take the time to explain what thats doing? I would really appreciate it. And now im starting on the check win function its all a bunch of if statements now :^\.

Anyways thanks!

Share this post


Link to post
Share on other sites
quote:
Original post by FiXXoR
... i understand how it works and all except this part..

Move[nMove] != (nMove + 0x30 + 1)


Hopefully it works like this. You initialize your Move array with the ASCII values of "1" through "9", which in hex are 0x31-0x39. The test above is to check if anything is on that spot, and should evaluate to TRUE, if the position where the user tried to move is not equal to its initialization value. In short, when the Move[] array is just initialize the following is true: Move[n] == (0x31 + n) where 0 <= n <= 8. If that equation isn''t TRUE then the spot is taken.

This was just something I added while typing, and you should use some other technique to check if the spot is free.

Share this post


Link to post
Share on other sites
Argh, ok i have some problems. Im working on a function that checks to see if there is a winner. But when i win it will ask for the other players input still.. i tryed a couple things to get it to catch that i''ve won and stop but it will not do it. And when i make a line with X O X it will say player one wins (ugh). Well of course any help is very appreciated, ive learned somethings from starting this project so it isnt a total loss, and i would like to finish it.



  
#include <iostream>

using namespace std;

class TicTacToe
{
public:
TicTacToe();
void SetVariables();
void DrawBoard();
void Play(int Player);
void CheckWin(bool Win, bool GameOver);

private:
char Move[9];
char Player1Move;
int Player;
bool Win, GameOver;
};

void TicTacToe::SetVariables()
{
Move[0] = ''1'';
Move[1] = ''2'';
Move[2] = ''3'';
Move[3] = ''4'';
Move[4] = ''5'';
Move[5] = ''6'';
Move[6] = ''7'';
Move[7] = ''8'';
Move[8] = ''9'';
Win = false;
GameOver = false;

} //End SetVariables


TicTacToe::TicTacToe()
{
SetVariables();
DrawBoard();
Play(Player = 1);

} //End Constructor



void TicTacToe::DrawBoard()
{
cout << endl;
cout << " " << Move[0] << " | " << Move[1] << " | " << Move[2] << endl;
cout << "---+---+---" << endl;
cout << " " << Move[3] << " | " << Move[4] << " | " << Move[5] << endl;
cout << "---+---+---" << endl;
cout << " " << Move[6] << " | " << Move[7] << " | " << Move[8] << endl;
cout << endl;

} //End DrawBoard



void TicTacToe::Play(int nPlayer)
{
int nMove; // Get move


while (!GameOver)
{

cout << "Player" << Player << " make a move: ";
cin >> nMove; // Make it zero-based


nMove -= 1;

// Discard invalid move (also added collision checking)


if (nMove < 0 || nMove > 8 || Move[nMove] != (nMove + 0x30 + 1))
{
cout << "\nNot a valid move!\n" << endl;
return;
}
// Otherwise set move


Move[nMove] = (Player == 1) ? ''X'' : ''O'';

DrawBoard();
CheckWin(Win, GameOver);

if (Player == 1)
Player = 2;
else
Player = 1;
} //End Loop


} //End Play


void TicTacToe::CheckWin(bool Win, bool GameOver)
{
if (Move[0] && Move[1] && Move[2] == ''X'')

Win = true;
if (Move[3] && Move[4] && Move[5] == ''X'')

Win = true;
if (Move[6] && Move[7] && Move[8] == ''X'')

Win = true;
if (Move[0] && Move[3] && Move[6] == ''X'')

Win = true;
if (Move[1] && Move[4] && Move[7] == ''X'')

Win = true;
if (Move[2] && Move[5] && Move[8] == ''X'')

Win = true;
if (Move[0] && Move[4] && Move[8] == ''X'')

Win = true;
if (Move[2] && Move[4] && Move[6] == ''X'')

Win = true;

if (Move[0] && Move[1] && Move[2] == ''O'')

Win = true;
if (Move[3] && Move[4] && Move[5] == ''O'')

Win = true;
if (Move[6] && Move[7] && Move[8] == ''O'')

Win = true;
if (Move[0] && Move[3] && Move[6] == ''O'')

Win = true;
if (Move[1] && Move[4] && Move[7] == ''O'')

Win = true;
if (Move[2] && Move[5] && Move[8] == ''O'')

Win = true;
if (Move[0] && Move[4] && Move[8] == ''O'')

Win = true;
if (Move[2] && Move[4] && Move[6] == ''O'')

Win = true;

if (Win)
cout << endl << "Player" << Player << " Wins!" << endl;
GameOver = true;


} //End Checkwin



int main()
{
TicTacToe Game;

TicTacToe();

return 0;

} //End Main

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Try changing
<code>
if (Move[0] && Move[1] && Move[2] == ''X'')
</code>
to:
<code>
if ((Move[0] == ''X'') && (Move[1] == ''X'') && (Move[2] == ''X''))
</code>
Also, this if statement
<code>
if (Win)
cout << endl << "Player" << Player << " Wins!" << endl; GameOver = true;
</code>
needs brackets, like so:
<code>
if (Win)
{
cout << endl << "Player" << Player << " Wins!" << endl; GameOver = true;
}
</code>

Share this post


Link to post
Share on other sites
Win detection in Tic-Tac-Toe:

3x3 Matrix or Simpler 9 cells:

0 1 2
3 4 5
6 7 8

So, There are eight ways to win.
0 1 2 4 1 7 8 2 5
0 3 6 4 2 6 8 6 7
0 4 8 4 3 5

This tester must be checked after every turn in Tic-Tac-Toe!!

Input:

Cell - a 9 element char array for a TicTacToe matrix
Players_Symbol - will be only X or Y for tic-tac-toe.

bool TicTacToe_Win_Tester(char *Cell, char Players_Symbol)
{
// Returns True if Players_Symbol matches a win
// Otherwise it returns false

// Check if player owns upperleft corner
if(Cell[0]==Players_Symbol)
{
// Check if player has won the first way (0,1,2)
if((Cell[1]==Players_Symbol)&&(Cell[2]==Players_Symbol))
{return(true)}
// Check if player has won the second way (0,3,6)
if((Cell[3]==Players_Symbol)&&(Cell[6]==Players_Symbol))
{return(true)}
// Check if player has won the third way (0,4,8)
if((Cell[4]==Players_Symbol)&&(Cell[8]==Players_Symbol))
{return(true)}
}

// Check if player owns Center
if(Cell[4]==Players_Symbol)
{
// Check if player has won the forth way (4,1,7)
if((Cell[1]==Players_Symbol)&&(Cell[7]==Players_Symbol))
{return(true)}
// Check if player has won the fifth way (4,2,6)
if((Cell[2]==Players_Symbol)&&(Cell[6]==Players_Symbol))
{return(true)}
// Check if player has won the sixth way (4,3,5)
if((Cell[3]==Players_Symbol)&&(Cell[5]==Players_Symbol))
{return(true)}
}

// Finally, Check if player owns bottomright corner
if(Cell[8]==Players_Symbol)
{
// Check if player has won the seventh way (8,2,5)
if((Cell[2]==Players_Symbol)&&(Cell[5]==Players_Symbol))
{return(true)}
// Check if player has won the eighth way (8,6,7)
if((Cell[6]==Players_Symbol)&&(Cell[7]==Players_Symbol))
{return(true)}
}

// End of function TicTacToe_Win_Tester
return(false) // Sorry Didn''t Win
}


Boy, that''s alot of typing.
This sould work just fine.
If anyone knows a better way please post it, Thank you.

Share this post


Link to post
Share on other sites

    
char winning_combos[8][3] =
{
{ 0, 1, 2 },
{ 4, 1, 7 },
{ 8, 2, 5 },
{ 0, 3, 6 },
{ 4, 2, 6 },
{ 8, 6, 7 },
{ 0, 4, 8 },
{ 4, 3, 5 }

};


bool TicTacToe_Win_Tester(char *Cell, char Players_Symbol)
{
for(int i=0;i<8;i++)
{
if( Cell[ winning_combos[i][0] ] == Players_Symbol &&
Cell[ winning_combos[i][1] ] == Players_Symbol &&
Cell[ winning_combos[i][2] ] == Players_Symbol)
{
return true;
}
}

return false;
}


How about that? (Hope it works now ) Of course there are other things you could do to it but it gives the idea.




[edited by - JuNC on September 6, 2002 7:38:38 AM]

Share this post


Link to post
Share on other sites
Cool JuNC, nice compact code!

But, it may be a little slower. (Big deal huh, its just TicTacToe)

This should show there are planty of ways to skin a cat but some just work better(easier to maintain) and look simpler(easier to understand).

Thanks again!!

Share this post


Link to post
Share on other sites
Wow, alot of code i have to go over. Anonymous Poster thanks for reminding me, i totally forgot about including that == ''X'' after every variable check, ugh! But ill see if i can try to implement and understand your guy''s other code. Thanks alot!

Share this post


Link to post
Share on other sites
Ok, well ive been messing with it for a while now and i just cant understand why the loop does not end when a player wins. I tryed tracing the GameOver variable and it doesnt change from false to true for some reason. Can anyone figure this out?

Share this post


Link to post
Share on other sites
You only have to check two things to determine if tic-tac-toe is done being played.

First, has the current player''s move won that player the game. Second, after the move was made are there no more empty cells left to move into.

So, just keep track of how many empty cells there are left and when it is zero the loop should exit. And if that happens that means the game was a draw.

And check after each move to see if the current player has won.

Main Program Flow for Tic=Tac-Toe:
.Initialize (Current Player, Next Player, and Empty Cell Count)

.While there is a Move (empty cell)
...Current player Moves by choosing an empty cell
....subtract 1 from emtpy cell count
....if player has one of the 8 winning squences the player wins
.....and the game ends
...Swap Current Player with Next Player
.End of Main Loop

.All Moves where made and no one won so it was a Draw
.Game ends

Share this post


Link to post
Share on other sites