War Games Tic Tac Toe

I saw a site that had C++ code as examples and there was a TicTacToe thing that was horrible and had comments like "//This line adds two numbers". It also had a random number generator to produce moves and it was not guaranteed to select one of the positions so it was just running some odd number of times so that it usually worked. I decided to make it into automatic play and test the "War Games" hypothesis that it was always a draw. I know that this is true, but I couldn't help changing the code to fix the silliness and try my hand at doing some C++ from scratch. I learned a few things that a person should keep in mind, like making sure index variables are not overloaded on arrays as this can be a real bear. I just used a weighted array with no flexibility in response though I could have randomized responses in the set of best responses or approached from different aspects to a choice, but I will leave that to the next person to leave their mark on this concept. Here is the code as I wrote it tonight and I make no promises, but I tested it and compile it with just "g++ tictactoe.cc -o tictactoe". It isn't gospel code so have fun with it.

/* This is an automatic "War Games" tictactoe game. Mohr */ #include "tictactoe.h" int main(int argc, char * argv[]){ ticTacToe tt; tt.debug=0; tt.runIt(tt); return 0;} ticTacToe::ticTacToe(){;} ticTacToe::~ticTacToe(){;} void ticTacToe::runIt(ticTacToe &tt){ tt.seedit(); // Init random number generator (unused) draws=0;gameNum=1; while ( gameNum <= MAX_GAMES ){ for(i=0;i<3;i++) for(j=0;j<3;j++) tt.tic[i][j]=' '; tt.ticp[1][1]=5; tt.ticp[1][2]=3; tt.ticp[1][0]=3; tt.ticp[0][1]=3; tt.ticp[0][2]=4; tt.ticp[0][0]=4; tt.ticp[2][1]=3; tt.ticp[2][2]=4; tt.ticp[2][0]=4; playNum=0; while (playNum<9){ if (tt.user(gameNum, tt) == 0 ){ playNum++; if ( tt.check(tt) == 1 ){tt.newdisp(tt);break;} if ( playNum == 9 ){draws++;break;} if ( tt.pcMove('O',tt) == 1 ){exit(1);} playNum++; if ( tt.check(tt) == 1 ){break;}} else{cout<<"try again."<<endl;}} gameNum++;}} int ticTacToe::user(int z, ticTacToe &tt){ if (z>=1){ return pcMove('X',tt);} /* Do the computer emulation if input is 1 */ cout<<"row column "; cin>>userx>>usery; if((userx<0) || (userx>2) && (usery<0) || (usery>2)){ cout<<"Invalid coordinates."<<endl; return 1;} else{ if(tt.tic[userx][usery]==' '){ tt.tic[userx][usery]='X'; tt.ticp[userx][usery]=10;} else{ cout<<"This position is filled try again."<<endl; return 1;}} return 0;} int ticTacToe::pcMove(char xo,ticTacToe &tt){ best=0;score=0;scoreval=10; for (il=0;il<3;il++){ score=scoreRow(il,tt); if (score>best){best=score;}} for (il=0;il<3;il++){ score=scoreColumn(il,tt); if (score>best){best=score;}} score=scoreDiagonal1(0, tt); if (score>best){best=score;}; score=scoreDiagonal2(0, tt); if (score>best){best=score;}; for (il=0;il<3;il++){ score=scoreRow(il, tt); if (score==best){rowmake(il,xo,scoreval, tt);return 0;}} for (il=0;il<3;il++){ score=scoreColumn(il, tt); if (score==best){colmake(il,xo,scoreval, tt);return 0;}} score=scoreDiagonal1(0, tt); if (score==best){diag1make(0,xo,scoreval, tt);return 0;} score=scoreDiagonal2(0, tt); if (score==best){diag2make(0,xo,scoreval, tt);return 0;} return 0;} int ticTacToe::check(ticTacToe &tt){ if( ((tt.tic[0][0] == tt.tic[0][1]) && (tt.tic[0][1] == tt.tic[0][2]) && (tt.tic[0][1]!=' ')) || ((tt.tic[1][0] == tt.tic[1][1]) && (tt.tic[1][1] == tt.tic[1][2]) && (tt.tic[1][1]!=' ')) || ((tt.tic[2][0] == tt.tic[2][1]) && (tt.tic[2][1] == tt.tic[2][2]) && (tt.tic[2][1]!=' ')) )return 1; if( ((tt.tic[0][0] == tt.tic[1][0]) && (tt.tic[1][0] == tt.tic[2][0]) && (tt.tic[0][0]!=' ')) || ((tt.tic[0][1] == tt.tic[1][1]) && (tt.tic[1][1] == tt.tic[2][1]) && (tt.tic[0][1]!=' ')) || ((tt.tic[0][2] == tt.tic[1][2]) && (tt.tic[1][2] == tt.tic[2][2]) && (tt.tic[0][2]!=' ')) )return 1; if( ((tt.tic[0][0] == tt.tic[1][1]) && (tt.tic[1][1] == tt.tic[2][2]) && (tt.tic[1][1]!=' ')) || ((tt.tic[0][2] == tt.tic[1][1]) && (tt.tic[1][1] == tt.tic[2][0]) && (tt.tic[1][1]!=' ')) )return 1; return 0;} void ticTacToe::seedit(void){ struct timeval tv; gettimeofday(&tv, NULL); srand(tv.tv_sec * tv.tv_usec);} int ticTacToe::scoreRow(int r,ticTacToe &tt){ if ( tt.tic[r][0]==' ' || tt.tic[r][1]==' ' || tt.tic[r][2]==' '){ if(( tt.tic[r][0]=='X' && tt.tic[r][1]=='O') || ( tt.tic[r][1]=='X' && tt.tic[r][2]=='O') || ( tt.tic[r][0]=='X' && tt.tic[r][2]=='O') || ( tt.tic[r][0]=='O' && tt.tic[r][1]=='X') || ( tt.tic[r][1]=='O' && tt.tic[r][2]=='X') || ( tt.tic[r][0]=='O' && tt.tic[r][2]=='X')){return 1;} return (tt.ticp[r][0]+tt.ticp[r][1]+tt.ticp[r][2]);} else{return 0;}} int ticTacToe::scoreColumn(int r,ticTacToe &tt){ if ( tt.tic[0][r]==' ' || tt.tic[1][r]==' ' || tt.tic[2][r]==' '){ if ( ( tt.tic[0][r]=='X' && tt.tic[1][r]=='O') || ( tt.tic[1][r]=='X' && tt.tic[2][r]=='O') || ( tt.tic[0][r]=='X' && tt.tic[2][r]=='O') || ( tt.tic[0][r]=='O' && tt.tic[1][r]=='X') || ( tt.tic[1][r]=='O' && tt.tic[2][r]=='X') || ( tt.tic[0][r]=='O' && tt.tic[2][r]=='X') ){return 1;} return (tt.ticp[0][r]+tt.ticp[1][r]+tt.ticp[2][r]);} else {return 0;}} int ticTacToe::scoreDiagonal1(int r,ticTacToe &tt){ if ( tt.tic[0][0]==' ' || tt.tic[1][1]==' ' || tt.tic[2][2]==' '){ if(( tt.tic[0][0]=='X' && tt.tic[1][1]=='O') || ( tt.tic[1][1]=='X' && tt.tic[2][2]=='O') || ( tt.tic[0][0]=='X' && tt.tic[2][2]=='O') || ( tt.tic[0][0]=='O' && tt.tic[1][1]=='X') || ( tt.tic[1][1]=='O' && tt.tic[2][2]=='X') || ( tt.tic[0][0]=='O' && tt.tic[2][2]=='X') ){return 1;} return (tt.ticp[0][0]+tt.ticp[1][1]+tt.ticp[2][2]);} else {return 0;}} int ticTacToe::scoreDiagonal2(int r,ticTacToe &tt){ if ( tt.tic[2][0]==' ' || tt.tic[1][1]==' ' || tt.tic[0][2]==' '){ if ( ( tt.tic[2][0]=='X' && tt.tic[1][1]=='O') || ( tt.tic[1][1]=='X' && tt.tic[0][2]=='O') || ( tt.tic[0][2]=='X' && tt.tic[2][0]=='O') || ( tt.tic[2][0]=='O' && tt.tic[1][1]=='X') || ( tt.tic[1][1]=='O' && tt.tic[0][2]=='X') || ( tt.tic[0][2]=='O' && tt.tic[2][0]=='X')) {return 0;} return (tt.ticp[0][2]+tt.ticp[1][1]+tt.ticp[2][0]);} else{return 0;}} void ticTacToe::rowmake( int r, char s, int scory,ticTacToe &tt){ for (ix=0;ix<3;ix++){ if (tt.tic[r][ix] == ' '){tt.tic[r][ix]=s;tt.ticp[r][ix]=scory;return;}}} void ticTacToe::colmake( int r, char s, int scory, ticTacToe &tt){ for (iy=0;iy<3;iy++){ if (tt.tic[iy][r] == ' '){tt.tic[iy][r]=s;tt.ticp[iy][r]=scory;return;}}} void ticTacToe::diag1make( int r, char s, int scory, ticTacToe &tt){ if (tt.tic[1][1] == ' '){tt.tic[1][1]=s;tt.ticp[1][1]=scory;return;} if (tt.tic[0][0] == ' '){tt.tic[0][0]=s;tt.ticp[0][0]=scory;return;} if (tt.tic[2][2] == ' '){tt.tic[2][2]=s;tt.ticp[2][2]=scory;return;}}; void ticTacToe::diag2make( int r, char s, int scory, ticTacToe &tt){ if (tt.tic[1][1] == ' '){tt.tic[1][1]=s;tt.ticp[1][1]=scory;return;} if (tt.tic[0][2] == ' '){tt.tic[0][2]=s;tt.ticp[0][2]=scory;return;} if (tt.tic[2][0] == ' '){tt.tic[2][0]=s;tt.ticp[2][0]=scory;return;}} void ticTacToe::newdisp(ticTacToe &tt){ if (tt.debug >= 1){cout<<endl; for( iz=0; iz<3; iz++ ){ cout<<" "<<tt.tic[iz][0]<<" | "<<tt.tic[iz][1]<<" | "<<tt.tic[iz][2]<<endl; if(iz != 2){cout<<" --|---|--"<<endl;}} for(iz=0;iz<3;iz++){ cout<<" "<<tt.ticp[iz][0]<<" | "<<tt.ticp[iz][1]<<" | "<<tt.ticp[iz][2]<<endl; if(iz != 2){cout<<" --|---|--"<<endl;}}}}

