7 Replies - 1038 Views - Last Post: 27 February 2012 - 09:32 AM Rate Topic: -----

#1 zim1985  Icon User is offline

  • Grand Inquisitor
  • member icon

Reputation: 74
  • View blog
  • Posts: 568
  • Joined: 19-February 10

TicTacToe Game and Private Member Functions

Posted 27 February 2012 - 03:57 AM

#include <cstdlib>
#include <iostream>

using namespace std;

class Game
{
	private:
		char board[3][3];

		bool rowWin()
		{
			for(int i = 0; i < 3; i++)
			{
				for(int j = 0; j < 3; j++)
				{
					if((board[i][j] == board[i+1][j] && board[i][j] == board[i+2][j]) || (board[i][j] == board[i][j+1] && board[i][j] == board[i][j+2])) //condition for 3 in a row
					{
						if(board[i][j] == '+') cout << "Player 1 has won.";
						else cout << "Player 2 has won.";
						return true;
					}
					else return false;
				}
			}
		}

		bool diagWin()
		{
			if((board[0][0] == board[1][1] && board[0][0] == board[2][2]) || (board[0][2] == board[1][1] && board[0][2] == board[2][0]))
			{
				if(board[0][0] == '+' || board[0][2] == '+') cout << "Player 1 has won.";
				else cout << "Player 2 has won.";
				return true;
			}
			else return false;
		}

	public:
		Game()
		{
			for(int i = 0; i < 3; i++)
				for(int j = 0; j < 3; j++)
					board[i][j] = '*';
		}
		
		void setSpot(int player, int i, int j)
		{
			if(player == 1) board[i][j] = '+';
			else board[i][j] = '0';
		}

		void printBoard()
		{
			cout << "-------";
			for(int i = 0; i < 3; i++)
			{
				cout << "\n|";
				for(int j = 0; j < 3; j++)
				{
					cout << board[i][j] << "|";
				}
			}
			cout << "\n-------";
		}

		bool hasWon()
		{
			return rowWin() && diagWin();
		}

		void doTurn()
		{
			int m, n;
			for(int i = 0; i < 2; i++)
			{
				printBoard();
				do
				{
					cout << "\n\nPlayer " << i+1 << " enter row and column of your move. (1-3):   ";
					cin >> m >> n;
					setSpot(i, m-1, n-1);
				} while((m > 0 || n < 4) && (n > 0 || n < 4));
			}
			
		}
};

int main()
{
	Game tic;

	cout << "Welcome to the Tic-Tac-Toe game!\n";
	system("PAUSE");
	do
	{
		system("CLS");
		tic.doTurn();
		system("PAUSE");
	} while(tic.hasWon());

	
}



I'm getting some errors with this code. I'm pretty sure it has something to do with the input. I've also never used private member functions before, so that might have some issues as well. I'm not entirely sure.

Is This A Good Question/Topic? 0
  • +

Replies To: TicTacToe Game and Private Member Functions

#2 Hezekiah  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 207
  • View blog
  • Posts: 552
  • Joined: 12-July 09

Re: TicTacToe Game and Private Member Functions

Posted 27 February 2012 - 07:27 AM

Quote

I'm getting some errors with this code.

Copy them and paste them here. If you don't get the output you expect, post the input, output and expected output.

		bool rowWin()
		{
			for(int i = 0; i < 3; i++)
			{
				for(int j = 0; j < 3; j++)
				{
					if((board[i][j] == board[i+1][j] && board[i][j] == board[i+2][j]) || (board[i][j] == board[i][j+1] && board[i][j] == board[i][j+2])) //condition for 3 in a row
					{
						if(board[i][j] == '+') cout << "Player 1 has won.";
						else cout << "Player 2 has won.";
						return true;
					}
					else return false;
				}
			}
		}

This will access board with invalid indices. When i=1, i+2 will be an invalid index. When i=2, i+1 and i+2 will be invalid indices. You have the same problem with j. You only need one loop here. The counter can be used where you didn't do i+x or j+x (where x is 0, 1 or 2). The other index should use the values 0, 1 and 2:
for(int i = 0; i < 3; ++i) {
	if((board[0][i] == board[1][i] && board[0][i] == board[2][i])
		|| (board[i][0] == board[i][1] && board[i][0] == board[i][2])) {
		//game over
	}
}
//continue playing

