Tic Tac Toe using 2D array

  • (2 Pages)
  • +
  • 1
  • 2

18 Replies - 11466 Views - Last Post: 27 February 2011 - 02:36 AM Rate Topic: -----

#1 goldfish  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 25-February 11

Tic Tac Toe using 2D array

Posted 25 February 2011 - 10:47 PM

I am very new to programming. I have been working on this project for days and completely stuck.
I was able to display 3x3 gameboard with *, assign player 1-X palyer 2-O taking turns to place their marks. I don't know how to use bool to end game with one of the player WIN or TIE.
Please point me to the right direction.

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

void showBoard(void);
void playerInput(int p);
void checkWinner();
void nextPlayer(int);


int board[3][3]={{0,0,0},{0,0,0},{0,0,0}};

int _tmain(int argc, _TCHAR* argv[])
{
	int r;
	int c;
	int player;
	int winner;
	int turns;
 	cout << "******* Tic Tac Toe Game *******" << endl;

	showBoard();
	nextPlayer(1);
	return 0;
}

void showBoard(void)
{
	int r;
	int c;

	cout << endl << endl;
	cout <<"\tColumns\n";
	cout <<"\t123\n";

	for(r=0; r<=2; r++)
	{	
		cout <<"Row " << (r+1) << ": ";
		for(c=0; c<=2; c++)
		{
			if( board [r][c]==0)
				cout << "* ";
			else if (board [r][c]==1)
				cout << "X ";
			else 
				cout << "O ";
		}
		cout << endl;
	}
}

void playerInput(int p)
{
	int row;
	int col;
	
	if(p==1)
		cout <<"\nPlayer 1, place X mark in the game board\n\n";
	else 
		cout <<"\nPlayer 2, place O mark in the game board\n\n";

	cout <<"Enter Row ";
	cin >> row;
	cout <<"Enter Column ";
	cin >> col;

	if(p==1)
		board[--row][--col]=1;
	if(p==2)
		board[--row][--col]=2;
}
	
void checkWinner()
{
	int winner;
	for (int i=0; i<=2; i++)
	{
		if(board[i][0]==board[i][1] && board[i][1]==board[i][2] && board[i][0]!=0)
		{
			winner=board[i][0];
		}
	}
	
	for(int i=0; i<=2; i++)
	{
		if(board[0][i]==board[1][i] && board[1][i]==board[2][i] && board[0][i]!=0)
		{
			winner=board[0][i];
		}
	}
	
	if(board[0][0]=board[1][1] && board[1][1]==board[2][2] && board[0][0]!=0)
	{
		winner=board[0][0];
	}
	
	if(board[0][2]=board[1][1] && board[1][1]==board[2][0] && board [0][2]!=0)
	{
		winner=board[0][2];
	}

	if(board[0][0]==board[0][1] && board[0][1]==board[0][2]&& board[0][2]==board[0][1]&& board[1][0]==board [1][1]&& board[1][1]==board [1][2]&& board[1][2]==board[2][0]&&board[2][0]==board [2][1]&& board[2][1]==board [2][2] && board [0][0]!=0)
	{
		winner=0;
	}
	
}

void nextPlayer(int player)
{

	playerInput(player);
	showBoard();

	if(player==1)
	player=2;
	else
	player=1;
	nextPlayer(player);

}


This post has been edited by Martyn.Rae: 25 February 2011 - 10:49 PM
Reason for edit:: Added code tags


Is This A Good Question/Topic? 0
  • +

Replies To: Tic Tac Toe using 2D array

#2 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Re: Tic Tac Toe using 2D array

Posted 25 February 2011 - 11:02 PM

The logic in the function checkWinner is wrong. In order to determine the winner in the game, all cells in the game grid must belong to one player. So, we look at board[0][0] as the first thing and take note of the player. If board[0][0] is zero, then the game is not over and you can leave the routine.

Now, once we have established the owner of the first cell on the board, we need to check every cell on the board to ensure they are all owned by that player. It does not matter that we retest board[0][0] as we know that the player owns it. Providing all cells are owned by a player then that player has won. If you come across a cell that has not been used (*), then you can simply leave the routine as the game is not over. If all cells are used, but you have noted that the player who owns board[0][0] does not own all cells, then it is a tie.

