AI in tictactoe (segmentation error)

Out of sheer boredom, I decided to do the regular tictactoe game and try and make the computer unbeatable. I've got it to the point where it is drawing the majority of the time, but I am having some problems when I tell it to watch out for forks (where a line can be made in 2 different ways in the next move). I thought I had it working, but occasionally it clears the screen and goes into an infinite loop of blank lines. After about 15 mins of testing, I finally got a segmentation error. Here's the code (hope it's not too long)
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

bool ComputerValidMove(char board[], int movemade)
{
    if (board[movemade]=='X'||board[movemade]=='O')
    {
        return false;
    }
    return true;
}
int LookForWin(char board[],char player[],int play, bool fork=false)
{
    int wincombos[8][3]={{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
    for (int i=0; i<8; i++)
    {
        int pieces=0;
        int emptysquares=0;
        for (int j=0; j<3; j++)
        {
            if (board[wincombos[i][j]]==player[play])
            {
                pieces++;
            }
            else if (board[wincombos[i][j]]!='X' && board[wincombos[i][j]]!='O')
            {
                emptysquares++;
            }
        }
        if (pieces==2 && emptysquares==1)
        {
            for (int j=0; j<3; j++)
            {
                if (board[wincombos[i][j]]!='X' && board[wincombos[i][j]]!='O')
                {
                    return wincombos[i][j];
                }
            }
        }
        if (fork && pieces==1 && emptysquares==2)
        {
            for (int k=i+1; k<8; k++)
            {
            // find an intersecting line with the same property
                for (int j=0; j<3; j++)
                {
                    if (board[wincombos[k][j]]==player[play])
                    {
                        pieces++;
                    }
                    else if (board[wincombos[k][j]]!='X' && board[wincombos[k][j]]!='O')
                    {
                        emptysquares++;
                    }
                }
            }
            if (pieces==2 && emptysquares==4)
            {
                for (int j=0; j<3; j++)
                {
                    for (int k=i+1; k<8; k++)
                    {
                        for (int m=0; m<3; m++)
                        {
                            if (wincombos[i][j]==wincombos[k][m] && board[wincombos[i][j]]!='X' && board[wincombos[i][j]]!='O')
                            {
                                return board[wincombos[i][j]];
                            }
                        }
                    }
                }
            }
        }
    }
    return 9;
}
void DisplayBoard(char board[])
{
    for (int i=0; i<3; i++)
    {
        cout << "   |   |   " << endl;
        for (int j=0; j<3; j++)
        {
            cout << " " << board[3*i+j] << " ";
            if (j!=2)
            {
                cout << "|";
            }
        }
        cout << endl;
        if (i!=2)
        {
            cout << "___|___|___" << endl;
        }
    }
    cout << "   |   |   " << endl;
}
void ComputerMove (char board[],char player[], int& movesmade)
{
    int moves;
    string positions[9]={"top-left", "top-middle", "top-right", "middle-left", 
"center", "middle-right", "bottom-left", "bottom-middle", "bottom-right"};
    if (movesmade==0)
    {
        moves=rand()%9;
        board[moves]=player[1];
    }
    else if (movesmade==1)
    {
        if (board[0]==player[0]||board[2]==player[0]||board[6]==player[0]||board[8]==player[0])// if player went in corner
        {
            moves=4;
            board[moves]=player[1];
        }
        else if (board[4]==player[0])
        {
            bool validmove=false;
            while (!validmove)
            {
                int movelist[4]={0,2,6,8};
                moves=movelist[rand()%4];
                if (ComputerValidMove(board,moves))
                {
                    board[moves]=player[1];
                    validmove=true;
                }
            }
        }
    }
    else if (LookForWin(board , player, 1)!=9)
    {
        moves=LookForWin(board , player, 1);
        board[moves]=player[1];
    }
    else if (LookForWin(board , player, 0)!=9)
    {
        moves=LookForWin(board , player, 0);
        board[moves]=player[1];
    }
    else if (LookForWin(board , player, 1, true)!=9)
    {
        moves=LookForWin(board , player, 1,true);
        board[moves]=player[1];
    }
    else if (LookForWin(board , player, 0, true)!=9)
    {
        moves=LookForWin(board , player, 0,true);
        board[moves]=player[1];
    }
    else
    {
        bool validmove=false;
        while (!validmove)
        {
            moves=rand()%9;
            if (ComputerValidMove(board,moves))
            {
                board[moves]=player[1];
                validmove=true;
            }
        }
    }
    cout << "The computer took the " << positions[moves] << " square." << endl;
    movesmade++;
}
void PlayerMove (char board[],char player[], int turn, int& movesmade)
{
    string positions[9]={"top-left", "top-middle", "top-right", "middle-left", 
"center", "middle-right", "bottom-left", "bottom-middle", "bottom-right"};
    board[turn]=player[0];
    cout << "You took the " << positions[turn] << " square." << endl;
    movesmade++;
}
bool GameStatus(char board[], char player[], int& gameswon, int& gamesdrawn, int& gameslost)
{
    if (board[0]==board[1] && board[1]==board[2])
    {
        if (board[0]==player[1])
        {
            gameslost++;
            return true;
        }
        else
        {
            gameswon++;
            return true;
        }
    }
    else if (board[0]==board[3] && board[3]==board[6])
    {
        if (board[0]==player[1])
        {
            gameslost++;
            return true;
        }
        else
        {
            gameswon++;
            return true;
        }
    }
    else if (board[2]==board[5] && board[5]==board[8])
    {
        if (board[2]==player[1])
        {
            gameslost++;
            return true;
        }
        else
        {
            gameswon++;
            return true;
        }
    }
    else if (board[6]==board[7] && board[7]==board[8])
    {
        if (board[6]==player[1])
        {
            gameslost++;
            return true;
        }
        else
        {
            gameswon++;
            return true;
        }
    }
    for (int i=0; i<4; i++)
    {
        if (board[4]==board[i] && board[4]==board[8-i])
        {
            if (board[4]==player[1])
            {
                gameslost++;
                return true;
            }
            else
            {
                gameswon++;
                return true;
            }
        }
    }
    for (int i=0; i<9; i++)
    {
        if (board[i]!='X' && board[i]!='O')
        {
            return false;
        }
    }
    gamesdrawn++;
    return true;
}


D'oh, code was too long, will post the main function in next post. Here's the errors I'm getting:

#0 0046A91D std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () (??:??)
#1 00478860 std::cerr () (??:??)
#2 0046F0A5 std::__convert_from_v () (??:??)
#3 00402BD7 main() (C:\C++ Game\tictactoe\main.cpp:329)
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
int main()
{
    srand ( unsigned (time(0) ) );
    bool programactive=true;
    char board[9]={'1', '2', '3', '4', '5', '6', '7', '8', '9'};
    int playermove;
    int gameswon=0;
    int gamesdrawn=0;
    int gameslost=0;
    int gamesplayed=0;
    char piece;
    char player[2];
    int movesmade;
    bool gameactive;
    while (piece!='X' && piece!='O')
    {
        cout << "Select your piece (X or O)" << endl;
        cin >> piece;

    }
    if (piece=='X')
    {
        player[0]='X';
        player[1]='O';
    }
    else
    {
        player[0]='O';
        player[1]='X';
    }
    while (programactive)
    {
        for (int i=0; i<9; i++)
        {
            board[i]=i+49; // sets positions to 1-9 (ASCII code)
        }
        cout << "W: " << gameswon << " D: " << gamesdrawn << " L: " << gameslost << endl;
        gameactive=true;
        movesmade=0;
        while (gameactive)
        {
            if (gamesplayed%2==0 && movesmade==0)
            {
                ComputerMove(board, player, movesmade);
            }
            DisplayBoard(board);
            bool playerturn=false;
            if (!GameStatus(board, player, gameswon, gamesdrawn, gameslost))
            {
                cout << "Make your move." << endl;
                while (!playerturn)
                {
                    cin >> playermove;
                    if (playermove>9 || playermove<0 || board[playermove-1]=='X' || board[playermove-1]=='O')
                    {
                        cout << "invalid move- please select another" << endl;
                    }
                    else
                    {
                        PlayerMove(board, player, playermove-1, movesmade);
                        playerturn=true;
                    }
                }
            }
            else
            {
                gameactive=false;
                DisplayBoard(board);
                break;
            }
            if (!GameStatus(board, player, gameswon, gamesdrawn, gameslost))
            {
                ComputerMove(board, player, movesmade); // seg error here
            }
            else
            {
                gameactive=false;
                DisplayBoard(board);
                break;
            }
        }
        gamesplayed++;
    }
    return 0;
}
Last edited on
Topic archived. No new replies allowed.