Starting with C++ and Tic Tac Toe

I just started at a university CS program and the first language requirement is C++. So I thought that I would try to create a program with everything that I've learned so far and improve it as I learn new things. This way I can hold on to the stuff I know and use the things that I'm learning. I thought that a Tic Tac Toe game would be easy enough but the win conditions have me a bit stumped. I've gone through about a third of the C++ book so my knowledge is limited to the various loops and if statements available as well as functions and arrays. I haven't learned about classes yet, but classes and pointers are next week. So, I am hoping the knowledge on these forums can lend a hand. What I have so far is rudimentary and crude but it works. I'm using functions to display the game board, clear the board, and check for a full board condition. I'm using two parallel, 2D arrays, one for visuals so the players can see the the X or O token on the board and the other for all the condition computing underneath. Please try to remember that I'm using only what I know to get the job done so my processes may be a little under developed. The visual array is a char array to simply display an X, O, or a blank space. The second array in an int array and is initialized with all zeros to start and "1" for X and "-1" for every O.
My thought in this was that when checking for a win condition you could use the players row and column input to add up the three subscripts to either 3 or -3 and determine a win. I'm able to drag through a function and brute force my way through about 9 if statements for X tokens and another 9 for O. I'm wondering is my thought train on this is even in the right direction. I'll post the code that I have to far. Thanks in advance for any help in the right direction.


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

