TicTacToe game

Hello,

I`m now learning C++ and found a code which is a tictactoe game. Now I try to understand what each part of the code does and maybe improve it at some point. I have marked with */ my comments. If someone would be kind to explain the code little to me. Here is the code:

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

#include <iostream>

class TicTacToe
{
public:
	enum { PLAYER_X = 'X', PLAYER_O = 'O', AVAILABLE = ' '}; */ types that are defined with a set of custom identifiers, known as enumerators, as possible values which are X and 0 and can be called at some point?

	void newGame()
	{
		for (int r = 0; r < 3; ++r)
		{
			for (int c = 0; c < 3; ++c)
			{
				board[r][c] = AVAILABLE; */ presents the 3x3 board which is 2-dimensional, the syntax is unclear to me.
			}
		}
	}

	void play()
	{
		for (int turns = 0; turns < 9; ++turns)
		{
			char player = (turns % 2 == 0 ? PLAYER_X : PLAYER_O); */ char reserves memory for player X and player O?
			bool legal = false;
			do
			{
				int row = -1;
				int col = -1;    */ ??

				std::cout << "\nPlayer " << player << " -- Choose a move..." << std::endl;
				std::cout << "Enter row and col (e.g. 1 2): ";
				std::cin  >> row >> col;

				legal = isLegalMove(row-1, col-1);

				if (!legal) */ move happens if the move is legal , what does (row-1 and col-1) do?
				{
					std::cout << "Illegal move!  Try again...\n" << std::endl;
				}
				else
				{
					board[row-1][col-1] = player;

					displayBoard();

					if (checkForWin(player))
					{
						std::cout << "Player " << player << " has won!" << std::endl;
						exit(0);
					}
				}
			} while (!legal);
		} 
		std::cout << "The game ended in a tie!" << std::endl;
	}

private:
	void displayBoard()
	{
		std::cout << "+-----+-----+-----+\n";
		for (int r = 0; r < 3; ++r)
		{
			std::cout << "|";
			for (int c = 0; c < 3; ++c)
			{
				std::cout << "  " << board[r][c] << "  |";
			}
			std::cout << "\n+-----+-----+-----+\n";
		}
		std::cout << std::endl;
	}

	bool isLegalMove(int row, int col)
	{
		if (row < 0 || row > 2 || col < 0 || col > 2)
			return false;

		// return true if cell in board is available, false otherwise
		return board[row][col] == AVAILABLE;
	}

	bool checkForWin(char player)
	{
		for (int r = 0; r < 3; ++r)
		{
			if (board[r][0] == player && board[r][1] == player && board[r][2] == player)
				return true;  */ returns true if player enters numbers correctly?
		}
		for (int c = 0; c < 3; ++c)
		{
			if (board[0][c] == player && board[1][c] == player && board[2][c] == player)
				return true;
		}
		if ((board[0][0] == player && board[1][1] == player && board[2][2] == player) ||
		    (board[0][2] == player && board[1][1] == player && board[2][0] == player))
		{
			return true;
		}
		return false;
	}

	char board[3][3];
};

int main()
{
	TicTacToe ttt;

	ttt.newGame();
	ttt.play();
}
Last edited on
enum { PLAYER_X = 'X', PLAYER_O = 'O', AVAILABLE = ' '};
An enumeration is a type that contains discrete values. So this declares a type that has three values: PLAYER_X, PLAYER_O, and AVAILABLE.

Have you seen the type bool yet? bool is very much like an enum bool {false=0, true=1};

board[r][c] = AVAILABLE
Board is defined at line 103. This statement is assigning the enum AVAILABLE to an item in the array.

char player = (turns % 2 == 0 ? PLAYER_X : PLAYER_O);
This creates a single character called "player". The expression after "=" is the value that gets assigned to player initially. It's sort of a way to do an if-then-else inside an expression. If turns % 2 == 0 then this assigns PLAYER_X to player. Otherwise it assigns PLAYER_0 to player.

legal = isLegalMove(row-1, col-1);
It looks like the user can enter a column or row number between 1-3. But in C++, the first element in an array is number 0, not number 1. So it looks to me like isLegalMove() expects its row and column numbers to be "C++ index values" an not "user input values."

This presents a good opportunity for you to make a change. Rather than having "row" and "col" be in "user coordinates," try converting them to "C++ coordinates" immediately after the user inputs them by subtracting 1 from each. This way all of the code deals with C++ coordinates and you won't have to remember that these variables are an exception.
1
2
if (board[r][0] == player && board[r][1] == player && board[r][2] == player)
	return true;

This says that if columns 1, 2, and 3 in a single row (row r) are all occupied by the player, then player wins. More generally, the for loop at line 85 checks if the player has won by getting all three columns in any row. The loop at line 90 checks if they have all three rows in any column, and the code at lines 95 and 96 checks if they either diagonal.

Hope this helps,
Dave

(board[0][2] == player && board[1][1] == player && board[2][0] == player))

This is the diagonal from [0][2] to [2] [0] assuming that it means "three columns up from first square and then three rows horizontally to the right corner " however

in C++, the first element in an array is number 0, not number 1. Then columns [1] and [2] follow column [0] upwards.

The occupation of the second diagonal from [2] [2] to [0] [0], The occupation of this diagonal
is checked with for (int r = 0; r < 3; ++r) and this checks the occupation of any diagonal.


I try to change the code and see what happens. Very good explanation.

I changed legal = isLegalMove(row-1, col-1);

TO:

1
2
3
 for (int r = 0; r < 3; ++r) 

legal = isLegalMove(row [0][2], col[0][2]); 







Last edited on
I get error message after that... Please can anybody say what I did wrong?
Topic archived. No new replies allowed.