I sow several tic-tac-toe games for arduino.
All of them were designed for GLCD library, and none was a "thinking" one, all were randomly chosen steps.
At first this game was designed for GLCD, but when I sow the TVOUT library, I knew this will be my first trail with it, converting the tic tac toe to output on TV.
You can see the setup in this photo:
I used Duemilanove board, the keyboard you see is also home made. The arduino is connected to the computer since I was in the middle of working on the code when I took the photo.
And in this photo you can see Its still easy to beat the game, but that is true when playing against humans as well, If you go for 3 corners no one can stop you from winning.
If you are interested in the code, just drop me a line.
I think I would like to add some sounds to it as well, which is available with the TVOUT library.
This looks really good. Do you have any videos showing it in action? Have you considered making a version with some form of AI, so that it's a real challenge?
I decently need to make a video, just don't have a proper video camera to do it with.
It's not Simple to beat it, but as you might know, if u played enough tic tac toe, that there are not as many options of winning.
And the chance of winning if u r second are close to none ...
Basically what I did is to teach it all that I know about the game, it sues score point to choose the next move out of the possibilities, this is the part of code that is responsible fro the "thinking".
// **********************************************************************************************************************
// Compute next move
// **********************************************************************************************************************
void computNextMove(){
// declare high points for tile
int highpoints = 0;
int highpointsRow = 4; //we use 4 as WAY bigger then the cube
int highpointsCol = 4; //we use 4 as WAY bigger then the cube
// lo0p over row
for(int row = 0; row < 3; row++) {
// loop over col
for (int col = 0; col < 3; col++) {
// if ZERO - free space
if (tiles[row][col] ==0) {
// Calc the total of the ROW
int totalRow = tiles[row][0] +tiles[row][1] + tiles[row][2] ;
int totalCol = tiles[0][col] +tiles[1][col] + tiles[2][col] ;
// declare the othe player for the math
int OtherPlayer = CurrentPlayer==0?1:0;
int CurrentPlayerPlaceHolder=placeHolder[CurrentPlayer];
int OtherPlayerPlaceHolder=placeHolder[OtherPlayer];
int totalTilePoints =0;
// make 2 for self = 1 point ** block 2 of oppisite = 3 ** make 3 (win) = 5
// add row trotal points
totalTilePoints = totalTilePoints + calcTotalPointsSetOfThree(totalRow);
// add col total points
totalTilePoints = totalTilePoints + calcTotalPointsSetOfThree(totalCol);
// check center
if (row ==1 && col ==1) {
// on diag
int diagTotalONE = tiles[0][0] +tiles[1][1] + tiles[2][2];
// add diagn poins
totalTilePoints = totalTilePoints + calcTotalPointsSetOfThree(diagTotalONE);
// secdiag
int diagTotalTWO = tiles[2][0] +tiles[1][1] + tiles[0][2];
// add diagn poins
totalTilePoints = totalTilePoints + calcTotalPointsSetOfThree(diagTotalTWO);
} // end if (row ==1 && col ==1)
// check diagonals
if (row !=1 && col !=1) {
// add extra point for crners
totalTilePoints = totalTilePoints + 1;
// to know in wich dirctio nto go
int rowDir = row==0?1:-1;
int colDir = col==0?1:-1;
int diagTotal = tiles[row][col] +tiles[row+rowDir][col+colDir] + tiles[row+rowDir*2][col+colDir*2];
// add diagn poins
totalTilePoints = totalTilePoints + calcTotalPointsSetOfThree(diagTotal);
// add 1 more tests :
// 1, if the OTHER ROW CORENER is your opponenet add 1 point
if (tiles[row][col+colDir*2] == OtherPlayerPlaceHolder) {
totalTilePoints = totalTilePoints + 1; }
// 2, if the OTHERcol CORENER is your opponenet add 1 point
if (tiles[row+rowDir*2][col] == OtherPlayerPlaceHolder) {
totalTilePoints = totalTilePoints + 1; }
} // END if (row !=1 && col !=1)
// check if maxed high point
if (highpoints<totalTilePoints) {
highpoints = totalTilePoints;
highpointsRow = row;
highpointsCol = col;
} // end if (highpoints<totalTilePoints)
} // end (tiles[j][k] =!=0)
} // end loop over col
} // end loop over row
// if found possible row
if (highpoints >0) {
playMove(highpointsRow,highpointsCol); }
// if not found match .. random choose one of the corners
else {
// first check fi (1,1) is avialble
int fodunfreespace = 0;
// lop over row
for(int j = 0; j < 3; j++) {
// loop over col
for (int k = 0; k < 3; k++) {
// set to zero = empty
if(tiles[j][k] == 0) {
fodunfreespace = 1;
playMove(j,k);
} // end if(tiles[j][k] == 0)
} // end loop over col
} // end loop over row
// if not foudn any open space ... end game
if (fodunfreespace == 0) {
isGameOver = 1;
refreshDisplay = true;
} // end if (fodunfreespace == 0)
} // end if (highpoints >0)
} // end void computNextMove
If you got ideas to improve it I'm more then happy to hear ...
After sending the video to my brother he pointed out that the tic tac toe game when played by equal players will always end up in a tie.
I then remembered this scene from the "war games" movie from back in the 80's (one of the best computer movies)
So I took the challenge and here is a revised version of the "thinking" part, I would love to get comment if any one can beat the computer now.
If u want the full code just drop me a line,
void computNextMove(){
// declare high points for tile
int highpoints = 0;
int highpointsRow = 4; //we use 4 as WAY bigger then the cube
int highpointsCol = 4; //we use 4 as WAY bigger then the cube
// lo0p over row
for(int row = 0; row < 3; row++) {
// loop over col
for (int col = 0; col < 3; col++) {
// if ZERO - free space
if (tiles[row][col] ==0) {
// Calc the total of the ROW
int totalRow = tiles[row][0] +tiles[row][1] + tiles[row][2] ;
int totalCol = tiles[0][col] +tiles[1][col] + tiles[2][col] ;
// declare the othe player for the math
int OtherPlayer = CurrentPlayer==0?1:0;
int CurrentPlayerPlaceHolder=placeHolder[CurrentPlayer];
int OtherPlayerPlaceHolder=placeHolder[OtherPlayer];
int totalTilePoints =0;
// make 2 for self = 1 point ** block 2 of oppisite = 3 ** make 3 (win) = 5
// add row trotal points
totalTilePoints = totalTilePoints + calcTotalPointsSetOfThree(totalRow);
// add col total points
totalTilePoints = totalTilePoints + calcTotalPointsSetOfThree(totalCol);
// check center
if (row ==1 && col ==1) {
//ADD point for crners
totalTilePoints = totalTilePoints + 3 ;
// on diag
int diagTotalONE = tiles[0][0] +tiles[1][1] + tiles[2][2];
// add diagn poins
totalTilePoints = totalTilePoints + calcTotalPointsSetOfThree(diagTotalONE);
// secdiag
int diagTotalTWO = tiles[2][0] +tiles[1][1] + tiles[0][2];
// add diagn poins
totalTilePoints = totalTilePoints + calcTotalPointsSetOfThree(diagTotalTWO);
} // end if (row ==1 && col ==1)
// check diagonals
if (row !=1 && col !=1) {
//ADD point for crners
// totalTilePoints = totalTilePoints +1 ;
// to know in wich dirctio nto go
int rowDir = row==0?1:-1;
int colDir = col==0?1:-1;
int diagTotal = tiles[row][col] +tiles[row+rowDir][col+colDir] + tiles[row+rowDir*2][col+colDir*2];
// add diagn poins
totalTilePoints = totalTilePoints + calcTotalPointsSetOfThree(diagTotal);
// add 1 more tests :
} // END if (row !=1 && col !=1)
// any of the outer center cubes
if ((row == 1 && col != 1) || (row != 1 && col == 1)) {
// if u got the center, pick this one
if(tiles[1][1] == CurrentPlayerPlaceHolder) {
totalTilePoints = totalTilePoints + 2 ; }
} // end if ((row == 1 && col != 1) || (row != 1 && col == 1))
// check if maxed high point
if (highpoints<totalTilePoints) {
highpoints = totalTilePoints;
highpointsRow = row;
highpointsCol = col;
} // end if (highpoints<totalTilePoints)
} // end (tiles[j][k] =!=0)
} // end loop over col
} // end loop over row
// if found possible row
if (highpoints >0) {
playMove(highpointsRow,highpointsCol); }
// if not found match .. random choose one of the corners
else {
// first check fi (1,1) is avialble
int fodunfreespace = 0;
// lop over row
for(int j = 0; j < 3; j++) {
// loop over col
for (int k = 0; k < 3; k++) {
// set to zero = empty
if(tiles[j][k] == 0 && fodunfreespace==0) {
fodunfreespace = 1;
playMove(j,k);
break;
} // end if(tiles[j][k] == 0)
} // end loop over col
} // end loop over row
// if not foudn any open space ... end game
if (fodunfreespace == 0) {
isGameOver = 1;
refreshDisplay = true;
} // end if (fodunfreespace == 0)
} // end if (highpoints >0)
} // end void computNextMove