I hope this helps you.

This post has been edited by Martyn.Rae: 25 February 2011 - 11:12 PM

Was This Post Helpful? 1
  • +
  • -

#3 goldfish  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 25-February 11

Re: Tic Tac Toe using 2D array

Posted 25 February 2011 - 11:25 PM

Ah,,,
I think I'm slowly getting it. So, do I need to have a counter <9 to determin if it's a tie?

I am sorry, I know I'm asking a really 'sorry' question but I haven't finished the first C++ book yet and am totally new to programming.
Was This Post Helpful? 0
  • +
  • -

#4 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Re: Tic Tac Toe using 2D array

Posted 25 February 2011 - 11:35 PM

You could do it that way, yes! Count the number of cells owned by player 1 and player 2, then if player 1 has nine cells they have won, if player2 has nine cells then they have won and finally if the sum of the cells that player 1 and player 2 have is nine, then its a tie else the game is not over.
Was This Post Helpful? 1
  • +
  • -

#5 goldfish  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 25-February 11

Re: Tic Tac Toe using 2D array

Posted 25 February 2011 - 11:49 PM

So, if I were to do that, which function do I need to add that to? or do I need to create another function to determine Tie?
I understand I'll have to work on logic on checkWinner() before I do anything with it.
Was This Post Helpful? 0
  • +
  • -

#6 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Tic Tac Toe using 2D array

Posted 26 February 2011 - 12:30 AM

View PostMartyn.Rae, on 26 February 2011 - 01:02 AM, said:

In order to determine the winner in the game, all cells in the game grid must belong to one player. So, we look at board[0][0] as the first thing and take note of the player. If board[0][0] is zero, then the game is not over and you can leave the routine.


I'm very puzzled by this discussion. In TicTacToe, the winner is the player who owns all 3 cells in a particular row, column or diagonal, and this can occur even if less than 9 moves have been made.

To check for a winner I would test each row something like this (looping through the 3 rows):
if( board[row][0] == x && board[row][1] == x && board[row][2] == x ) player x wins
and do a similar test for the 3 columns and the 2 diagonals.
Was This Post Helpful? 1
  • +
  • -

#7 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Re: Tic Tac Toe using 2D array

Posted 26 February 2011 - 01:11 AM

Hmmm, you are absolutely correct. I appear to have got reversi and tic-tac-toe somewhat confused.
Was This Post Helpful? 0
  • +
  • -

#8 janotte  Icon User is offline

  • code > sword
  • member icon

Reputation: 990
  • View blog
  • Posts: 5,141
  • Joined: 28-September 06

Re: Tic Tac Toe using 2D array

Posted 26 February 2011 - 02:40 AM

So let's start again.
You have been lead into a completely wrong direction because the program requirements were misunderstood. That's a valuable lesson all on it's own. You will find a large amount of resources get wasted in most programming operations due to exactly that problem. Whenever you are asking for help it is very very important that the person you are asking for help from understands the requirements you are working to. Although it seems to take a long time it is often worth writing out your requirements fully. Often simply doing that will help you immediately see the answer yourself. If it doesn't then it will help the person you ask for help to help you effectively.

So let's state the requirements for a checkForWinner() function.
IF
one player holds all the squares any row
OR
one player holds all the squares any column
OR
one player holds all the squares in either of the two 3 square diagonals
THEN
that player has won and the game ends.

With those requirements stated openly we have not only a framework to build against but also a set of individual tests that we can do as individual bits of code. We might break each test out as it's own function. If not that we at least have some high level comments to add to our code to help us write the code in a logical and disciplined way and will also help others reading our code to know what we are trying to do where.

