Hey there. I am taking a programming class using C++ and my assignment is to create "Tictactoe" using ObjectOrientedProgramming... The problem is I have no idea what I am doing...
I need to have a "tictactoe" class file and a "player" class file - each with their own header files and one driver file.

"You will need to have two classes: a TicTacToe class and a Player class. The TicTacToe class should contain the above mentioned 2D array for representing the game board, i.e., this class should have a 2D array of characters as its data member. You should have a zero-argument constructor in the TicTacToe class that will generate the initial game state (all the 2D array elements initialized to '\0'). You should overload the << operator to display the game board at any point. The game board should be displayed along with the grid as shown in the sample executions. There should also be a member function called SetValue that will have three arguments (a row index, a column index, and an integer representing the player index) and a boolean return type. This function will set the specified cell of the 2D array to an appropriate character depending on the player index. This function should also make sure that a player makes its move to a blank and valid (inside the array bounds) position. In case a player wants to make a move to an invalid or already occupied position, it should return false. In case of a valid move, it should return true. There should be another member function called GetStatus that will return an integer (0-3) representing the game status; 0 representing a tie, 1 representing a win by Player1, 2 representing a win by Player2, and 3 otherwise.

The Player class will be relatively simple and will have information such as the player’s name and an integer representing whether he/she is Player1 or Player2. It should have a two-argument constructor to initialize the data members, a member function called GetIndex to return an integer value (1 or 2) depending on whether it’s Player1 or Player2, and a member function called GetName to return the name of the player. There should be a member function called NextMove that will allow a Player object to make a move. This function should accept a TicTacToe object by reference, prompt the player to enter his move, accept the move in the form of the row and column numbers of the position where he wants to make the move (look at the sample execution), and make changes to the 2D array of the TicTacToe object. Note that this function will be calling the SetValue function of the TicTacToe class and will keep on re-prompting the player (as shown in the sample executions) to make another move as long as the SetValue function returns false. Note that the Player class should not have the TicTacToe object as its data member."


So far, all I have is:
tictactoe.cpp

#include <iostream>
 using namespace std;
 #include "tictactoe.h"
 
 Tictactoe::Tictactoe()
{
}
 
 void Tictactoe::displayBoard()
 {
 cout << endl << endl;
 cout << "  " << s[1] << " | " << s[2] << " | " << s[3] << endl;
 cout << " -----------" << endl;
 cout << "  " << s[4] << " | " << s[5] << " | " << s[6] << endl;
 cout << " -----------" << endl;
 cout << "  " << s[7] << " | " << s[8] << " | " << s[9] << endl << endl;
 }

 void Tictactoe::placement()
{
 cout << "Which row please? " << endl;
 cin >> row;
 cout << "Which column please? " << endl;
 cin >> col;
 
 if (row == 1)
 {
  if (col == 1)
  {
   s[1] = 'X';
  }
  else if (col == 2)
  {
   s[2] = 'X';
  }
  else if (col == 3)
  {
   s[3] = 'X';
  }
 }
 else if (row == 2)
 {
  if (col == 1)
  {
   s[4] = 'X';
  }
  else if (col == 2)
  {
   s[5] = 'X';
  }
  else if (col == 3)
  {
   s[6] = 'X';
  }
 }
 else if (row == 3)
 {
  if (col == 1)
  {
   s[7] = 'X';
  }
  else if (col == 2)
  {
   s[8] = 'X';
  }
  else if (col == 3)
  {
   s[9] = 'X';
  }
 }
}

tictactoe.h

class Tictactoe
{
 private:
 int s[9];
 int row, col;
 
 public:
 Tictactoe();
 void displayBoard();
 void placement();
};

player.cpp

#include <iostream>
 using namespace std;
 #include "player.h"
 
 void Player::getName(string name)
 {
  playerName = name;
 }

  int Player::choose(int player)
  {
  int random_integer = rand(); 
  if (random_integer%2)
    {
	  cout << playerName << " goes first." << endl;
	}
  else
    {
	  cout << playerName << " goes first." << endl;
	}
  }