Here is the header too. I suppose there are some "build essentials" that are needed, but that is part of the fun. "sudo apt-get install build-essentials" gets most of the stuff. The code really has no output without debug as it only reports if one of the computer players wins and that should never happen in this universe. I don't know how this will look on the blog, as the blog form is not always completely WYSIWYG and some very strange things can happen.

#ifndef __MAIN_H__ #define __MAIN_H__ #include <iostream> #include <sys/time.h> using namespace std; const int MAX_GAMES = 200; class ticTacToe { public: ticTacToe(); ~ticTacToe(); int debug; void runIt(ticTacToe &tt); private: char tic[3][3]; int ticp[3][3]; /* These iteration variables should not interact during calls and so each should be unique. */ int il,ix,iy,iz,i,j; int score,best,scoreval,draws; int userx,usery; int gameNum; int playNum; /* Random number seeding using time, not implemented here. */ void seedit(); int user(int z, ticTacToe &tt); void newdisp(ticTacToe &tt); int pcMove(char x, ticTacToe &tt); int check(ticTacToe &tt); void rowmake( int r, char s, int scory, ticTacToe &tt); void colmake( int r, char s, int scory, ticTacToe &tt); void diag1make( int r, char s, int scory, ticTacToe &tt); void diag2make( int r, char s, int scory, ticTacToe &tt); int scoreDiagonal1(int r, ticTacToe &tt); int scoreDiagonal2(int r, ticTacToe &tt); int scoreRow(int r, ticTacToe &tt); int scoreColumn(int r, ticTacToe &tt); }; #endif

0 comments:

Contributors

Automated Intelligence

Automated Intelligence
Auftrag der unendlichen LOL katzen