tic tac toe game

Hi guys,

I've been programming in c++ for just a couple of days (I've had some brief exposure to c beforehand but we never really got on) and I'm trying to get to grips with the whole Object Oriented philosophy. I've read a bunch of material on the web & watched several hours of tutorial videos and I think I've got the basic idea.

Here is my first console application game, the prototypical tic tac toe:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include "stdafx.h"
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>

using namespace std;

//Function decleration
void clearboard( char a[] );		
void redraw( char a[] );			
bool checkwin( char a[] );
void playerturn( char a[] );
void cputurn( char a[] );
bool retry();

//MAIN
int main()
{
	char board[9];		//game board,  rows: [0]-[2], [3]-[5], [6]-[8] 
	string player;		//records player (user or cpu)
	unsigned short int turns=0;		//tracks number of turns
	bool gameover = false;			// play again flag
	
	do
	{
		// initialise gameboard
		clearboard(board);
		redraw(board);

		do
		{
			
			turns++;
			
			//Player's move
			player = "Player";
			playerturn(board);
			cout << "  Current Player: " << player << endl;

			if(checkwin(board))
			{
				cout << "         \n\n$$$$$  " << player << " Wins in " << turns  << " turns!!  $$$$$\n\n";
				break;
			}
			
			//CPU move
			player = "Computer";
			cputurn(board);
			cout << "\n          Current Player: " << player << endl;

			if(checkwin(board))
			{
				cout << "          \n\n$$$$$  " << player << " Wins in " << turns << " turns!!  $$$$$\n\n";
				break;
			}


			//check for a tie
			if(turns==9)
			{
				cout << "          \n\nIt's a tie! \n\n";
				break;
			}
		
		}while(turns<=9);

	gameover = retry(); //play again?

	}while(!gameover);
}


// Reset the board[] at the beginning of a round
void clearboard(char a[])
{
	a[0] = '1';
	a[1] = '2';
	a[2] = '3';
	a[3] = '4';
	a[4] = '5';
	a[5] = '6';
	a[6] = '7';
	a[7] = '8';
	a[8] = '9';
}



//redraw the board[] after a move has been made
void redraw( char a[] )
{
	unsigned short int i=0, j=0, k=0;
	cout << "                 ***************************\n";
	cout << "                 *****   TIC TAC TOE   *****\n";
	cout << "                 ***************************\n\n";
	cout << "     Rules: you are the 'X', computer will play as 'O'\n     Try to make 3 in a row!\n\n"; 

	
	for(i=0;i<3;i++)
	{
		cout << "                    *************\n";
		cout << "                    *   *   *   *\n";
		cout << "                    *";
		for(j=0;j<3;j++)
		{
			cout << " " << a[k] << " *";
			k++;
		}
		cout << "\n                    *   *   *   *\n";

	}
	cout << "                    *************";
}


//check to see if anyone won, the winning player is tracked by string: player
bool checkwin( char a[] )
{
	//check horizontal combinations
	if(a[0]==a[1] && a[1]==a[2]) return true;
	else if(a[3]==a[4] && a[4]==a[5]) return true;
	else if(a[6]==a[7] && a[7]==a[8]) return true;

	//check vertical combinations
	else if(a[0]==a[3] && a[3]==a[6]) return true;
	else if(a[1]==a[4] && a[4]==a[7]) return true;
	else if(a[2]==a[5] && a[5]==a[8]) return true;

	//check diagonal combinations
	else if(a[0]==a[4] && a[4]==a[8]) return true;
	else if(a[2]==a[4] && a[4]==a[6]) return true;
	else return false;

}

void playerturn( char a[] )			//Player's turn: asks where you want to place your 'X' on the board[], on a free space only (1-9)
{
	unsigned short int move;
	do
	{
		cout << "               \n\nChoose your move: (1-9) \n";
		cin >> move;
		move--;
		if(cin.fail() || move>8)
		{
			cin.clear();
			cin.ignore();
			cout << "     Oops, i didn't understand that, please enter a number 1-9.. \n";
			continue;
		}

		if(a[move]=='O' || a[move]=='X')
		{
			cout << "     That space is already taken! try again.. \n";
			continue;
		}

		a[move] = 'X';
		redraw(a);
		break;
	}while(true);
}


void cputurn( char a[] )				//CPU turn, randomly places a 'O' in an empty space by generating random numbers 0 <= r <= 8
{
	srand( (unsigned)time(NULL));
	int r;
	do
	{
		r = rand()%9;
		if(a[r]=='O' || a[r]=='X') continue;
		else
		{
			a[r]='O';
			redraw(a);
			break;
		}
	}while(true);
}

bool retry()							// Play Again?
{
	char input;

	do
	{
		cout << "Play again? y/n:  ";
		cin >> input;
		if(cin.fail() || (input!='y' && input!='n'))
		{
			cin.clear();
			cin.ignore();
			cout << "not understood.. please type y or n: ";
			cout << endl;
			continue;
		}
		
		if(input=='y')
		{
			return false;
			break;
		}
		if(input=='n')
		{
			cout << "Thank you for playing, Goodbye! \n";
			return true;
			break;
			
		}
	}while(true);
}


I am aware there are bad habits to get into when coding, If anyone could point out any bad things that I've done or perhaps some short cuts using different commands / expressions etc. (for example my checkwin() function is not very elegant) I'd be very grateful.

Thanks.
It's awesome that you're really applying yourself and wanting to sharpen your skills. Great qualities of a student. Now, your program. Just right off the bat I'd suggest that when you create your console application that you select "Empty Project" in the wizard that pops up when you make a new project, I'm assuming you're using Visual Studios. That way you won't have to deal with the junk files and precompiled includes (stdafx.h)

Also be sure to keep in good practice and have your main function returning control to the OS.

1
2
3
4
5
6
int main()
{
    //program
   
    return 0;
}


You mentioned that you're trying to learn how to OOP. I'd say that you have a lot of opportunities to do that here in this program. But, I don't really see you using any OOP concepts.

If you'd like I can elaborate a little bit more with some examples.
Last edited on
Yeah didn't even notice the missing, return 0, I'll fix that up.

as far as I was aware, I thought the goal of OOP was to seperate out as many functions from main() as possible? Is it more specific than that (i.e. declarations in a .h header file and the definitions in a seperate source file) or am I oversimplifying / missing the point entirely?

Thanks
You are right that creating functions is a part of OOP. But, the true meat and potatoes of OOP is creating classes and encapsulating your data to create layers of abstraction.

Think about the game board as being it's own class and it's only aware of which spots are occupied. Think of the game play being in a class. The players themselves can be a calss and they would be aware of moves made, times won heck even player names. You could also make an AI class that is in charge of being "clever" and how many times it has won.

You basically want to hash out the design of the program and create "Objects" that carry unique traits that define them. Ideally your main game loop would look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{
	TicTacToe game;
	
	while(game.IsPlaying())
	{
		game.ClearBoard();

		game.PlayGame();

		game.Draw();
	}

	return 0;
}
I think I understand, I'll have a read up on classes and see if i can redesign the whole thing using only interacting objects. Thanks so much for your help.
No problem!

I wanted to let you know that I will use a similar program like this one and change it to use the principles that I talked about in a you tube video - it inspired me =P

youtube.com/nandez52

I'm just starting out with making tutorials and how to's for C++ and game development.

Have a good day.
Topic archived. No new replies allowed.