Help Modifying Tic Tac Toe

I am trying to make this Tic Tac Toe program so that it is always played against a computer. I need a rand() function limited between 1-8 to meet the criteria of the challenge. I am totally clueless and would greatly appreciate a full working modified code. I have read through other similar posts with no avail.

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
214
215
216
217
218
  // Tic Tac Toe, by Zach
 
// Include the libraries
#include <iostream>
#include <string>
 
//Use the standard namespace
using namespace std;
 
// Declare global variables
char Board[9];
 
// Declare functions
void showBoard ( );
bool moveIsValid (int m);
int whoWon ( ); //Returns 0 if no one has won, 1 if player 1 has won, and 2 if player 2 has won
 
void main ( )
{
   // Declare local variables
   string Player_1_Name;
   string Player_2_Name;
   int Whose_Turn = 1; // 1 means it's player 1's turn, 2 means it's player 2's turn
   int Move; // Stores where the player wants to move
   int Total_Moves = 0;
 
   //Assign values to the playing board
   Board[0] = '0';
   Board[1] = '1';
   Board[2] = '2';
   Board[3] = '3';
   Board[4] = '4';
   Board[5] = '5';
   Board[6] = '6';
   Board[7] = '7';
   Board[8] = '8';
 
   // Get player names
   cout << "Player 1: Please enter your name." << endl;
   cin >> Player_1_Name;
   cout << "Player 2: Please enter your name." << endl;
   cin >> Player_2_Name;
 
   while (whoWon ( ) == 0 && Total_Moves < 9)
   {
      // Do this until the player chooses a valid move
      do
      {
         // Show the board
         showBoard ( );
 
         // Tell which player to move
         if (Whose_Turn == 1)
         {
            cout << Player_1_Name << ": It's your turn." << endl;
         }
         else
         {
            cout << Player_2_Name << ": It's your turn." << endl;
         }
         // Get the move
         cout << "Enter the number of the spot where you'd like to move." << endl;
         cin >> Move;
      } while (moveIsValid (Move) != true);
 
      // Add 1 to Total_Moves
      Total_Moves++;
 
      // Change whose turn it is
      switch (Whose_Turn)
      {
      case (1):
         {
            Board[Move] = 'x';
            Whose_Turn = 2;
            break;
         }
      case (2):
         {
            Board[Move] = 'o';
            Whose_Turn = 1;
         }
      }
   }
   // Show the board
   showBoard ( );
 
   if (whoWon ( ) == 1)
   {
      cout << Player_1_Name << " has won the game!" << endl;
   }
   else if (whoWon ( ) == 2)
   {
      cout << Player_2_Name << " has won the game!" << endl;
   }
   else
   {
      cout << "It's a tie game!" << endl;
   }
 
   system ("PAUSE");
}
 
void showBoard ( )
{
   cout << endl;
   cout << Board[0] << " | " << Board[1] << " | " << Board[2] << endl;
   cout << "--+---+--" << endl;
   cout << Board[3] << " | " << Board[4] << " | " << Board[5] << endl;
   cout << "--+---+--" << endl;
   cout << Board[6] << " | " << Board[7] << " | " << Board[8] << endl;
   cout << endl;
}
 
bool moveIsValid (int m)
{
   if (Board[m] != 'x' && Board[m] != 'o')
   {
      return true;
   }
   else
   {
      return false;
   }
}
 
int whoWon ( )
{
   if (Board[0] == Board[1] && Board[1] == Board[2])
   {
      if (Board[0] == 'x')
      {
         return 1;
      }
      else
      {
         return 2;
      }
   }
   if (Board[3] == Board[4] && Board[4] == Board[5])
   {
      if (Board[3] == 'x')
      {
         return 1;
      }
      else
      {
         return 2;
      }
   }
   if (Board[6] == Board[7] && Board[7] == Board[8])
   {
      if (Board[6] == 'x')
      {
         return 1;
      }
      else
      {
         return 2;
      }
   }
   if (Board[0] == Board[3] && Board[3] == Board[6])
   {
      if (Board[0] == 'x')
      {
         return 1;
      }
      else
      {
         return 2;
      }
   }
   if (Board[1] == Board[4] && Board[4] == Board[7])
   {
      if (Board[1] == 'x')
      {
         return 1;
      }
      else
      {
         return 2;
      }
   }
   if (Board[2] == Board[5] && Board[5] == Board[8])
   {
      if (Board[2] == 'x')
      {
         return 1;
      }
      else
      {
         return 2;
      }
   }
   if (Board[0] == Board[4] && Board[4] == Board[8])
   {
      if (Board[0] == 'x')
      {
         return 1;
      }
      else
      {
         return 2;
      }
   }
   if (Board[2] == Board[4] && Board[4] == Board[6])
   {
      if (Board[2] == 'x')
      {
         return 1;
      }
      else
      {
         return 2;
      }
   }
   return 0;
}
You usually limit rand using modulo operator, but I recommend you not using rand.
You can use random number generators from <random> header instead, which will be much better, see:
http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful

Anyway, to answer your question:
1
2
3
4
5
int i = (rand() % 8 ) +1;
//This code is doing following things:
//rand() -> get random number in the range or RAND_MAX
// rand() % 8 -> (in short) cuts range from 0 to 7
// +1 -> adds 1, meaning we now have range from 1 to 8 


Pattern for getting range of rand is:
rand() % N
And you get range from 0 to N-1. If you want to have range from X to Y, you do:
(rand() % Y-X+1) +X

Cheers!
Last edited on
Ok, but how would I implement that into the main code? I knew how rand worked, but I have no idea of how to make it act as it's own player in the game.
A very simple way of implementing it would be this:
while(true)
-Make a random number, n
-Check if square n is empty
-If it is empty, play in that square and break;
Also, not too god way. Infinite loops are not good.
Where did you learn C++? You should never declare main as void.
do:
int main() or int main(int argc, char* args[]) instead.

Game consists of game loop. It goes somewhat like this:
1
2
3
4
5
6
7
//Pseudocode
while(PlayerWantsToPlay)
{
     GetInput();
     GameLogic();
     Draw();
}

And that's all. Now what is every of these functions?

GetInput() gets input from player. Simple as that. In more advanced games it may be checking for many buttons, but right now, in cosole, you will most likely simply get some char input from cin.

GameLogic is, well... where game logic is. It checks for collision, moves everything, updates object's, and so on. In tic-tac-toe, here you can chceck if anyone won, check if input was valid, and if it was, put 'x' or 'o' in currently chosen cell.

Draw() will draw everything. Here it will most likely be some formatted output, using cout.

Cheers!
Here is a complete example of how to produce a random number...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <ctime>
using namespace std;

int main() {

	srand ( time(NULL)); //this is needed for 'seeding the random draw'

	bool gameon = true; //used to end a loop

	while (gameon == true) {
		
	int randnum = (rand() % 8) + 1; //create a random number from 1-8
		
	
	cout << randnum << endl;
                if (randnum == 8) {
                   gameon = false;
                }
	}
  system ("PAUSE");
	return 0;
}
Last edited on
lol @MatthewRock, criticizing my infinite loop and then immediately posting your code in an infinite game loop.
@Mats -
1
2
3
4
while(true)
{
//code...
}

While loop with constant bool(true). Condition will always be true. This loop will run forever(almost :) ). You can only stop this loop by break, goto, etc.

1
2
3
4
5
bool SomeBool = true;
while(SomeBool)
{
//code...
}

This isn't an infinite loop. You can put functions that I mentioned in post before, and you can change SomeBool to false. You don't have to use break or goto, and your intention is clear.

I just wanted to say that I consider creating loops with bool as a condition better practice, then with const bool("true"). It just shows when loop is running, and when it should stop. :)
Last edited on
So I found this yesterday and I wanted to modify your code just for the fun of it.

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
// Tic Tac Toe, by Zach
// Modified by James

#include <iostream>
#include <string>
#include <vector>
#define SIZE 9

using namespace std;

char BOARD[SIZE] = {'0', '1', '2', '3', '4', '5', '6', '7', '8'};