player.h

class Player
{
 private:
 string playerName;
 
 public:
 void getName(string name);
 int choose(int player);
};

and the driver file

#include <iostream>
using namespace std;
#include "tictactoe.h"


int main()
{
 Tictactoe game;
return 0;
}

Any help is greatly appreciated -- mainly I'm not quite sure what is it I need to add to make this work: not looking for code but description of what I'm missing.
Thanks

Recommended Answers

All 7 Replies

int Player::choose(int player)
  {
  int random_integer = rand(); 
  if (random_integer%2)
    {
	  cout << playerName << " goes first." << endl;
	}
  else
    {
	  cout << playerName << " goes first." << endl;
	}
  }

You don't return an integer, and you don't use the parameter passed to this function.

void Tictactoe::displayBoard()
 {
 cout << endl << endl;
 cout << "  " << s[1] << " | " << s[2] << " | " << s[3] << endl;
 cout << " -----------" << endl;
 cout << "  " << s[4] << " | " << s[5] << " | " << s[6] << endl;
 cout << " -----------" << endl;
 cout << "  " << s[7] << " | " << s[8] << " | " << s[9] << endl << endl;
 }

See red above. Using 9 as an array index is out-of-bounds. Legal indexes are 0 through 8 See your declaration below:

class Tictactoe
{
 private:
 int s[9];
 int row, col;
 
 public:
 Tictactoe();
 void displayBoard();
 void placement();
};

Somewhere you need to initialize your tic-tac-toe board to all spaces or whatever represents a blank space. I imagine you want to do this in the constructor. Also, do you have any way to check the board to see if there is a winner?

And you need a Player constructor in addition to your TicTacToe constructor, right?

Thank you. I took your advice and made some changes, as well as added some:
(just putting the class files down for now since they are what I'm struggling with)

tictactoe.cpp

#include <iostream>
 using namespace std;
 #include "tictactoe.h"
 
 Tictactoe::Tictactoe()
{
 	row = 1;
	col = 1;
	for (int i = 1; i < 4; i++)
	{
		for (int j = 1; j < 4; j++)
		{
			board[i][j] = 0;
			square[i][j] = ' ';
		}
	}	
}
 
 void Tictactoe::displayBoard()
 {
	for ( int row = 1; row < 4; row ++)
	{
		for ( int col = 1; col < 4; col++)
		{
			if ( board[row][col] == 0)
			{
				square[row][col] = ' ';
			}
			if ( board[row][col] == 1)
			{
				square[row][col] = 'X';
			}
			if ( board[row][col] == 2)
			{
				square[row][col] = 'O';
			}
		}
	}
 cout << endl << endl;
 cout << "  " << square[1][1] << " | " << square[1][2] << " | " << square[1][3] << endl;
 cout << " -----------" << endl;
 cout << "  " << square[2][1] << " | " << square[2][2] << " | " << square[2][3] << endl;
 cout << " -----------" << endl;
 cout << "  " << square[3][1] << " | " << square[3][2] << " | " << square[3][3] << endl << endl;
 }

 void Tictactoe::placement()
{
 cout << "Which row please? " << endl;
 cin >> row;
 cout << "Which column please? " << endl;
 cin >> col;
 
 if (row == 1)
 {
  if (col == 1)
  {
   square[0] = player;
  }
  else if (col == 2)
  {
   square[1] = player;
  }
  else if (col == 3)
  {
   square[2] = player;
  }
 }
 else if (row == 2)
 {
  if (col == 1)
  {
   square[3] = player;
  }
  else if (col == 2)
  {
   square[4] = player;
  }
  else if (col == 3)
  {
   square[5] = player;
  }
 }
 else if (row == 3)
 {
  if (col == 1)
  {
   square[6] = player;
  }
  else if (col == 2)
  {
   square[7] = player;
  }
  else if (col == 3)
  {
   square[8] = player;
  }
 }
}

 bool Tictactoe::checkForWin()
 {
  if (square[1][1] == square[1][2] && square[1][1] == square[1][3])
   return true;
  else if (square[2][1] == square[2][2] && square[2][1] == square[2][3])
   return true;
  else if (square[3][1] == square[3][2] && square[3][1] == square[3][3])
   return true;
  else if (square[1][1] == square[2][1] && square[1][1] == square[3][1])
   return true;
  else if (square[1][2] == square[2]2] && square[1][2] == square[3][2])
   return true;
  else if (square[1][3] == square[2][3] && square[1][3] == square[3][3])
   return true;
  else if (square[1][1] == square[2][2] && square[1][1] == square[3][3])
   return true;
  else if (square[1][3] == square[2][2] && square[1][3] == square[3][1])
   return true;
  else
   return false;
 }
 
 bool Tictactoe::checkSpot(int row, int col)
 {
  if (row != 1 && row != 2 && row != 3)
  {
   cout << "Choose again." << endl;
   return false;
  }
  else if (col != 1 && col != 2 && col != 3)
  {
   cout << "Choose again." << endl;
   return false;
  }
  else if (board[row][col] == 1 || board[row][col] == 2)
  {
   cout << "Already occupied. Choose again." << endl;
   return false;
  }
  else
  {
   board[row][col] = player;
   return true;
  }
 }