The return should also be only after the loop.

		bool diagWin()
		{
			if((board[0][0] == board[1][1] && board[0][0] == board[2][2]) || (board[0][2] == board[1][1] && board[0][2] == board[2][0]))
			{
				if(board[0][0] == '+' || board[0][2] == '+') cout << "Player 1 has won.";
				else cout << "Player 2 has won.";
				return true;
			}
			else return false;
		}

Testing if either board[0][0] or board[0][2] is + could give the wrong result. Rather test board[1][1], which is part of both diagonal rows.

		bool hasWon()
		{
			return rowWin() && diagWin();
		}

That should be ||. You only need one row to win.

		void doTurn()
		{
			int m, n;
			for(int i = 0; i < 2; i++)
			{
				printBoard();
				do
				{
					cout << "\n\nPlayer " << i+1 << " enter row and column of your move. (1-3):   ";
					cin >> m >> n;
					setSpot(i, m-1, n-1);
				} while((m > 0 || n < 4) && (n > 0 || n < 4));
			}
			
		}

The first parameter to setSpot() should be i+1. The loop condition isn't correct. You want to continue while m<=0 or m>3 or n<=0 or n>3. The call to setSpot() should be after the loop.

int main()
{
	Game tic;

	cout << "Welcome to the Tic-Tac-Toe game!\n";
	system("PAUSE");
	do
	{
		system("CLS");
		tic.doTurn();
		system("PAUSE");
	} while(tic.hasWon());

	
}

You want to continue playing while nobody has won, so add a not (!).
Was This Post Helpful? 1
  • +
  • -

#3 zim1985  Icon User is offline

  • Grand Inquisitor
  • member icon

Reputation: 74
  • View blog
  • Posts: 568
  • Joined: 19-February 10

Re: TicTacToe Game and Private Member Functions

Posted 27 February 2012 - 08:02 AM

View PostHezekiah, on 27 February 2012 - 06:27 AM, said:

Quote

I'm getting some errors with this code.

Copy them and paste them here. If you don't get the output you expect, post the input, output and expected output.

		bool rowWin()
		{
			for(int i = 0; i < 3; i++)
			{
				for(int j = 0; j < 3; j++)
				{
					if((board[i][j] == board[i+1][j] && board[i][j] == board[i+2][j]) || (board[i][j] == board[i][j+1] && board[i][j] == board[i][j+2])) //condition for 3 in a row
					{
						if(board[i][j] == '+') cout << "Player 1 has won.";
						else cout << "Player 2 has won.";
						return true;
					}
					else return false;
				}
			}
		}

This will access board with invalid indices. When i=1, i+2 will be an invalid index. When i=2, i+1 and i+2 will be invalid indices. You have the same problem with j. You only need one loop here. The counter can be used where you didn't do i+x or j+x (where x is 0, 1 or 2). The other index should use the values 0, 1 and 2:
for(int i = 0; i < 3; ++i) {
	if((board[0][i] == board[1][i] && board[0][i] == board[2][i])
		|| (board[i][0] == board[i][1] && board[i][0] == board[i][2])) {
		//game over
	}
}
//continue playing

The return should also be only after the loop.

		bool diagWin()
		{
			if((board[0][0] == board[1][1] && board[0][0] == board[2][2]) || (board[0][2] == board[1][1] && board[0][2] == board[2][0]))
			{
				if(board[0][0] == '+' || board[0][2] == '+') cout << "Player 1 has won.";
				else cout << "Player 2 has won.";
				return true;
			}
			else return false;
		}

Testing if either board[0][0] or board[0][2] is + could give the wrong result. Rather test board[1][1], which is part of both diagonal rows.

		bool hasWon()
		{
			return rowWin() && diagWin();
		}

That should be ||. You only need one row to win.

		void doTurn()
		{
			int m, n;
			for(int i = 0; i < 2; i++)
			{
				printBoard();
				do
				{
					cout << "\n\nPlayer " << i+1 << " enter row and column of your move. (1-3):   ";
					cin >> m >> n;
					setSpot(i, m-1, n-1);
				} while((m > 0 || n < 4) && (n > 0 || n < 4));
			}
			
		}

The first parameter to setSpot() should be i+1. The loop condition isn't correct. You want to continue while m<=0 or m>3 or n<=0 or n>3. The call to setSpot() should be after the loop.

int main()
{
	Game tic;

	cout << "Welcome to the Tic-Tac-Toe game!\n";
	system("PAUSE");
	do
	{
		system("CLS");
		tic.doTurn();
		system("PAUSE");
	} while(tic.hasWon());

	
}

You want to continue playing while nobody has won, so add a not (!).

That was beyond helpful. I've been up all night trying to get this to work properly and you just fixed so many of my errors in seconds.

