Computer Constantly Taking Turn in Tic-Tac-Toe Game

Hello again! I’m trying to make a tic tac toe game against a computer, where the user enters their choice using number inputs instead of mouseclicks. Edit, I’ve gotten the computer to stop constantly taking its turn, but now player input is returning the “Incorrect key pressed! Please select an empty space.” error every time the player makes a move. Additionally, if the computer hits a full space, it does not reroll until it finds an empty space. How do I fix this?


void setup() {
  size(500, 500);
  background(255, 255, 255);
  ticTacToeBoard();
  nestedForLoopToPopulateGameBoard();
  System.out.println("Press a number from 0 to 8");

}

void draw() {
  if(keyPressed == true){    
      keyPressed();
      keyReleased(); 
      delay(100);
      gameLogic();
  }
} 



Random randomizer = new Random();
  
void nestedForLoopToPopulateGameBoard() {
   for(int row = 0; row<3; row++)
     for(int col = 0; col<3; col++)
       gameBoard[row][col] = ' ';
}
      
void gameLogic() {  
    computerMove = new Random().nextInt(9+1);
    
  //if(playerCurrentTurn == false){
        switch(computerMove) {
    case 1:
    if(gameBoard[0][0] != moveTokenO)
      if(gameBoard[0][0] != moveTokenX) {
         strokeWeight(2);
         line(0,0,165,165);
         line(165,0,0,165);
       gameBoard[0][0] = moveTokenX;
       System.out.println(gameBoard[0][0]);
        } else { 
         gameLogic();
       }
       break;
     case 2:
     if(gameBoard[0][1] != moveTokenO) 
       if(gameBoard[0][1] != moveTokenX) {
         strokeWeight(2);
         line(165,0,330,165);
         line(330,0,165,165);
       gameBoard[0][1] = moveTokenX;
       System.out.println(gameBoard[0][1]);
         } else { 
         gameLogic();
       }
       break;
    case 3:
    if(gameBoard[0][2] != moveTokenO) 
      if(gameBoard[0][2] != moveTokenX) {
         strokeWeight(2);
         line(330,0,500,165);
         line(500,0,330,165);
       gameBoard[0][2] = moveTokenX;
       System.out.println(gameBoard[0][2]);
        } else { 
         gameLogic();
       }
       break;
    case 4:
    if(gameBoard[1][0] != moveTokenO) 
    if(gameBoard[1][0] != moveTokenX) {
         strokeWeight(2);
         line(0,165,165,330);
         line(165,165,0,330);
       gameBoard[1][0] = moveTokenX;
       System.out.println(gameBoard[1][0]);
        } else { 
         gameLogic();
       }
       break;
    case 5:
    if(gameBoard[1][1] != moveTokenO) 
    if(gameBoard[1][1] != moveTokenX) {
         strokeWeight(2);
         line(165,165,330,330);
         line(330,165,165,330);
         gameBoard[1][1] = moveTokenX;
       System.out.println(gameBoard[1][1]);
        } else { 
         gameLogic();
       }
       break;
    case 6:
    if(gameBoard[1][2] != moveTokenO) 
      if(gameBoard[1][2] != moveTokenX) {
         strokeWeight(2);
         line(330,165,500,330);
         line(500,165,330,330);
       gameBoard[1][2] = moveTokenX;
       System.out.println(gameBoard[1][2]);
        } else { 
         gameLogic();
       }
       break;
    case 7:
    if(gameBoard[2][0] != moveTokenO) 
    if(gameBoard[2][0] != moveTokenX) {
         strokeWeight(2);
         line(165,330,0,500);
         line(0,330,165,500);
       gameBoard[2][0] = moveTokenX;
       System.out.println(gameBoard[2][0]);
        } else { 
         gameLogic();
       }
       break;
    case 8:
    if(gameBoard[2][1] != moveTokenO)
    if(gameBoard[2][1] != moveTokenX) {
         strokeWeight(2);
         line(165,330,330,500);
         line(330,330,165,500);
       gameBoard[2][1] = moveTokenX;
       System.out.println(gameBoard[2][1]);
        } else { 
         gameLogic();
       }
       break;
    case 9:
    if(gameBoard[2][2] != moveTokenO) 
    if(gameBoard[2][2] != moveTokenX) {
         strokeWeight(2);
         line(500,330,330,500);
         line(330,330,500,500);
       gameBoard[2][2] = moveTokenX;
       System.out.println(gameBoard[2][2]);
        } else { 
         gameLogic();
       }
       break;
  }    
  System.out.println(computerMove); 
  
     }
  
