/**************************************************************************
//https://www.hackster.io/giobbino/easiest-tictactoe-with-and-without-an-oled-display-f06231 
 *  
 *  TicTacToe  - Serial monitor version.
 *  Note: the OLED version code is better described; if you have any
 *        doubt about any instruction, please take a look to that version.
**************************************************************************/
#include <Servo.h>

#define trigPinLeft 2

#define echoPinLeft 8

#define trigPinRight 12

#define echoPinRight 7

Servo servoleft;

Servo servoright;

int soundleft = 250;

int soundright = 250;
int TestSwitchPin = 2;

int gameStatus = 0;
int whosplaying = 0; //0 = Arduino, 1 = Human 

int winner = -1;  //-1 = Playing, 0 = Draw, 1 = Human, 2 = CPU


int board[]={0,0,0,  
             0,0,0,
             0,0,0}; //0 = blank, 1 = human (circle), 2 = computer (cross)

             





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

void playhuman() {
     
    int humanMove = -1;     
    bool stayInLoop = true;
    
    while (stayInLoop) {
                  
         Serial.println(F("\nMake your move\n"));
    
         while (Serial.available() && Serial.read()); // empty buffer
         while (!Serial.available());                 // wait for data
  
         if (Serial.available()) {  //data available.
          
             int humanMove = Serial.read() - 48;     //serial.read() return the ascii value of the pressed key. The "1" ascii value is 49. 
                          
             Serial.println(humanMove);
             
             if (humanMove >=0 && humanMove <=9) {

                if (board[humanMove-1] !=0) {
                   Serial.println(F("\nError - Cell already in use"));                
                   stayInLoop = true;
                }
                else {
                    stayInLoop = false;                
                    board[humanMove-1] = 1; //remember: the player uses the 1..9 keys, but the array index starts by 0 (9 cells = 0..8)
                }    
             }
             else {
                Serial.println(F("\ntype error (just 1 to 9)"));                
                stayInLoop = true;
             }      
             
         }      
  }

  
 
    
}


//--------------------------------------------------------------------------------------------------------
void playcpu() {
          
     int cpumove = checkboard(2);  //2 = cpu  let's check if there's a cpu's winner move

     if (cpumove >=0) {
        board[cpumove] = 2;    //cpu's winner move
     }
     else {    
         cpumove = checkboard(1);  //1=player check if the player has a chance to win (2 circles and an empty cell in a row)   
         if (cpumove >=0) {  
            board[cpumove] = 2;  //this move will break the player's winner move
         }     
    
        //there's no possible winner move neither for the cpu, nor for the human, I will put an "X" in a random cell
        while (cpumove < 0) {                
           int randomMove = random(10);
           if (randomMove >=0 && randomMove <=8 && board[randomMove] == 0) {
               cpumove = randomMove;
           }        
        }        
        board[cpumove] = 2;
     } 
}


