• Forum
  • Lounge
  • Project Idea: Tic-Tac-Toe (Noughts and C

 
Project Idea: Tic-Tac-Toe (Noughts and Crosses, …)

closed account (z05DSL3A)
Level:
Beginner

Introduction
Tic-tac-toe, also called noughts and crosses, hugs and kisses, and many other names, is a pencil-and-paper game for two players, O and X, who take turns marking the spaces in a 3×3 grid. The player who succeeds in placing three respective marks in a horizontal, vertical or diagonal row wins the game. This game is won by the first player, X:

│ │ X O │ │ X O │ │ X O │ │ X O │ │ X O │ │ X O │ │ X
───┼───┼─── ───┼───┼─── ───┼───┼─── ───┼───┼─── ───┼───┼─── ───┼───┼─── ───┼───┼───
│ │ │ │ │ │ │ O │ │ O │ │ O │ O │ O │ O
───┼───┼─── ───┼───┼─── ───┼───┼─── ───┼───┼─── ───┼───┼─── ───┼───┼─── ───┼───┼───
│ │ │ │ X │ │ X │ │ X │ │ X X │ │ X X │ X │ X


Your ‘Assignment’ Stage 1:
Write a simple program that will allow two ‘human’ players to play Tic-tac-toe on the screen, there is no need to determine Win, lose, or draw yet. Just make sure that the players can not put marks in places that already have marks and finish the ‘playing’ sequence when all spaces are taken.

Stage 2:
Modify your program from stage 1 to allow your program to determine Win, lose, or draw states.

Stage 3:
Modify your program from stage 2, to have the option of playing against a ‘computer’ opponent.





______________________________________
Motivation came from a posting by arrrgh. Introduction from Wikipedia
Last edited on
So, we have to make a function Tic-Tac-Toe, with a variable number of arguments, first one being Noughts-and-Crosses, no? ;D
Grey,

I have been trying to do this for a while, but I think what I was doing wrong, is I was trying to do step 2 and 3 before I even did step one. I will try doing it the right way!

Also how would you solve this problem. I am not really interested in the source code, but rather the methodologies behind developing software.
Last edited on
There are a number of approaches to problem solving for a problem like this.
My take would be to look at the problem and see how to break it down into simpler problems - so here you might decide the porblems are
1) Display the Grid
2) Display the 'pieces' on the grid
3) Determine if more pieces can be placed
4) Enter position for next piece.
For stages 2 point (3) can be extended to check for Win, Lose or Draw, and for stage 3 you can develop a (4a) wich is an computer placement.
Having done a first take on simplifying the problem, you then think about relationships between the stages - common data, functions, classes, etc.
This can then be repeated on the subtasks until you reach a point where you have something you are happy you have understood the problem and have simplified the subtasks to a point where you can code them without risking any additional interdependancies.
For a larger project, where multiple developers are involved, gettign the design to a point where you know the interdependancies before coding starts is important, as that is the point where you can portion the work out to different people, safe in the knowledge that the links between the code will be OK.
Last edited on
Faldrax,

Thanks for the advice. I was going about the total opposite way, I will try this out and see what I can come up with!

So this is what I have come up with so far, I would love some comments on what could make it better/run smoother.

There are some bugs I have found some bugs, but nothing major yet. Let me know what you think!

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
#include <iostream>
#include <string.h>
#include <sstream>
#include <ctype.h>

using namespace std;
class game{

	private:
		int place,gameOn,turn,winner;
		char board[9];
		unsigned short int win[9];
		string posZero,posOne,posTwo,posThree, posFour,posFive, posSix,posSeven, posEight;	
	public:		
		game()
		{
			turn = 0;
			for(int i = 0; i < 9; i++)
			{
				board[i] = '\0';
				win[i] = '\0';
			}	
			cout << board[1];
		}
		int getWinner()
		{ return winner; }
		void setTurn()
		{ turn = (turn == 0) ? 1 : 0; }
		void setCords()
		{
			int x = 0;
			cout << "\n\nEnter place number: ";
			cin >> x;
			cout << "\n";
			place = x - 1;
		}
		int setGrid()
		{
			if(board[place] == 'O' || board[place] == 'X')
			{
				cout << "\nThat place is already taken!" << endl;
				draw();
				return 0;
			}	
			else if(win[place] == 1 || win[place] == 2)
			{
				cout << "\nWin already taken\n";
				draw();
				return 0;
			}
			else
			{
				if(turn == 0)
				{
					board[place] = 'X';
					win[place] = 1;
					return 1;
				}
				else
				{
					board[place] = 'O';
					win[place] = 2;
					return 1;
				} } }
		
