Help me program how to win in tic tac toe

please format code with </> button * homework policy * asking questions

//A simple tic tac toe by Caleigh Esterhuyse

Grid grid;
int numMoves = 9;
int column, row;
boolean player1Playing = true;
int moves = new int[numMoves];

void setup() {
size(600, 630);
grid = new Grid();
}

void draw() {
background(255);
grid.display();
drawPlayerLabel();
gameElements();
}

void mousePressed() {
column = mouseX/200;
row = mouseY/200;

int indexInArray = column + (row * 3);

if (moves[indexInArray] == 0) {
if (player1Playing) {
moves[indexInArray] = 1;
} else {
moves[indexInArray] = 2;
}
}
player1Playing = !player1Playing;
}

void drawPlayerLabel() {
String label = “Player 1”;

if (player1Playing == false) {
label = “Player 2”;
}

fill(0);
textSize(16);
textAlign(CENTER, BOTTOM);
text(label, width/2, height - 5);
}

void gameElements() {

for ( int i = 0; i < moves.length; i++) {
column = i % 3;
row = i / 3;

switch (moves[i]) {
case 1:  
  new Cross(column, row);
  break;
case 2: 
  new Circle(column, row);
  break;
}

}
}

class Circle {

int column, row;

Circle(int column, int row) {
this.column = column;
this.row = row;

display();

}

void display() {
strokeWeight(10);
stroke(#6DC5D3);
fill(255);
pushMatrix();
//translate( 100 + column * 200, 100 + row * 200);
circle(100 + 200 * column, 100 + 200* row, 100);

popMatrix();

}
}

class Cross {
int column, row;

Cross(int column, int row) {
this.column = column;
this.row = row;
display();
}

void display() {
strokeWeight(10);
stroke(#E37272);

pushMatrix();
translate( 100 + column * 200, 100 + row * 200);
line(- 40, -40, 40, 40);
line(- 40, 40, 40, -40);

popMatrix();

}
}

class Grid {

//Methods
void display() {
strokeWeight(1);
stroke(0);
line(width/3, 15, width/3, height - 15);
line(width/32, 25, width/32, height - 15);
line(0, height/3, width, height/3);
line(0, height/32, width, height/32);
}
}

Do you want to play against the computer and the computer generates moves?

Like a computer AI?

New version without AI

In this version

  • hit n for a new game
  • hit 0,1,2… to see lines that can be used for a win
  • program shows when somebody wins
  • program shows when board is full (a Draw)

Chrisir





//A simple tic tac toe by Caleigh Esterhuyse
// Version 2 - 4th of October 2020

Grid grid;
int numMoves = 9;
int column, row;
boolean player1Playing = true;
int[] moves = new int[numMoves];

// stuff to detect a win --------------------------
// this is a list of triples. 
// Each triple holds the indexes for moves[] for one winning line. Press 0..9 to see them.  
int[][] listOfIndexesForPossibleWins = {

  {0, 1, 2}, // horiz
  {3, 4, 5}, 
  {6, 7, 8}, 

  {0, 3, 6}, // vertical 
  {1, 4, 7}, 
  {2, 5, 8}, 

  { 0, 4, 8 }, //diagonal 
  { 6, 4, 2 }

};

int listOfIndexesForPossibleWins_To_Show=-1; // No triple / line is shown  

// Winner is: 
int winnerIs=-1; // NONE
boolean itsADraw=false; 

//------------------------------------------------------------------

void setup() {
  size(600, 630);
  grid = new Grid();
}

void draw() {
  background(255);

  grid.display();
  drawPlayerLabel();
  gameElements();

  showWinningLine();
  didSomebodyWin();
  showWinner();

  if (itsADraw) {
    fill(2, 0, 0); 
    text("It's a draw (N to New)", 100, 100);
  }
}

//------------------------------------------------------------------
// Input functions 

void mousePressed() {

  if (winnerIs!=-1) 
    return; // leave

  column = mouseX/200;
  row = mouseY/200;

  int indexInArray = column + (row * 3);

  // Is field empty?
  if (moves[indexInArray] == 0) {
    //ok
    if (player1Playing) {
      moves[indexInArray] = 1;
    } else {
      moves[indexInArray] = 2;
    }
  }//if
  player1Playing = ! player1Playing;

  printArray(moves);
  println();
}

void keyPressed() {
  switch(key) {
  case 'n':
    // NEW 
    moves = new int[numMoves];
    player1Playing = true;
    winnerIs=-1;
    listOfIndexesForPossibleWins_To_Show=-1; 
    itsADraw=false;
    break;

  default:
    listOfIndexesForPossibleWins_To_Show=key-48;
    println(listOfIndexesForPossibleWins_To_Show);
    break;
  }
}

//------------------------------------------------------------------
// Other functions 

void showWinner() {
  switch( winnerIs) {
  case -1: 
    //none
    break; 

  case 1:
    fill(255, 0, 0); 
    text("Player 1 won (N to New)", 100, 100);
    break; 

  case 2:
    fill(255, 0, 0);
    text("Player 2 won (N to New)", 100, 100);
    break;
  }
}

void didSomebodyWin() {
  int count=0;

  // check both players 
  for (int checkPlayer=1; checkPlayer<=2; checkPlayer++) {

    // loop over all triples 
    int tripleCounter=0; 
    for (int[] a : listOfIndexesForPossibleWins) {
      // loop over this triple and count
      count=0;        
      for (int i : a) {
        if ( moves[i] == checkPlayer ) {
          count++;
        }//count
      }//for
      if (count==3) {
        winnerIs = checkPlayer;
        // println(checkPlayer +" wins");
        listOfIndexesForPossibleWins_To_Show=tripleCounter;
      }
      tripleCounter++;
    }//for
  }//for
}

void showWinningLine() {
  int tripleCounter=0; 
  strokeWeight(5);
  // loop over all triples 
  for (int[] a : listOfIndexesForPossibleWins) {
    stroke(  255, 0, 0   );
    if (tripleCounter==listOfIndexesForPossibleWins_To_Show) {
      // loop over this triple 
      for (int i : a) {
        column = i % 3;
        row = i / 3;
        PVector pv = new PVector(100 + 200 * column, 100 + 200* row);
        line(pv.x-33, pv.y+63, 
          pv.x+33, pv.y+63);
      }//for
    }//if
    tripleCounter++;
  }//for
  strokeWeight(1);
}

void drawPlayerLabel() {
  String label = "Player 1";

  if (player1Playing == false) {
    label = "Player 2";
  }

  if (itsADraw) {
    label = "D R A W";
  }

  if (winnerIs!=-1) {
    label = "Hit n for a new Game.";
  }

  fill(0);
  textSize(16);
  textAlign(CENTER, BOTTOM);
  text(label, width/2, height - 5);
}

void gameElements() {

  int count = 0; 

  for ( int i = 0; i < moves.length; i++) {
    column = i % 3;
    row = i / 3;

    switch (moves[i]) {
    case 1:  
      new Cross(column, row); // whatever
      break;
    case 2: 
      new Circle(column, row); // whatever
      break;
    }//switch

    if (moves[i]!=0) {
      count++;
    }
  }//for 

  if (count==numMoves) {
    //println ("It's a draw");
    itsADraw=true;
  }
}

// ==============================================================

class Circle {

