I am trying to create an artificially intelligent tic-tac-toe program. I am using the MENACE(Machine Educational Noughts And Crosses Engine) algorithm to create it. Anyway, I'm almost done, but I have a segmentation fault I need to take care of. Basically, the heart of my AI consist of a vector of matchBox. If you read about the MENACE machine at
http://www.adit.co.uk/html/menace_simulation.html then you may have an idea of what I mean by matchBox. A matchBox is a class I created that hold a tic-tac-toe position with some statistics about the possible moves in that tic-tac-toe position. I have a vector of matchBox, because I am going to grow the collection of matchBox and update the statistics of each matchBox as it plays more games. The more games it plays the more matchBox it accumulates (until eventually it has a matchBox for every single possible tic-tac-toe position) and the more accurate the statistics become (until eventually it solves tic-tac-toe).
In the beginning of my program I ask the user, "How many games do you want the computer to play before playing you?" (line 28) This allows the user to choose how much it wants the computer to "learn" before playing you. The number the user chooses goes into numberOfGames (line 29) and the program then enters a for loop (line 30) to execute that many games between computer1(vector<matchBox> that always plays 'X') and computer2(vector<matchBox> that always plays 'O'). When entering the for loop I create two arrays of boards (record_X and record_O)--line 33. They are going to keep track of each tic-tac-toe position the computer takes so that it can either punish or reward the computers actions (by adjusting the statistics of the move it chooses for that tic-tac-toe position). The Xcounter and Ocounter keep track of how many tic-tac-toe positions the computer actually sees in the game. If the tic-tac-toe game goes to the very end then the board array record_X would be full of meaningful tic-tac-toe positions, because X moved 5 times. However, a game could end early (say the 5th move) in that case Xcounter would terminate at 3 and the AI would know to just search the first three board positions in the record_X array.
So I create a board object called game (line 34). It is initialized to the beginning position of a normal tic-tac-toe game. A board is another class I created. It gives you anything and everything you would want to know about a tic-tac-toe position. For instance one of it's methods let's you know whether the game is done. That is why I have a while loop that says while (!game.isDone)- line 35. Since we want the computer to play numberOfGames games before playing the user we need someway of keeping track when a game is over or not. Since the game hasn't started the game is obviously not done so it enters the while loop. record_X stores the board position (game) in it's array. Then I execute an if statement. The if statement test whether the computer has information about this specific position. Since the vector<matchBox> starts out empty it obviously can't have information about the specific position. Therefore, it jumps to the else statement. The else statement adds the specific matchBox to computer1 and then randomly picks a move from that matchBox to play. See lines: 50- 52;
If that randomly chosen move is successful at the end of the game I will reward that move with a call:
(computer1[index]).incrementThree ();
If that randomly chosen move is unsuccessful at the end of the game I will punish that move with a call:
(computer2[index]).decrement ();
See lines 80, 85, 93 and 98.
Anyway, the segmentation fault happens somewhere in my code between:
lines 50 - 55.
I know this is alot of stuff so if you have any questions just let me know I will fill you in. Next is my code and my output. Look at my output so you can see how the program is running. This is a run-time error. I was able to compile this program just fine.
Here is my 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 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
|
/*
* testmatchBox.cpp
*
*
* Created by Matthew Dunson on 9/20/09.
* Copyright 2009 The Ohio State University. All rights reserved.
*
*/
#include <iostream>
#include <vector>
#include <cstdlib>
#include "matchBox.h"
#include "board.h"
using namespace std;
bool isDefined (vector<matchBox> bag, board game);
int returnIndex (vector<matchBox> bag, board game);
int main ()
{
int move, numberOfGames, n;
vector<matchBox> computer1, computer2;
cout << "How many games do you want the computer to play before playing you? ";
cin >> numberOfGames;
for (int i = 0; i < numberOfGames; i++)
{
int Xcounter = 0, Ocounter = 0;
board record_X[5], record_O[5];
board game;
while (!game.isDone ())
{
record_X[Xcounter] = game;
if (isDefined(computer1, game))
{
int index = returnIndex (computer1, game);
move = (computer1[index]).getMove ();
game.change (move, 'X');
}
else
{
cout << game;
matchBox box (game);
computer1.push_back (box);
cout << "The size of the vector computer1 is " << computer1.size () << "." << endl;
move = (computer1[computer1.size () - 1]).getMove ();
cout << "The position computer1 choose is " << move << " notice the \'X\' on the next output of the board \"game\"." << endl;
game.change (move, 'X');
cout << game;
}
Xcounter++;
cout << Xcounter;
if (!game.isDone ())
{
record_O[Ocounter] = game;
if (isDefined (computer2, game))
{
int index = returnIndex (computer2, game);
move = (computer2[index]).getMove ();
game.change (move, 'X');
}
else
{
matchBox box (game);
move = (computer2[computer2.size () - 1]).getMove ();
game.change (move, 'O');
}
Ocounter++;
}
}
if (game.xWin ())
{
for (int i = 0; i < Xcounter; i++)
{
int index = returnIndex (computer1, record_X[i]);
(computer1[index]).incrementThree ();
}
for (int i = 0; i < Ocounter; i++)
{
int index = returnIndex (computer2, record_O[i]);
(computer2[index]).decrement ();
}
}
if (game.oWin ())
{
for (int i = 0; i < Xcounter; i++)
{
int index = returnIndex (computer1, record_X[i]);
(computer1[index]).decrement ();
}
for (int i = 0; i < Ocounter; i++)
{
int index = returnIndex (computer2, record_O[i]);
(computer2[index]).incrementThree ();
}
}
}
cout << "Done playing games";
board game1;
int turn;
while (!game1.isDone ())
{
cout << game1;
if (isDefined (computer1, game1))
{
int index = returnIndex (computer1, game1);
turn = (computer1[index]).getMove ();
game1.change (turn, 'X');
cout << game1;
}
else
{
matchBox box (game1);
computer1.push_back (game1);
turn = (computer1[computer1.size () - 1]).getMove ();
game1.change (turn, 'X');
cout << game1;
}
if (!game1.isDone ())
{
cout << "What is your move";
cin >> turn;
game1.change (turn, 'O');
cout << game1;
}
}
return 0;
}
bool isDefined (vector<matchBox> bag, board game)
{
bool answer = false;
int counter = 0;
while (counter < bag.size ())
{
if (game == (bag[counter]).returnGame ())
{
answer = true;
break;
}
}
return answer;
}
int returnIndex (vector<matchBox> bag, board game)
{
int answer = 0, counter = 0;
while (counter < bag.size ())
{
if (game == (bag[counter]).returnGame ())
{
answer = counter;
break;
}
counter++;
}
return answer;
}
| |
Here is my output:
Last login: Sun Oct 18 16:22:59 on ttys000
localhost:~ matthewdunson$ Documents/c_plus_plus_projects/tic_tac_toe/testmatchBox
How many games do you want the computer to play before playing you? 2
1|2|3
-----
4|5|6
-----
7|8|9
The size of the vector computer1 is 1.
The position computer1 choose is 5 notice the 'X' on the next output of the board "game".
1|2|3
-----
4|X|6
-----
7|8|9
Segmentation fault
localhost:~ matthewdunson$
|