It seems now that my program is stuck where I run the test for a winning board. After the second turn, the game decides that Player 2 has won, when he obviously has not, and then quits.

#include <cstdlib>
#include <iostream>

using namespace std;

class Game
{
	private:
		char board[3][3];

		bool rowWin()
		{
			for(int i = 0; i < 3; i++)
			{
				for(int j = 0; j < 3; j++)
				{
					if((board[i][j] == board[i+1][j] && board[i][j] == board[i+2][j]) || (board[i][j] == board[i][j+1] && board[i][j] == board[i][j+2])) //condition for 3 in a row
					{
						if(board[i][j] == '+') cout << "Player 1 has won.";
						else cout << "Player 2 has won.";
						return true;
					}
					else return false;
				}
			}
		}

		bool diagWin()
		{
			if((board[0][0] == board[1][1] && board[0][0] == board[2][2]) || (board[0][2] == board[1][1] && board[0][2] == board[2][0]))
			{
				if(board[1][1] == '+') cout << "Player 1 has won.";
				else cout << "Player 2 has won.";
				return true;
			}
			else return false;
		}

	public:
		Game()
		{
			for(int i = 0; i < 3; i++)
				for(int j = 0; j < 3; j++)
					board[i][j] = '*';
		}
		
		void setSpot(int player, int i, int j)
		{
			if(player == 1) board[i][j] = '+';
			else board[i][j] = '0';
		}

		void printBoard()
		{
			cout << "-------";
			for(int i = 0; i < 3; i++)
			{
				cout << "\n|";
				for(int j = 0; j < 3; j++)
				{
					cout << board[i][j] << "|";
				}
			}
			cout << "\n-------";
		}

		bool hasWon()
		{
			return rowWin() || diagWin();
		}

		void doTurn()
		{
			int m, n;
			for(int i = 0; i < 2; i++)
			{
				printBoard();
				do
				{
					cout << "\n\nPlayer " << i+1 << " enter row and column of your move. (1-3):   ";
					cin >> m >> n;
					setSpot(i+1, m-1, n-1);
				} while(m <= 0 || m > 3 || n <= 0 || n > 3);
			}
			
		}
};

int main()
{
	Game tic;

	cout << "Welcome to the Tic-Tac-Toe game!\n";
	system("PAUSE");
	do
	{
		system("CLS");
		tic.doTurn();
		system("PAUSE");
	} while(!tic.hasWon());

	return 0;
}


I'll continue tweaking and trying to find the error, which I suspect lies in the diagWin function, but I'll leave this here in case anyone else has some better ideas.

Also, sorry. I'm not new to coding, but I am relatively new to C++.

This post has been edited by zim1985: 27 February 2012 - 08:06 AM

Was This Post Helpful? 0
  • +
  • -

#4 Hezekiah  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 207
  • View blog
  • Posts: 552
  • Joined: 12-July 09

Re: TicTacToe Game and Private Member Functions

Posted 27 February 2012 - 08:18 AM

You haven't fixed the rowWin() function. Did you understand my explanation (I don't think I would)? Have another look at my code example, and ask if you don't understand.
Was This Post Helpful? 0
  • +
  • -

#5 zim1985  Icon User is offline

  • Grand Inquisitor
  • member icon

Reputation: 74
  • View blog
  • Posts: 568
  • Joined: 19-February 10

Re: TicTacToe Game and Private Member Functions

Posted 27 February 2012 - 08:20 AM

View PostHezekiah, on 27 February 2012 - 07:18 AM, said:

You haven't fixed the rowWin() function. Did you understand my explanation (I don't think I would)? Have another look at my code example, and ask if you don't understand.

I think I get what you were saying in general. Since only one variable really changes, I don't need the nested loops. I'll fix that and then post back and see if it changes anything...

OH also because the array will go out of bounds if I don't do it this way. I get it.

This post has been edited by zim1985: 27 February 2012 - 08:24 AM

Was This Post Helpful? 0
  • +
  • -

#6 zim1985  Icon User is offline

  • Grand Inquisitor
  • member icon

Reputation: 74
  • View blog
  • Posts: 568
  • Joined: 19-February 10

Re: TicTacToe Game and Private Member Functions

Posted 27 February 2012 - 08:28 AM

View PostHezekiah, on 27 February 2012 - 07:18 AM, said:

You haven't fixed the rowWin() function. Did you understand my explanation (I don't think I would)? Have another look at my code example, and ask if you don't understand.

I fixed the rest of what you said to fix. I ran the program again and got the same error.