player.cpp

#include <iostream>
 using namespace std;
 #include "player.h"
 #include "tictactoe.h"
 
 void Player::getName(string name)
 {
  playerName = name;
 }

  int Player::choose(int &player)
  {
   int random_integer = rand(); 
   if (random_integer%2)
    player = 2;
   else
    player = 1;
  }

In tictactoe.cpp function "void Tictactoe::placement()" I'm not sure how to get the result of "player" from the function in the player class "int Player::choose(int &player)" - a 1 or 2 which corresponds into x or o respectively - and use it in this function...
Much thanks.

You've changed your variables, so you need to post the tictactoe.h and player.h files.

tictactoe.h

class Tictactoe
{
 private:
 int s[9];
 int row, col;
 char square[3][3];
 char board[3][3];
 
 public:
 Tictactoe();
 void displayBoard();
 void placement();
 bool checkForWin();
 bool checkSpot(int row, int col);
};

player.h

class Player
{
 private:
 string playerName;
 
 public:
 void getName(string name);
 int choose(int &player);
};

tictactoe.h

class Tictactoe
{
 private:
 int s[9];
 int row, col;
 char square[3][3];
 char board[3][3];
 
 public:
 Tictactoe();
 void displayBoard();
 void placement();
 bool checkForWin();
 bool checkSpot(int row, int col);
};

player.h

class Player
{
 private:
 string playerName;
 
 public:
 void getName(string name);
 int choose(int &player);
};

I see arrays s (one dimensional), square (two dimensional) and board (2 dimensional). Is s used? board and square seem to store the same information, even though they store it differently. Do you need/want both?

I see these lines:

if (row == 1)
 {
  if (col == 1)
  {
   square[0] = player;
  }
  else if (col == 2)
  {
   square[1] = player;
  }
  else if (col == 3)
  {
   square[2] = player;
  }
 }

which are legal (you CAN map a 2-D array to 1-D index, but I think it makes the code harder to follow), but I would take advantage of the fact that it is a 2-D array and do this:

square[row-1][col-1] = player;

The code is easier to read and is shorter. You are also less likely to make an error when converting back to a 2-D array like you do here:

bool Tictactoe::checkForWin()
 {
  if (square[1][1] == square[1][2] && square[1][1] == square[1][3])
   return true;
  else if (square[2][1] == square[2][2] && square[2][1] == square[2][3])
   return true;
  else if (square[3][1] == square[3][2] && square[3][1] == square[3][3])
   return true;
  else if (square[1][1] == square[2][1] && square[1][1] == square[3][1])
   return true;
  else if (square[1][2] == square[2]2] && square[1][2] == square[3][2])
   return true;
  else if (square[1][3] == square[2][3] && square[1][3] == square[3][3])
   return true;
  else if (square[1][1] == square[2][2] && square[1][1] == square[3][3])
   return true;
  else if (square[1][3] == square[2][2] && square[1][3] == square[3][1])
   return true;
  else
   return false;
 }