  int column, row;

  // constr
  Circle(int column, int row) {
    this.column = column;
    this.row = row;

    display(); // whatever
  }// constr

  //Methods
  void display() {
    strokeWeight(10);
    stroke(#6DC5D3);
    fill(255);
    pushMatrix();
    //translate( 100 + column * 200, 100 + row * 200);
    ellipse(100 + 200 * column, 100 + 200* row, 
      100, 100);

    popMatrix();
  }
}

// ==============================================================

class Cross {
  int column, row;

  // constr 
  Cross(int column, int row) {
    this.column = column;
    this.row = row;

    display(); // whatever
  }// constr

  //Methods
  void display() {
    strokeWeight(10);
    stroke(#E37272);

    pushMatrix();
    translate( 100 + column * 200, 100 + row * 200);
    line(- 40, -40, 40, 40);
    line(- 40, 40, 40, -40);

    popMatrix();
  }
}

// ==============================================================

class Grid {

  // NO constr

  //Methods
  void display() {
    strokeWeight(1);
    stroke(0);
    line(width/3, 15, width/3, height - 15);
    line(width/3*2, 25, width/3*2, height - 15);

    line(0, height/3, width, height/3);
    line(0, height/3*2, width, height/3*2);
  }
}
//

I thought tic tac toe cannot be won ?

> Falken and David direct the computer to play tic-tac-toe against itself. This results in a long string of draws, forcing the computer to learn the concept of futility and no-win scenarios. WOPR obtains the launch codes, but before launching, it cycles through all the nuclear war scenarios it has devised, finding that they all result in draws as well. Having discovered the concept of mutual assured destruction (“WINNER: NONE”), the computer tells Falken that it has concluded that nuclear war is “a strange game” in which “the only winning move is not to play.” WOPR relinquishes control of NORAD and the missiles and offers to play “a nice game of chess”.

1 Like
1 Like

Hello,

Please format your code as a courtesy to this community:
https://discourse.processing.org/faq#format-your-code

:)

Alternatively to minmax algorithm you can implement the strategy here: https://en.wikipedia.org/wiki/Tic-tac-toe#Strategy

It’s very hard to program!!

Testing your AI

I recommend building a 2nd random AI; it plays just random.

When you let your two AIs play each other automatically 10.000 times and your strategy AI is perfect, it will never loose. Not once. You can also decide whether your random (not so intelligent) AI or your REAL AI begins a game.

It’s a good test!