//THIS IS THE WIN CONDITION FUNCTION SO FAR.

  bool playerWinCondition(int parBoard[][3],int row, int first, int second, string token);
{
    if (token == player1)
        int sum = 3;
    if (first - 1 == 0)
        for (int total, index = 0; index < 3; index++)
        {
            total += parBoard[first - 1][index];
            if (total == sum)
                winCondition = true;
        }
    if (first - 1 == 1)
        for (int total, index = 0; index < 3; index++)
        {
            total += parBoard[first - 1][index];
            if (total == sum)
                winCondition = true;
        }
    if (first - 1 == 2)
        for (int total, index = 0; index < 3; index++)
        {
            total += parBoard[first - 1][index];
            if (total == sum)
                winCondition = true;
        }
    if (second - 1 == 0)
        for (int total, index = 0; index < 3; index++)
        {
            total += parBoard[index][second - 1];
            if (total == sum)
                winCondition = true;
        }
    if (second - 1 == 0)
        for (int total, index = 0; index < 3; index++)
        {
            total += parBoard[index][second - 1];
            if (total == sum)
                winCondition = true;
        }
    if (second - 1 == 0)
        for (int total, index = 0; index < 3; index++)
        {
            total += parBoard[index][second - 1];
            if (total == sum)
                winCondition = true;
        }
    if (first-1 == second -1)
        for (int total, index = 0; index < 3; index++)
        {
            total += parBoard[first-1][index];
            if (total == sum)
                winCondition = true;




//AND THIS IS THE MAIN GAME FUNCTION SO FAR




//Main game loop, Condition is wins per player.
    do
    {
        //First 'for' loop, player one's turn.
        for(int index = 0;index < 1; )
        {
            bool makeMove = false;
            while(!makeMove)
            {
            cout << "\n";
            cout << " " << player1 << endl;
            cout << "\n";
            cout << " Enter ROW #. ";
            cin >> first;
            cin.clear();
            cout << " Enter COLUMN #. ";
            cin >> second;
            cin.clear();
            cout << "\n";
            cout << "\n";
            cout << "\n";
            cout << "\n";

                //If statement to check if space chosen is already used.
                if(parBoard[first - 1][second - 1] == 1 || parBoard[first - 1][second - 1] == -1)
                {
                    cout << " That space is already taken,\n";
                    cout << " Please choose another.\n";
                }
                else
                {
                    //Place X token on visual game board.
                    gameBoard[first - 1][second - 1] = 'X';
                    //Place '1' placeholder integer on parallel game board.
                    parBoard[first - 1][second - 1] = 1;
                    index++;
                    makeMove = true;
                }//End of If statement.
            }//End while(makeMove) loop.
        }//End of player 1 first 'for' loop.

        //Print visual game board after player one makes move.
        printGameBoard(gameBoard, row);
        //Check if the game board is full and there are no more moves to make.
        full = boardFull(parBoard, row);
        //When the board is full a draw is declared and a new game is started.
         if (full)
        {
            cout << "\n";
            cout << " ITS A DRAW!!" << endl;
            cout << " LETS START A NEW GAME" << endl;
            cout << " Press ENTER to continue. ";
            cin.ignore();
            cin.get();

            //Clear the game board after a draw is declared.
            clearGameBoard(gameBoard, row);
            //Clear the parallel game array after a draw is declared.
            clearGameBoard(parBoard, row);
            //Print cleared game board.
            printGameBoard(gameBoard, row);

            continue;
        }

        //Second 'for' loop, player two's turn.
        for(int index = 0;index < 1; )
        {
            bool makeMove = false;
            while(!makeMove)
            {
            cout << "\n";
            cout << " " << player2 << endl;
            cout << "\n";
            cout << " Enter ROW #. ";
            cin >> first;
            cin.clear();
            cout << " Enter COLUMN #. ";
            cin >> second;
            cin.clear();
            cout << "\n";
            cout << "\n";

                //If statement to check if space chosen is already used.
                if(parBoard[first - 1][second - 1] == 1 || parBoard[first - 1][second - 1] == -1)
                {
                    cout << " That space is already taken,\n";
                    cout << " Please choose another.\n";
                }
                else
                {
                    //Place O token on visual game board.
                    gameBoard[first - 1][second - 1] = 'O';
                    //Place '-1' placeholder integer on parallel game board.
                    parBoard[first - 1][second - 1] = -1;
                    index++;
                    makeMove = true;
                }//End of If statement.
            }//End while(makeMove) loop.
        }//End of player 1 first 'for' loop.

        //Print visual game board after player two makes move.
        printGameBoard(gameBoard, row);

    } while(p1win < 3 || p2win < 3);
> The second array in an int array and is initialized with all zeros to start and "1" for X and "-1" for every O.
> My thought in this was that when checking for a win condition you could use the players row and column input
> to add up the three subscripts to either 3 or -3 and determine a win.

Yes, that is the right idea; one that can be implemented succinctly and elegantly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <cstdlib> // for int std::abs(int)

// initialized with all zeros to start, +1 for X and -1 for O.
const std::size_t N = 3 ;
typedef int par_board[N][N] ; // each cell contains 1 for 'X', -1 for 'O', and zero for empty

int row_sum( const par_board& board, std::size_t row ) { return board[row][0] + board[row][1] + board[row][2] ; }

int col_sum( const par_board& board, std::size_t col ) { return board[0][col] + board[1][col] + board[2][col] ; }

// if a row, col or diagonal sum adds up to 3 or -3, (ie. the absolute value of the sum is three) it is a win situation
bool player_win_condition( const par_board& board )
{
    for( std::size_t row = 0 ; row < N ; ++row ) if( std::abs( row_sum( board, row ) ) == 3 ) return true ;
    for( std::size_t col = 0 ; col < N ; ++col ) if( std::abs( col_sum( board, col ) ) == 3 ) return true ;

    if( std::abs( board[0][0] + board[1][1] + board[2][2] ) == 3 ) return true ; // diagonal 1
    if( std::abs( board[0][2] + board[1][1] + board[2][0] ) == 3 ) return true ; // diagonal 2

    return false ; // no win
}
Here is my code for 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
#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

//Function Prototypes
void Display_Board(char[], string, string);
bool Rater(char[], int&, int&);

int main()
{
	//Variables Definition
	int score1, score2, count1, count2;
	string Player1, Player2;
	//Dynamic Memory Allocation
	char *again = new char;
	int *board = new int;
	//Array for game board
	char Board_array[10] = { '1', '2', '3', '4', '5', '6', '7', '8', '9'};
	cout << "\t\t\tWelcome to Tic Tac Toe" << endl << endl << endl;
	//Prompts for user names
	cout << "Player 1 enter your name" << endl;
	getline(cin, Player1);
	cout << endl;
	cout << "Player 2 enter your name" << endl;
	getline(cin, Player2);
	//Resets the score
	score1 = 0;
	score2 = 0;
	do
	{
		//Clears the screen
		system("cls");
		//Displays the game board
		Display_Board(Board_array, Player1, Player2);
		//Resets the number of board markers
		count1 = 0;
		count2 = 0;
		//Loop for a game
		while ((count1 + count2) != 9)
		{
			cout << endl << endl;
			//Prompts the user for input
			cout << Player1 << "'s turn: ";
			cin >> *board;
			//Input Validation
			if (Board_array[(*board) - 1] == 'X' || Board_array[(*board) - 1] == '0')
				*board = 20;
			while (!(*board > 0 && *board < 10))
			{
				cout << "ERROR! Please enter a valid field from 1 - 9" << endl;
				cin >> *board;
				if (Board_array[(*board) - 1] == 'X' || Board_array[(*board) - 1] == '0')
					*board = 20;
			}
			//Places 'X' on player's desired location
			Board_array[(*board) - 1] = 'X';
			//Clears the screen
			system("cls");
			//Displays the board for Player 2
			Display_Board(Board_array, Player1, Player2);
			count1++;
			cout << endl << endl;
			//Rates the input of user if required
			if (Rater(Board_array, score1, score2))
			{
				cout << Player1 << " wins Congratulation!" << endl << endl;
				break;
			}
			else if ((count1)+(count2) == 9)
				break;
			cout << endl << endl;
			//Prompts the user for input
			cout << Player2 << "'s turn: ";
			cin >> *board;
			//Input Validation
			if (Board_array[(*board) - 1] == 'X' || Board_array[(*board) - 1] == '0')
				*board = 20;
			while (!(*board > 0 && *board < 10))
			{
				cout << "ERROR! Please enter a valid field from 1 - 9" << endl;
				cin >> *board;
				if (Board_array[(*board) - 1] == 'X' || Board_array[(*board) - 1] == '0')
					*board = 20;
			}
			//Places '0' on player's desired location
			Board_array[(*board) - 1] = '0';
			count2++;
			//Clears the screen
			system("cls");
			//Displays the game board for Player 2
			Display_Board(Board_array, Player1, Player2);
			cout << endl << endl;
			if (Rater(Board_array, score1, score2))
			{
				cout << Player2 << " wins Congatulation!" << endl << endl;
				break;
			}
			else if ((count1) + (count2) == 9)
				break;
		}
		cout << "Do you want to play again Y/N : ";
		cin >> *again;
		while (!((*again == 'Y' || *again == 'y') || (*again == 'N' || *again == 'n')))
		{
			cout << "ERROR! Please enter a valid answer" << endl;
			cin >> *again;
		}
		Board_array[0] = '1';
		Board_array[1] = '2';
		Board_array[2] = '3';
		Board_array[3] = '4';
		Board_array[4] = '5';
		Board_array[5] = '6';
		Board_array[6] = '7';
		Board_array[7] = '8';
		Board_array[8] = '9';
	} while (*again == 'Y' || *again == 'y');
	delete again, board;
	cout << endl << endl;
	if (score1 > score2)
		cout << Player1 << " wins with " << score1 << " wins" << " against " << Player2 << " with " << score2 << " wins" << endl;
	else if (score1 < score2)
		cout << Player2 << " wins with " << score2 << " wins" << " against " << Player1 << " with " << score1 << " wins" << endl;
	else
		cout << "The match was a tie with both players scoring " << score1 << endl;
	cin.get();
	return 0;
}

void Display_Board(char array[], string name1, string name2)
{
	cout << setw(10) << "|" << setw(10) << "|" << endl;
	cout << setw(5) << array[0] << setw(5) << "|" << setw(5) << array[1] << setw(5) << "|" << setw(5) << array[2] << endl;
	cout << setw(10) << "|" << setw(10) << "|" << endl;
	cout << "------------------------------" << endl;
	cout << setw(10) << "|" << setw(10) << "|" << endl;
	cout << setw(5) << array[3] << setw(5) << "|" << setw(5) << array[4] << setw(5) << "|" << setw(5) << array[5] << endl;
	cout << setw(10) << "|" << setw(10) << "|" << endl;
	cout << "------------------------------" << endl;
	cout << setw(10) << "|" << setw(10) << "|" << endl;
	cout << setw(5) << array[6] << setw(5) << "|" << setw(5) << array[7] << setw(5) << "|" << setw(5) << array[8] << endl;
	cout << setw(10) << "|" << setw(10) << "|" << endl;
	cout << endl << endl << endl;
	cout << name1 << ": X\n" << name2 << ": 0" << endl;
}

bool Rater(char array[], int &score1, int &score2)
{
	//Horizontal test cases
	if ((array[0] == 'X' && array[1] == 'X') && array[2] == 'X')
		score1++;
	else if ((array[0] == '0' && array[1] == '0') && array[2] == '0')
		score2++;
	else if ((array[3] == 'X' && array[4] == 'X') && array[5] == 'X')
		score1++;
	else if ((array[3] == '0' && array[4] == '0') && array[5] == '0')
		score2++;
	else if ((array[6] == 'X' && array[7] == 'X') && array[8] == 'X')
		score1++;
	else if ((array[6] == '0' && array[7] == '0') && array[8] == '0')
		score2++;
	//Vertical test cases
	else if ((array[0] == 'X' && array[3] == 'X') && array[6] == 'X')
		score1++;
	else if ((array[0] == '0' && array[3] == '0') && array[6] == '0')
		score2++;
	else if ((array[1] == 'X' && array[4] == 'X') && array[7] == 'X')
		score1++;
	else if ((array[1] == '0' && array[4] == '0') && array[7] == '0')
		score2++;
	else if ((array[2] == 'X' && array[5] == 'X') && array[8] == 'X')
		score1++;
	else if ((array[2] == '0' && array[5] == '0') && array[8] == '0')
		score2++;
	//Diagonal Test Cases
	else if ((array[0] == 'X' && array[4] == 'X') && array[8] == 'X')
		score1++;
	else if ((array[0] == '0' && array[4] == '0') && array[8] == '0')
		score2++;
	else if ((array[2] == 'X' && array[4] == 'X') && array[6] == 'X')
		score1++;
	else if ((array[2] == '0' && array[4] == '0') && array[6] == '0')
		score2++;
	else
		return false;
	return true;
}
Topic archived. No new replies allowed.