So let's work on our first test "one player holds all the squares any row"
Let's sketch out one possible algorithm. There are many ways to do this but here is one.
We need to check 3 rows, 0->2.
Each row starts at [x][0] (where 'x' represents the row.
Starting at the first row (0) and moving to the last row (2) go though these tests.
..If [x][0] is not held by any player then this row does not contain a winner, check next row or end if on last row.
..Otherwise row may contain a winner so keep working
....If [x][1] is NOT held by the same player as [x][0] (including if [x][1] is blank) then this row does not contain a winner, check next row or end if on last row.
....Otherwise row may contain a winner so keep working
.......If [x][2] is NOT held by the same player as [x][1] then this row does not contain a winner, check next row or end if on last row.
......Otherwise the player who holds [x][0] has won, end checking and report the result to calling function.

Go through each of the other two tests and write out an algorithm for each of the tests.
Once you have an algorithm for each test then go write code.
Write the code for each test one by one. Get one test working correctly before moving onto the next test.

Give all that a try and get back to us if you have problems with any step.
Was This Post Helpful? 1
  • +
  • -

#9 goldfish  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 25-February 11

Re: Tic Tac Toe using 2D array

Posted 26 February 2011 - 09:29 AM

Thank you so much helpful fellas!
I followed the instruction(I think) and made small tests in checkWinner()function.
Started with Player 1: row1 row2, row3, then column1, column2, column3, then diagonal 2 ways.
After that, Player 2: row1, row2, row3, column1, column2, column3, diagonals x2.
Each test announced the winner with cout << statement.


void checkWinner()
{
	// Check Rows for Player 1
	if( (board[0][0]=1) && (board [0][0] == board [0][1]) && (board [0][1] == board [2][2]))
	 cout << "X won!";
	else if( (board[1][0]=1) && (board [1][0] == board [1][1])&& (board [1][1] == board [1][2]))
	cout << "X won!";
	 else if( (board[2][0]=1) && (board [2][0] == board [2][1])&& (board [2][1] == board[2][2]))
		 cout << "X won!";

	// Check Columns for Player 1
	 else if ( (board[0][0]=1)&& (board[0][0] == board [1][0] )&& (board [1][0] == board [2][0]))
		 cout << "X won!  "<< endl;
	 else if ( (board [0][1] == 1 )&& (board[0][1] == board [1][1] )&& (board [1][1] == board [2][1]))
		 cout << "X won!  "<< endl;
	 else if ((board [0][2] == 1 )&& (board [0][2] == board [1][2] ) && (board [1][2] == board [2][2]))
		  cout << "X won!  "<< endl;

	// Check diagonal for Player 1
	 else if( (board[0][0] == 1 ) && (board [0][0] == board[1][1] ) && (board [1][1] == board[2][2] ))
		 cout << "X won!  "<< endl;
	 else   ((board[2][0] == 1 )&& (board [2][0] == board[1][1]) && (board [1][1] == board[0][2]))
		 cout << "X won!  "<< endl;

	 //Check Rows for Player 2
	 { 	 
	 if( (board[0][0]=2) && (board [0][0] == board [0][1]) && (board [0][1] == board [2][2]))
		cout << "O won!";
	 else if( (board[1][0]=2) && (board [1][0] == board [1][1])&& (board [1][1] == board [1][2]))
		cout << "O won!";
	 else if( (board[2][0]=2) && (board [2][0] == board [2][1])&& (board [2][1] == board[2][2]))
		 cout << "O won!";

	// Check Columns for Player 2
	 else if ( (board[0][0]=2)&& (board[0][0] == board [1][0] )&& (board [1][0] == board [2][0]))
		 cout << "O won!  "<< endl;
	 else if ( (board [0][1] == 2 )&& (board[0][1] == board [1][1] )&& (board [1][1] == board [2][1]))
		 cout << "O won!  "<< endl;
	 else if ((board [0][2] == 2 )&& (board [0][2] == board [1][2] ) && (board [1][2] == board [2][2]))
		  cout << "O won!  "<< endl;

	// Check diagonal for Player 2
	 else if( (board[0][0] == 2 ) && (board [0][0] == board[1][1] ) && (board [1][1] == board[2][2] ))
		 cout << "O won!  "<< endl;
	 else  ((board[2][0] == 2 )&& (board [2][0] == board[1][1]) && (board [1][1] == board[0][2]))
		 cout << "O won!  "<< endl;
	 }
}



Is this what I needed to do? Now, tell me how to limit players moves <=9. or do I need to do another function like gameOver() with bool status?---go ahead & laugh at me. I'm ignorant!

Another thing I'm not sure about is where can I call this checkWinner() function from.
Can I do that from nextPlayer() or playerInput() or main()?? It seems like I need to check it after each player but up to 3rd move there won't be a winner anyway... I am confused.

I also have a problem with nextPlayer() function. I know I need to let player take turns but I realize this loop looks like an endless one. How can I end it when all the spaces are taken?

This post has been edited by Martyn.Rae: 26 February 2011 - 01:02 PM
Reason for edit:: Fixed code tags

Was This Post Helpful? 0
  • +
  • -

#10 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Tic Tac Toe using 2D array

Posted 26 February 2011 - 10:47 AM

It might be correct, but it's so hard to read (& unnecessarily complicated) that I don't have the patience to study every line. You know how to write loops, so why not use them? Also, you can pass the current player number to the function as a parameter & thereby simplify the logic. Finally, the function should report back whether there is a winner or not in order to signal the end of the game, so it's return type should be bool.

For example, this code only checks the rows. You can write something similar that also checks the columns and the 2 diagonals.

bool checkWinner( int playerNumber ) {
    bool winner = false;
    int row = 0;
    while( winner == false && row < 3 ) {
        if( board[row][0] == playerNumber && board[row][1] == playerNumber && board[row][2] == playerNumber ) {
            winner = true;
        }
        row++;
    }
    return winner;
}



Also, you made your nextPlayer function recursive. (A recursive function is one that calls itself.) In general you shouldn't use recursion without a good reason, and at your current level of programming you shouldn't be using it at all. Instead, the calls to playerInput should be in a loop which keeps repeating until there is a winner, using the results returned by checkWinner to determine IF there is a winner.

This post has been edited by r.stiltskin: 26 February 2011 - 10:49 AM

Was This Post Helpful? 1
  • +
  • -

#11 goldfish  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 25-February 11

Re: Tic Tac Toe using 2D array

Posted 26 February 2011 - 12:52 PM

Thank you sir,

Obviously, I don't know how to post or write code and I totally understand no one has patientce to check this line by line :stupid:

I'm going to try to use loop for checkWinnern function to see if I can do that.
I had no idea about "recursive". I think that is coming towards the end of the book I got almost half way in. I was looking at a code someone has used to switch players and used that to let player take turns.
So, I need make this a loop also,,,

Im going to work on it this afternoon.
Thank you so much for your help!
Was This Post Helpful? 0
  • +
  • -

#12 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Tic Tac Toe using 2D array

Posted 26 February 2011 - 01:01 PM

To post code:
when you are looking at the window, look at the widgets immediately above the window where you type. One of them says "CODE". Click it, and it will type the two code tags for you. Then just paste your code in between them.
Was This Post Helpful? 0
  • +
  • -

#13 21q  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 18
  • Joined: 26-February 11

Re: Tic Tac Toe using 2D array

Posted 26 February 2011 - 03:17 PM

If you use a loop for the row and column checks you could turn 6 lines of code into two.

Taking a piece from my tictactoe game
for(int i = 0; i<3;i++){
			if( (f[i][0] == f[i][1]) && f[i][2] == f[i][0] && f[i][0] != ' '){
			cout<<"You Win!"<<endl<<"\n"; 
			return 0;}
			}
		
		for(int i = 0; i<3;i++){
			if( (f[0][i] == f[1][i]) && f[2][i] == f[0][i] && f[0][i] != ' '){
			cout<<"You Win!"<<endl<<"\n"; 
			return 0;}
			}		


Now since you care to show if X or O won, I'd just do this, but maybe there is a simpler way. I'm rather new to coding myself. i tried to cater it to how you're coding as well this time.

               for(int i = 0; i<3;i++){
			if( (f[i][0] == f[i][1]) && f[i][2] == f[i][0] && f[i][0] != ' '){
                                  if(player==1){			
                                          cout<<"X Wins!"<<endl<<"\n";} 
                                  else {			
                                          cout<<"O Wins!"<<endl<<"\n";} 
			}
                }
		
		for(int i = 0; i<3;i++){
			if( (f[0][i] == f[1][i]) && f[2][i] == f[0][i] && f[0][i] != ' '){
			          if(player==1){			
                                          cout<<"X Wins!"<<endl<<"\n";} 
                                  else {			
                                          cout<<"O Wins!"<<endl<<"\n";} 
			}
                }	


Was This Post Helpful? 0
  • +
  • -

#14 janotte  Icon User is offline

  • code > sword
  • member icon

Reputation: 990
  • View blog
  • Posts: 5,141
  • Joined: 28-September 06

Re: Tic Tac Toe using 2D array

Posted 26 February 2011 - 04:21 PM

Since we are doing code here.

Here's an enhancement that not only returns whether there is a winner but also returns WHO won.

I am not saying this is superior as an algorithm (just showing that there are many valid ways to do the same thing) but see how adding some comments to your code can make even complex ideas far simpler to understand.

Also see how using meaningful variable names can help. Why use 'i' when 'row' is so much clearer?

Also see how building a little main() that does nothing other than test your function is helpful in narrowing down the scope of things you have to deal with at the same time and allows you to easily test all the permutations that the function may have to deal with without having to run a lot of other code that you are not interested in at this moment in time.

Once you are fully confident that your function works correctly (known as 'passing unit tests') you can put it into your 'real' program with some confidence.

I just banged this out quickly so it may have bugs.
Try putting different values into the grid, recompile and test.
Can you find a grid layout that doesn't work as it should?

#include <iostream>

// Function to check for winners
// TODO - current code only handles rows - needs to be
//        expanded to handle columns and diagonals.
int checkForWinner(int gridToCheck[][3], int numberOfRows){
	
	int winningPlayer = 0;
	
	// check rows for a winner
	// assumption - grid layout is [row][col] and has 3 cols
	// assumption = empty squares in the grid hold zero
	for(int row=0; row<numberOfRows; row++){
		// check if 1st square in this row has been played
		if(gridToCheck[row][0]){
			// 1st square has been played - keep checking
			// check if 1st square equals 2nd square
			if(gridToCheck[row][0] == gridToCheck[row][1]){
				// first square equals 2nd square - keep checking
				// check if 2nd square equals 3rd square
				if(gridToCheck[row][1] == gridToCheck[row][2]){
					// 2nd square equals 3rd square - winner found
					winningPlayer = gridToCheck[row][0];
					return winningPlayer;
				}					
			}
		}
	}
	
	return winningPlayer;
}


// test driver for checkForWinner().
int main()
{
	const int GRID_SIZE = 3;
	int gameGrid[GRID_SIZE][GRID_SIZE];
	
	// test values entered manually
	// assumption - grid layout is [row][col]
	// top row
	gameGrid[0][0] = 0;
	gameGrid[0][1] = 0;
	gameGrid[0][2] = 0;
	// middle row
	gameGrid[1][0] = 0;
	gameGrid[1][1] = 0;
	gameGrid[1][2] = 0;
	// bottom row
	gameGrid[2][0] = 0;
	gameGrid[2][1] = 0;
	gameGrid[2][2] = 0;
	
	
	int winningPlayer = 0;
	winningPlayer = checkForWinner(gameGrid, GRID_SIZE);
	
	if(winningPlayer){
		std::cout << "We have a winner!" << std::endl;
		std::cout << "Winner is: " << winningPlayer << std::endl;
	}else{
		std::cout << "No winner yet." << std::endl;
	}

	return 0;
}


Was This Post Helpful? 1
  • +
  • -

#15 goldfish  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 25-February 11

Re: Tic Tac Toe using 2D array

Posted 26 February 2011 - 06:25 PM

Please, explain to me like you would to a 4-year-old( maybe you were much smarter 4-year-old than I was but general 4-year-old). Your checkForWinner()function will determine IF there's a winner and WHO is the winner, right? In order to make this fully work, I need to expand it to check columns and diagonals also? Could I use a nested if for columns and diagonals?

Ah... why is it int numberOfRows instead of int 3? I remember reading passing 2D array to function and it showed like
void showArray(int array[][COLS], int rows) that I did not fully understand.
can numberOfRows be omitted and just use int there or is it needed?

I understand this function returns value winningPlayer. Is it best to call this function from main() or another function like playerInput?

I have been working on this Thursday and Friday by myself with almost no progress and my desperation got me registered on this site. I was really intimidated and afraid to let people know how little I know but you guys have been so kind and helpful. Thank you so much.
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2