//--------------------------------------------------------------------------------------------------------
int checkboard(int x){   //x = 1 -> player, x = 2 -> cpu

//full case
  
       if (board[0]==0 && board[1]==x && board[2]==x)  return  0;  //  0 1 1 
                                                                   //  . . .
                                                                   //  . . .
                                                                   
  else if (board[0]==x && board[1]==0 && board[2]==x)  return  1;  //  1 0 1 
                                                                   //  . . .
                                                                   //  . . .
                                                                   
  else if (board[0]==x && board[1]==x && board[2]==0)  return  2;  //  1 1 0
                                                                   //  . . .
                                                                   //  . . .                                                                   
  //-------------------------------------------------
  else if (board[3]==0 && board[4]==x && board[5]==x)  return  3;  //  . . .
                                                                   //  0 1 1
                                                                   //  . . .
                                                                     
  else if (board[3]==x && board[4]==0 && board[5]==x)  return  4;  //  . . .  
                                                                   //  1 0 1
                                                                   //  . . .                                                                 

  else if (board[3]==x && board[4]==x && board[5]==0)  return  5;  //  . . .
                                                                   //  1 1 0
                                                                   //  . . .
    //-------------------------------------------------
  else if (board[6]==0 && board[7]==x && board[8]==x)  return  6;  //  . . .
                                                                   //  . . .
                                                                   //  0 1 1
                                                                     
  else if (board[6]==x && board[7]==0 && board[8]==x)  return  7;  //  . . .  
                                                                   //  . . .
                                                                   //  1 0 1

  else if (board[6]==x && board[7]==x && board[8]==0)  return  8;  //  . . .
                                                                   //  . . .
                                                                   //  1 1 0

  //-------------------------------------------------
  else if (board[0]==0 && board[3]==x && board[6]==x)  return  0;  //  0 . .
                                                                   //  1 . .
                                                                   //  1 . .
  
  else if (board[0]==x && board[3]==0 && board[6]==x)  return  3;  //  1 . .
                                                                   //  0 . .
                                                                   //  1 . .
  
  else if (board[0]==x && board[3]==x && board[6]==0)  return  6;  //  1 . .
                                                                   //  1 . .
                                                                   //  0 . .  
                                                                   
  //-------------------------------------------------
  else if (board[1]==0 && board[4]==x && board[7]==x)  return  1;  //  . 0 .
                                                                   //  . 1 .
                                                                   //  . 1 .
  
  else if (board[1]==x && board[4]==0 && board[7]==x)  return  4;  //  . 1 .
                                                                   //  . 0 .
                                                                   //  . 1 .  
  
  else if (board[1]==x && board[4]==x && board[7]==0)  return  7;  //  . 1 .
                                                                   //  . 1 .
                                                                   //  . 0 .  
                                                                    
  //-------------------------------------------------
  else if (board[2]==0 && board[5]==x && board[8]==x)  return  2;  //  . . 0 
                                                                   //  . . 1 
                                                                   //  . . 1 
  
  else if (board[2]==x && board[5]==0 && board[8]==x)  return  5;  //  . . 1 
                                                                   //  . . 0 
                                                                   //  . . 1   
  
  else if (board[2]==x && board[5]==x && board[8]==0)  return  8;  //  . . 1 
                                                                   //  . . 1
                                                                   //  . . 0
                                                                    
  //-------------------------------------------------
  else if (board[0]==0 && board[4]==x && board[8]==x)  return  0;  //  0 . . 
                                                                   //  . 1 . 
                                                                   //  . . 1 
  
  else if (board[0]==x && board[4]==0 && board[8]==x)  return  4;  //  1 . . 
                                                                   //  . 0 .
                                                                   //  . . 1   
  
  else if (board[0]==x && board[4]==x && board[8]==0)  return  8;  //  1 . . 
                                                                   //  . 1 .
                                                                   //  . . 0

  //-------------------------------------------------
  else if (board[2]==0 && board[4]==x && board[6]==x)  return  2;  //  . . 0 
                                                                   //  . 1 . 
                                                                   //  1 . . 

  else if (board[2]==x && board[4]==0 && board[6]==x)  return  4;  //  . . 1 
                                                                   //  . 0 . 
                                                                   //  1 . . 
    
  else if (board[2]==x && board[4]==x && board[6]==0)  return  6;  //  . . 1 
                                                                   //  . 1 . 
                                                                   //  0 . . 
  
  else                                                 return -1;
}


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


void checkWinner() {    //check the board to see if there is a winner

  winner = 3;  //3=draft, 1= winner->player, 2=winner->cpu
    
  // circles win?
       if (board[0]==1 && board[1]==1 && board[2]==1)     winner=1;   
  else if (board[3]==1 && board[4]==1 && board[5]==1)     winner=1;   
  else if (board[6]==1 && board[7]==1 && board[8]==1)     winner=1;     
  else if (board[0]==1 && board[3]==1 && board[6]==1)     winner=1;   
  else if (board[1]==1 && board[4]==1 && board[7]==1)     winner=1;   
  else if (board[2]==1 && board[5]==1 && board[8]==1)     winner=1;     
  else if (board[0]==1 && board[4]==1 && board[8]==1)     winner=1;   
  else if (board[2]==1 && board[4]==1 && board[6]==1)     winner=1; 
    
  // crosses win?
  else if (board[0]==2 && board[1]==2 && board[2]==2)     winner=2;   
  else if (board[3]==2 && board[4]==2 && board[5]==2)     winner=2;   
  else if (board[6]==2 && board[7]==2 && board[8]==2)     winner=2;     
  else if (board[0]==2 && board[3]==2 && board[6]==2)     winner=2;   
  else if (board[1]==2 && board[4]==2 && board[7]==2)     winner=2;   
  else if (board[2]==2 && board[5]==2 && board[8]==2)     winner=2;     
  else if (board[0]==2 && board[4]==2 && board[8]==2)     winner=2;   
  else if (board[2]==2 && board[4]==2 && board[6]==2)     winner=2;   

  if (winner == 3) {      
     for(int i=0;i<9;i++) if (board[i]==0) winner=0;  //there are some empty cell yet. 
  }   
     
 
}

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