I entered 1 3 for Player 1.
Then 2 3 for Player 2.
The game quit. Again, just saying that Player 2 has won.

Maybe I messed something up that you told me to fix.

#include <cstdlib>
#include <iostream>

using namespace std;

class Game
{
	private:
		char board[3][3];

		bool rowWin()
		{
			int count = 0;
			for(int i = 0; i < 3; i++)
			{
				if((board[0][i] == board[1][i] && board[0][i] == board[2][i]) || (board[i][0] == board[i][1] && board[i][0] == board[i][2])) //condition for 3 in a row
				{
					if(board[i][0] == '+' || board[0][i] == '+') cout << "Player 1 has won.";
					else cout << "Player 2 has won.";
					return true;
				}
				else return false;
			}
		}

		bool diagWin()
		{
			if((board[0][0] == board[1][1] && board[0][0] == board[2][2]) || (board[0][2] == board[1][1] && board[0][2] == board[2][0]))
			{
				if(board[1][1] == '+') cout << "Player 1 has won.";
				else cout << "Player 2 has won.";
				return true;
			}
			else return false;
		}

	public:
		Game()
		{
			for(int i = 0; i < 3; i++)
				for(int j = 0; j < 3; j++)
					board[i][j] = '*';
		}
		
		void setSpot(int player, int i, int j)
		{
			if(player == 1) board[i][j] = '+';
			else board[i][j] = '0';
		}

		void printBoard()
		{
			cout << "-------";
			for(int i = 0; i < 3; i++)
			{
				cout << "\n|";
				for(int j = 0; j < 3; j++)
				{
					cout << board[i][j] << "|";
				}
			}
			cout << "\n-------";
		}

		bool hasWon()
		{
			return rowWin() || diagWin();
		}

		void doTurn()
		{
			int m, n;
			for(int i = 0; i < 2; i++)
			{
				printBoard();
				do
				{
					cout << "\n\nPlayer " << i+1 << " enter row and column of your move. (1-3):   ";
					cin >> m >> n;
					setSpot(i+1, m-1, n-1);
				} while(m <= 0 || m > 3 || n <= 0 || n > 3);
			}
			
		}
};

int main()
{
	Game tic;

	cout << "Welcome to the Tic-Tac-Toe game!\n";
	system("PAUSE");
	do
	{
		system("CLS");
		tic.doTurn();
		cout << "\n";
		system("PAUSE");
	} while(!tic.hasWon());

	return 0;
}


Was This Post Helpful? 0
  • +
  • -

#7 Hezekiah  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 207
  • View blog
  • Posts: 552
  • Joined: 12-July 09

Re: TicTacToe Game and Private Member Functions

Posted 27 February 2012 - 08:50 AM

First, the return false; has to be moved to after the loop.

if(board[i][0] == '+' || board[0][i] == '+')

Here you have the same problem you had with the diagWin() function. If board[i][0] is part of the winning row, and it contains '0', but board[0][i] contains '+', the program will say player 1 has won, even though board[0][i] is not part of the winning row.

If the winning row is a column, you should test the value of board[i][0-2], but if it is a row, you should test board[0-2][i]. If you think about it, there is a cell which always falls in both these ranges: board[i][i].

The reason why it always says player 2 has won, is not because there is a row of '0's, but because there is a row of '*'s. You have to implement a test for that.
Was This Post Helpful? 0
  • +
  • -

#8 zim1985  Icon User is offline

  • Grand Inquisitor
  • member icon

Reputation: 74
  • View blog
  • Posts: 568
  • Joined: 19-February 10

Re: TicTacToe Game and Private Member Functions

Posted 27 February 2012 - 09:32 AM

View PostHezekiah, on 27 February 2012 - 07:50 AM, said:

First, the return false; has to be moved to after the loop.

if(board[i][0] == '+' || board[0][i] == '+')

Here you have the same problem you had with the diagWin() function. If board[i][0] is part of the winning row, and it contains '0', but board[0][i] contains '+', the program will say player 1 has won, even though board[0][i] is not part of the winning row.

If the winning row is a column, you should test the value of board[i][0-2], but if it is a row, you should test board[0-2][i]. If you think about it, there is a cell which always falls in both these ranges: board[i][i].

The reason why it always says player 2 has won, is not because there is a row of '0's, but because there is a row of '*'s. You have to implement a test for that.


I get it. All I had to do was make sure that the tests only passed if the rows were + or 0. How I had it before made it so any row that was all equal would pass.

Thank you so much for your help. You are a genius.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1