Legal indexes are 0 through 2, not 1 through 3. Everything starts at 0, so square[3][3] is a segmentation fault. Thus you should ask for rows and columns of 0 through 2, or ask for rows and columns of 1 through 3, then subtract 1, but you must STORE everything as indexes 0 through 2, not 1 through 3. Arrays always start at 0, not 1.

Ok classes seem to be working fine -- I'm posting them in case anyone runs into this kind of program. They all compile without any errors :D

player.h

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

class Player
{
 private:
 string playerName;
 
 public:
 void getName(string n);
 int getIndex();
};

player.cpp

#include <iostream>
#include <string>
 using namespace std;
 #include "player.h"
 #include "tictactoe.h"
 
 void Player::getName(string n)
 {
  playerName = n;
  cout << playerName;
 }

  int Player::getIndex()
  {
   srand((unsigned)time(0)); 
   int random_integer = rand(); 
   if (random_integer%2)
    return 2;
   else
    return 1;
  }

tictactoe.h

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

class Tictactoe
{
 private:
 int row, col;
 char square[3][3];
 
 public:
 Tictactoe();
 void displayBoard(ostream & out);
 bool setValue(int row, int col, char player);
 int getStatus();
};

tictactoe.cpp

#include <iostream>
#include <string>
using namespace std;
#include "tictactoe.h"
 
Tictactoe::Tictactoe()
{
 	row = 0;
	col = 0;
	char player = '\0';
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			square[i][j] = player;
		}
	}	
}
 
void Tictactoe::displayBoard(ostream & out)
 {
 out << endl << endl
	 << "  " << square[1][1] << " | " << square[1][2] << " | " << square[1][3] << endl
	 << " -----------" << endl
	 << "  " << square[2][1] << " | " << square[2][2] << " | " << square[2][3] << endl
	 << " -----------" << endl
	 << "  " << square[3][1] << " | " << square[3][2] << " | " << square[3][3] << endl << endl;
 }

bool Tictactoe::setValue(int row, int col, char player)
{
  row = row - 1;
  col = col - 1;
  if (row != 0 && row != 1 && row != 2)
  {
   return false;
  }
  else if (col != 0 && col != 1 && col != 2)
  {
   return false;
  }
  else if ((square[row][col] = 'X') || (square[row][col] = 'O'))
  {
   return false;
  }
  else
  {
   square[row][col] = player;
   return true;
  }
}

int Tictactoe::getStatus()
 {
  if (square[0][0] == square[0][1] && square[0][0] == square[0][2])
	 return true;
  else if (square[1][0] == square[1][1] && square[1][0] == square[1][2])
	 return true;
  else if (square[2][0] == square[2][1] && square[2][0] == square[2][2])
	 return true;
  else if (square[0][0] == square[1][0] && square[0][0] == square[2][0])
	 return true;
  else if (square[0][1] == square[1][1] && square[0][1] == square[2][1])
	 return true;
  else if (square[0][2] == square[1][2] && square[0][2] == square[1][2])
	 return true;
  else if (square[0][0] == square[1][1] && square[0][0] == square[2][2])
	 return true;
  else if (square[0][2] == square[1][1] && square[0][2] == square[2][0])
	 return true;
  else
	 return false;
 }

Ok classes seem to be working fine -- I'm posting them in case anyone runs into this kind of program. They all compile without any errors :D

void Tictactoe::displayBoard(ostream & out)
 {
 out << endl << endl
	 << "  " << square[1][1] << " | " << square[1][2] << " | " << square[1][3] << endl
	 << " -----------" << endl
	 << "  " << square[2][1] << " | " << square[2][2] << " | " << square[2][3] << endl
	 << " -----------" << endl
	 << "  " << square[3][1] << " | " << square[3][2] << " | " << square[3][3] << endl << endl;
 }

They may compile without error, but it's doubletful that they'll run without error. You still have array indexes going from 1 to 3 instead of 0 to 2.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.