// The layout of our new type: Player
struct Player
{
    string name;
    char mark;
    Player(string n, char m)
    {
        name = n;
        mark = m;
    }
    ~Player() {};
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                    These functions appear in the order they are first called in the program                    //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void PLAY_GAME(); // Start the game instructions                                                                  //
string get_names(string*, int); // Enter the players' names                                                       //
bool making_move(vector<Player>*, int*); // Handles everything related to a single player's turn on the board     //
void show_board(); // Displays the board and its marks                                                            //
bool valid_move(char*, int*); // Determines if a given move can be made                                           //
void place_mark(char*, int*); // Places the player's mark whose turn it is                                        //
int winner(); // Returns 0 if a tie, 1 if player 1 has won, and 2 if player 2 has won                             //
void determine_winner(vector<Player>*, int*); // Determines winner if all spaces are filled                       //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int main()
{
    PLAY_GAME();

    return 0;
}

void PLAY_GAME()
{
    //     What each element of "data" will represent      //
    // [0] = Turn - [1] = Current Move - [2] = Total Moves //
    /////////////////////////////////////////////////////////
    int* data = new int[3];
    data[0] = 0;
    data[1] = 0;
    data[2] = 0;


    //   Adds two instances of "Player" to a vector "v"    //
    /////////////////////////////////////////////////////////
    string name;
    vector<Player>* v = new vector<Player>;
    v->push_back(Player(get_names(&name, 1), 'X'));
        name.clear();
    v->push_back(Player(get_names(&name, 2), 'O'));
        name.clear();

    // Prevents you from attempting to play longer than the game allows
    while(data[2] < SIZE)
    {
        // Exists solely to keep track of how many turns have occured
        cout << "\tTurn " << data[2] + 1 << endl;

        // Executes the function until the player makes a valid move
        while(making_move(v, data)) {}

        // This bit means we will begin checking for a winner
        // once enough moves have been made for player 1 to win
        if(data[2] >= 4)
            if(winner() != 0)
                break;
    }

    show_board();
    determine_winner(v, &data[1]);

    delete v;
    delete[] data;
}
string get_names(string* name, int num)
{
    cout << "Enter the name for player " << num << ": ";
        cin >> *name; cout << endl;

    return *name;
}
bool making_move(vector<Player>* v, int* data)
{
    show_board();

    cout << "\t" << v->at(data[0]).name << " ... It's your turn.\n";

    cout << "\tEnter the number of the spot where you'd like to move: ";
        cin >> data[1]; cout << endl;

    return valid_move(&v->at(data[0]).mark, data);
}
void show_board()
{
        cout << endl;
    cout << "\t\t\t\t" << BOARD[0] << " | " << BOARD[1] << " | " << BOARD[2] << endl;
        cout << "\t\t\t\t--+---+--" << endl;
    cout << "\t\t\t\t" << BOARD[3] << " | " << BOARD[4] << " | " << BOARD[5] << endl;
        cout << "\t\t\t\t--+---+--" << endl;
    cout << "\t\t\t\t" << BOARD[6] << " | " << BOARD[7] << " | " << BOARD[8] << endl;
        cout << endl;
}
bool valid_move(char* mark, int* data)
{
    // Determines if the selected spot has already been marked
    if (BOARD[data[1]] != 'X' && BOARD[data[1]] != 'O')
    {
        place_mark(mark, data);
        return false;
    }

    cout << "Invalid Move. Try again." << endl;
    return true;
}
void place_mark(char* mark, int* data)
{
    BOARD[data[1]] = *mark; // Places mark of the current player at the chosen spot
    ++data[0] %= 2; // Switches turns
    ++data[2]; // Updates total number of moves made
}
int winner()
{
    if(BOARD[0] == BOARD[1] && BOARD[1] == BOARD[2])
    {
        if(BOARD[0] == 'X')     return 1;
        return 2;
    }
    if(BOARD[3] == BOARD[4] && BOARD[4] == BOARD[5])
    {
        if(BOARD[3] == 'X')     return 1;
        return 2;
    }
    if(BOARD[6] == BOARD[7] && BOARD[7] == BOARD[8])
    {
        if(BOARD[6] == 'X')     return 1;
        return 2;
    }
    if(BOARD[0] == BOARD[3] && BOARD[3] == BOARD[6])
    {
        if(BOARD[0] == 'X')     return 1;
        return 2;
    }
    if(BOARD[1] == BOARD[4] && BOARD[4] == BOARD[7])
    {
        if(BOARD[1] == 'X')     return 1;
        return 2;
    }
    if(BOARD[2] == BOARD[5] && BOARD[5] == BOARD[8])
    {
        if(BOARD[2] == 'X')     return 1;
        return 2;
    }
    if(BOARD[0] == BOARD[4] && BOARD[4] == BOARD[8])
    {
        if(BOARD[0] == 'X')     return 1;
        return 2;
    }
    if(BOARD[2] == BOARD[4] && BOARD[4] == BOARD[6])
    {
        if(BOARD[2] == 'X')     return 1;
        return 2;
    }
    return 0;
}
void determine_winner(vector<Player>* v, int* move)
{
    if(winner() != 0)
        cout << v->at(winner() - 1).name << " has won the game!\n" << endl;
    else
        cout << "It's a tie game!" << endl;
}



I want to work on a smarter option for determining if a winning move was played instead of checking up to 8 times per turn after 4 turns have elapsed. I'm going to look for some help on this
Well I have written a Tic-Tac-Toe game few months ago in the D Programming Language. It is somewhat similar to C++ so you might be able to pick some ideas.

http://pastebin.com/NqzaPfi1
Also, if you want the compiled executable (to run it): http://wikisend.com/download/657056/tictac.exe
Last edited on
I also have some experience with this in Java as well as C++. While my working versions of Tic-Tac-Toe were primarily designed as 2 player, I can see how randomization could be used as a simple AI for a computer based player, as there are only a few options involved. I made use of a 2d array for mine, with a simple check for victory or a draw at the end of each turn. If no victory or draw occurred, the active player is alternated from 1 to 2 and the turn repeats, and this patern continues until one player wins or no empty spaces are left.
Last edited on
A good logic to follow for the AI is to perform these checks in this order.

1. Check for a win move.(you have two in row already)
if not then...
2.Check for a block move.(the opponent has two in row and must be stopped.)
if not then...
3. check for a two way possible win.(this move causes you to get two in a row going two different ways. the opponent can only block one, you will win next move.)
if not then...
4. check for a possible opponents two way.(This is to stop an opponent from catching you with two possible wins.)
if not then...
5. place a random move.

This was the logic I used when I made the game in JavaScript. It can not be defeated. When I switch both sides to computer control, it always ends in a tie game.
Last edited on
Topic archived. No new replies allowed.