void resetGame() {
  Serial.println("Resetting game...");
  for(int i=0;i<9;i++) board[i]=0; 
  winner = 0;
  gameStatus = 0; 
  
}

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

void boardDrawing() {
  
  Serial.println("");
  Serial.print(F("  ")); Serial.print(charBoard(0)); Serial.print(F(" | ")); Serial.print(charBoard(1)); Serial.print(F(" | "));  Serial.println(charBoard(2)); 
  Serial.println(F(" ---+---+---")); 
  Serial.print(F("  ")); Serial.print(charBoard(3)); Serial.print(F(" | ")); Serial.print(charBoard(4)); Serial.print(F(" | "));  Serial.println(charBoard(5)); 
  Serial.println(F(" ---+---+---")); 
  Serial.print(F("  ")); Serial.print(charBoard(6)); Serial.print(F(" | ")); Serial.print(charBoard(7)); Serial.print(F(" | "));  Serial.println(charBoard(8)); 
  Serial.println("");
  
}



//--------------------------------------------------------------------------------------------------------------
String charBoard(int x) {
       if (board[x] == 0) return " ";       
       if (board[x] == 1) return "o";
       if (board[x] == 2) return "x";  

       return "?";  //error trap; it shouldn't pass here.
}


//--------------------------------------------------------------------------------------------------------------
void setup() {
  
  Serial.begin(9600);
    
  randomSeed(analogRead(0));  //resetting the random function.

  pinMode(A0, INPUT);

pinMode(trigPinLeft, OUTPUT);

pinMode(echoPinLeft, INPUT);

pinMode(trigPinRight, OUTPUT);

pinMode(echoPinRight, INPUT);

servoleft.attach(6);

servoright.attach(5);


}


//--------------------------------------------------------------------------------------------------------------
void loop() {
 long durationLeft, distanceLeft, durationRight, distanceRight;

digitalWrite(trigPinLeft, LOW);

delayMicroseconds(2);

digitalWrite(trigPinLeft, HIGH);

delayMicroseconds(10);

digitalWrite(trigPinLeft, LOW);

durationLeft = pulseIn(echoPinLeft, HIGH);

distanceLeft = (durationLeft/2) / 29.1; 
servoleft.write(90);

// RIGHT SIDE 
digitalWrite(trigPinRight, LOW);

delayMicroseconds(2);

digitalWrite(trigPinRight, HIGH);

delayMicroseconds(10);

digitalWrite(trigPinRight, LOW);

durationRight = pulseIn(echoPinRight, HIGH);

distanceRight = (durationRight/2) / 29.1; 
servoright.write(90);




if (distanceLeft<10) {

servoleft.write(60); 
servoright.write(60);
}


//RIGHT SIDE DETECTION 

if (distanceRight<10) {

servoleft.write(109); 
servoright.write(109);
}




else {


}

delay(500);






  int lightRead = analogRead(A0);
  //Serial.println(lightRead); #print photoresistor value
  if (lightRead > 600){ //Start game if light is covered, using 10 kOhm resisor 
                
  if (gameStatus == 0){     
    Serial.println(F("A game for those who seek to find / a way to leave their world behind. The first player to reach the end wins. \nAdventurers beware: do not begin unless you intend to finish...."));  
    
    whosplaying = 2;
    while ( whosplaying <0 || whosplaying > 1) {
         whosplaying = random(2);  
    }

    gameStatus = 1;
    winner = 0;
  }

  //---------------------------------------------
  
  if (gameStatus == 1){   //start

      if (whosplaying == 1) boardDrawing();
      
      
      while (winner == 0) {  //game main loop
                       
        if (whosplaying == 0) { 
          Serial.println("CPU turn:");    
          playcpu();  
          whosplaying =1; 
        }
        else { 
          Serial.println("Player turn:"); 
          playhuman(); 
          whosplaying =0; 
          
          
        }

        boardDrawing();
        checkWinner();  //this will assign the winner variable

         if (winner > 0) {
            Serial.println("");
            if (winner == 3) Serial.print(F("Tie!"));
            else {
                Serial.print(F("JUMANJI   "));
                if (winner == 1) Serial.println(F("the human")); else Serial.println(F("the CPU")); 
            }               
                     
         }
        
      }
      resetGame();      
      Serial.println("");
      delay(2000);
      Serial.println("");
      Serial.flush();
  }
  
  
}

}



 