		bool play()
		{
			for(int x = 1; x < 3; x++)
			{
				if(win[0] == x)
				{
					if(win[1] == x) { if(win[2] == x) { winner = x; return true; } }
					if(win[4] == x) { if(win[8] == x) { winner = x; return true; } }
					if(win[3] == x) { if(win[6] == x) { winner = x; return true; } }
				}
				if(win[1] == x)
				{ if(win[4] == x) { if(win[7] == x) { winner = x; return true; } } }
				if(win[2] == x)
				{
					if(win[5] == x) { if(win[8] == x) { winner = x; return true; } }
					if(win[4] == x) { if(win[6] == x) { winner = x; return true; } }
				}
				if(win[3] == x)
				{ if(win[4] == x) { if(win[5] == x) { winner = x; return true; } } }
				if(win[6] == x)
				{ if(win[7] == x) { if(win[8] == x) { winner = x; return true; } } }
			}	
			return false;	
		}
		
		void draw()
		{ cout << endl << posZero <<posOne << posTwo << posThree << posFour << posFive << posSix << posSeven << posEight; }
		void drawChange()
		{
			for(int i = 0; i < 9; i++)
			{	
				switch(i)
				{
					case 0:
						if(board[0] == 'X')
						{ posZero = "_X_|"; }
						else if(board[0] == 'O')
						{ posZero = "_O_|"; }
						else
						{ posZero = "___|"; }
						break;
					case 1:	
						if(board[1] == 'X')
						{ posOne = "_X_|"; }
						else if(board[1] == 'O')
						{ posOne = "_O_|"; }
						else
						{ posOne = "___|"; }
						break;
					case 2:
						if(board[2] == 'X')
						{ posTwo = "_X_"; }
						else if(board[2] == 'O')
						{ posTwo = "_O_"; }
						else
						{ posTwo = "___"; }
						break;
					case 3:
						if(board[3] == 'X')
						{ posThree = "\n_X_|"; }
						else if(board[3] == 'O')
						{ posThree = "\n_O_|"; }
						else
						{ posThree = "\n___|"; }
						break;
					case 4:	
						if(board[4] == 'X')
						{ posFour = "_X_|"; }
						else if(board[4] == 'O')
						{ posFour = "_O_|"; }
						else
						{ posFour = "___|"; }
						break;
					case 5:
						if(board[5] == 'X')
						{ posFive = "_X_"; }
						else if(board[5] == 'O')
						{ posFive = "_O_"; }
						else
						{ posFive = "___"; }
						break;
					case 6:
						if(board[6] == 'X')
						{ posSix = "\n X |"; }
						else if(board[6] == 'O')
						{ posSix = "\n O |"; }
						else
						{ posSix = "\n   |"; }
						break;
					case 7:	
						if(board[7] == 'X')
						{ posSeven = " X |"; }
						else if(board[7] == 'O')
						{ posSeven = " O |"; }
						else
						{ posSeven = "   |"; }
						break;
					case 8:
						if(board[8] == 'X')
						{ posEight = " X "; }
						else if(board[8] == 'O')
						{ posEight = " O "; }
						else
						{ posEight = "   "; }
						break;
					}					
				}
				cout << posZero <<posOne << posTwo << posThree << posFour << posFive << posSix << posSeven << posEight;  }	
};
int main()
{	for(;;){	
		game TTT;
		while(!TTT.play())
		{
			TTT.drawChange();
			int r = 0;
			do{ 
			TTT.setCords();
			r = TTT.setGrid();
			}while(r < 1);
			TTT.setTurn();	
		}
		TTT.drawChange();
		
		if(TTT.getWinner() == 1)
		{ cout << "\nThe Winner is X.  Congrats" << endl; }
		if(TTT.getWinner() == 2)
		{ cout << "\nThe winner is O. Congrats" << endl; }
	}
	return 0;
}

Let me know what you think!
Hi, from a design standpoint I would have appraoched it differently.
I try and separate the design into three functional layers - User Interface, Core Logic and Data Storage.
This can be a good habit to get into as it makes portability easier. If you wanted to switch from consol to GUI then you only need to change the UI layer, if you wanted to add a score table (Trivial example in this case:-) then you can easily switch from text file to DB without affecting the rest of the app, etc.
In this case I would have a class to hold the state fo the board, a class to display it, etc.
Faldrax, I will re-write to see if I can duplicate what you are talking about.

Thanks for the comment!
Topic archived. No new replies allowed.