void keyPressed() {
  circle = createShape(ELLIPSE, 70, 70, 150, 150);
 //if(playerCurrentTurn == true) {
 if(keyPressed == true)
  switch(key) {
    case '0':
       if(gameBoard[0][0] != moveTokenX) {
             if(gameBoard[0][0] != moveTokenO){
         gameBoard[0][0] = moveTokenO;
       shape(circle, 10, 10);
       System.out.println(gameBoard[0][0]);
       delay(50);
             }
       } else { 
         println("Incorrect key pressed! Please select an empty space.");
       }
       break;
    case '1':
    if(gameBoard[0][1] != moveTokenX) 
      if(gameBoard[0][1] != moveTokenO){
       gameBoard[0][1] = moveTokenO;
       shape(circle, 180, 10);
       System.out.println(gameBoard[0][1]);
       delay(50);
    } else { 
         println("Incorrect key pressed! Please select an empty space.");
       }
       break;
    case '2':
    if(gameBoard[0][2] != moveTokenX) 
          if(gameBoard[0][2] != moveTokenO){
       gameBoard[0][2] = moveTokenO;
       shape(circle, 350, 10);
       System.out.println(gameBoard[0][2]);
       delay(50);
    } else { 
         println("Incorrect key pressed! Please select an empty space.");
       }
       break;
    case '3':
        if(gameBoard[1][0] != moveTokenX) 
              if(gameBoard[1][0] != moveTokenO){
       gameBoard[1][0] = moveTokenO;
       shape(circle, 10, 180);
       System.out.println(gameBoard[1][0]);
       delay(50);
        } else { 
         println("Incorrect key pressed! Please select an empty space.");
       }
       break;
    case '4':
       if(gameBoard[1][1] != moveTokenX) 
             if(gameBoard[1][1] != moveTokenO){
       gameBoard[1][1] = moveTokenO;
       shape(circle, 180, 180);
       System.out.println(gameBoard[1][1]);
       delay(50);
       } else { 
         println("Incorrect key pressed! Please select an empty space.");
       }
       break;
    case '5':
       if(gameBoard[1][2] != moveTokenX) 
             if(gameBoard[1][2] != moveTokenO){
       gameBoard[1][2] = moveTokenO;
       shape(circle, 350, 180);
       System.out.println(gameBoard[1][2]);
       delay(50);
       } else { 
         println("Incorrect key pressed! Please select an empty space.");
       }
       break;
    case '6':
       if(gameBoard[2][0] != moveTokenX) 
             if(gameBoard[2][0] != moveTokenO){
       gameBoard[2][0] = moveTokenO;
       shape(circle, 10, 350);
       System.out.println(gameBoard[2][0]);
       delay(50);
       } else { 
         println("Incorrect key pressed! Please select an empty space.");
       }
       break;
    case '7':
       if(gameBoard[2][1] != moveTokenX) 
             if(gameBoard[2][1] != moveTokenO){
       gameBoard[2][1] = moveTokenO;
       shape(circle, 180, 350);
       System.out.println(gameBoard[2][1]);
       delay(50);
       } else { 
         println("Incorrect key pressed! Please select an empty space.");
       }
       break;
    case '8':
       if(gameBoard[2][2] != moveTokenX) 
             if(gameBoard[2][2] != moveTokenO){
       gameBoard[2][2] = moveTokenO;
       shape(circle, 350, 350);
       System.out.println(gameBoard[2][2]);
       delay(50);
       } else { 
         println("Incorrect key pressed! Please select an empty space.");
       }
       break;
    default:   // catches numbers outside of 0-8
       println("Incorrect key pressed! Please select a key between 0-8"); 
       delay(50);
       break;  
  }
}
//}

void keyReleased() {
  playerCurrentTurn = true;
  delay(50);
  playerCurrentTurn = false;
  delay(5);

}

A few points here.

    keyPressed();
    keyReleased();

both get called automatically.

So no need to call them in draw().

The line if (keyPressed == true) {
is not needed because the funcs get called only when a key is pressed anyway.

I suggest

void draw() {
  background(255, 255, 255);
  delay(100);
  if (PC_MOVE)
    gameLogic();
  ticTacToeBoard();
}

The new var PC_MOVE is a boolean that is true or false. It indicates whether the human or the PC has to move.

declare it before setup() like boolean PC_MOVE = true;

  • After each successful human move please say PC_MOVE = true;
  • After each successful PC move please say PC_MOVE = false;

(technically, gameLogic is not the correct term, better pcMove() or ai_move())

Reroll

I think with my logic this is solved because draw() runs on and on so gameLogic() is called again and again until PC_MOVE == false.

But let me explain within your attempt:

You attempt to call gameLogic() from gameLogic() which is neat (recursive).

When you look closely at your if-clause in gameLogic(), there is an error though :

Since the first if has no { bracket, the entire block hangs on the first if.
When you would add the brackets it’d read:

    if(gameBoard[1][0] != moveTokenO) {
        if(gameBoard[1][0] != moveTokenX) {
                 do something
            } else { 
             gameLogic();
           }//else
    }//outer if
       break;

Now you can see that the “else gameLogic()”-section applies only to the inner if-clause and not to the outer one.

Hence,gameLogic() is only called when the outer if is true, and the inner if is false. Not when the outer if is false. Bad.

A fix: Give the outer if-clause its own else block:

    if(gameBoard[1][0] != moveTokenO) {
        if(gameBoard[1][0] != moveTokenX) {
                 do something
            } else { 
             gameLogic();
           }
    } else { 
             gameLogic();
    }
    break;

OR use && in the first place. AND

    if(gameBoard[1][0] != moveTokenO && 
        gameBoard[1][0] != moveTokenX) {
                 do something
            } else { 
             gameLogic();
           }
       break;

There are several other ways.
For example set a flag boolean moveSuccessful=false; and after the entire switch() section say

if(moveSuccessful == false) {
   gameLogic();
}

So you can get rid of all other else-gameLogic()-clauses in the function.

Remark 1

  • please use ctrl-t when programming, auto indents. Especially before posting in the forum.

  • please always post a runnable version of your Sketch so that we can check it

Remark 2

in the func keyPressed() this is not needed: if (keyPressed == true)

Chrisir

1 Like