Thursday, February 28, 2013

Rock, Paper, Scissors


We had an assignment to make a rock, paper, scissors game with the RGB LED.
R beats G
G beats B
B beats R

We were to use Serial communication to play with another person in class
I played with Laura so that we could test the entire communication protocol.
I had one bug that gave me a lot of problems which was that I was not delaying long
enough when trying to receive more than one character in a row as in "GGG"
I was not giving the buffer long enough to actually receive all of the data

Here is a schematic of my arduino board for this project (These are the exact pin #'s used)


And here is my code. I used a header file to organize my code and so that I could use enumerations which seem to have a slight problem in Arduino:

//functions.h


#include "Arduino.h"

HardwareSerial& s = Serial1;

const byte R_rock = 10;
const byte G_paper = 8;
const byte B_scissors = 9;

const byte R_stat = 7;
const byte G_stat = 6;
const byte B_stat = 5;

const byte pot_pin = A8;
int pot_val = 0;

const byte switch_pin = 2;
int prev_switch_val = 0;
int switch_val = 0;

int R_val = 0;
int G_val = 0;
int B_val = 0;

int R_stat_val = 0;
int G_stat_val = 0;
int B_stat_val = 0;

int state = 0;
enum Color{ RED, GREEN, BLUE };

Color my_choice  = RED;
Color opponent_choice = RED;


void set_rps_color()
{
  pot_val = analogRead(pot_pin);    // read the potentiometer to determine color choice
 
  if(pot_val < 413)
  {
    R_val = 255;
    G_val = 0;
    B_val = 0;
  }
  else if(pot_val < 827)
  {
    R_val = 0;
    G_val = 255;
    B_val = 0;
  }
  else
  {
    R_val = 0;
    G_val = 0;
    B_val = 255;
 
  }
}

//be careful with this...not listening to this all the time...
boolean switch_pressed()
{
  prev_switch_val = switch_val;
  switch_val = digitalRead(switch_pin);
  //Serial.print(prev_switch_val);Serial.print(" ");
  //Serial.println(switch_val);
  if(prev_switch_val==0 && switch_val==1)
  {
    return true;
  }
  return false;
}

int determine_winner(enum Color me,enum Color opponent)
{
  int test = (3+((int)me-(int)opponent))%3;
  if(test == 2)
  {
    //I win
    R_stat_val = 0;
    G_stat_val = 255;
    B_stat_val = 0;
  }
  else if(test == 1)
  {
    //They win
    R_stat_val = 255;
    G_stat_val = 0;
    B_stat_val = 0;
  }
  else if(test == 0)
  {
    //tie
    R_stat_val = 175;
    G_stat_val = 255;
    B_stat_val = 0;
  }
  return test;
}

int get_opponent()
{
  //need to read 3 times and construct a string?
  if(s.available() > 0)
  {
     char incomingByte = s.read();
   
    if(incomingByte == 'R') opponent_choice = RED;
    else if(incomingByte == 'G') opponent_choice = GREEN;
    else if(incomingByte == 'B') opponent_choice = BLUE;
    else return -1;
  }
  else
  {
    return -1;
  }
 
  return int(opponent_choice);
}

int send_choice()
{
  if(R_val == 255) {s.write("R"); my_choice = RED; return 0;}
  else if(G_val == 255) {s.write("G"); my_choice = GREEN; return 1;}
  else if(B_val == 255) {s.write("B"); my_choice = BLUE; return 2;}
  else return -1;
}

void set_stat_color(int R, int G, int B)
{
  R_stat_val = R;
  G_stat_val = G;
  B_stat_val = B;
}

//
// i is 1 for the first reset  => send ZZZ
// i is 2 for the second reset => send XXX
//
int send_reset(int i)
{
  if(i==1) {s.write("ZZZ"); }
  else if(i==2) {s.write("XXX");}
  else return -1;
}

//
// i is 1 for the first reset  => listening for ZZZ
// i is 2 for the second reset => listening for XXX
//
bool listen_for_reset(int i)
{
  String inData = "   ";
  int index = 0;
  char inChar;
 
  if(i==1)
  {
    //Serial.println("Wont work without this print for some weird crazy reason");
    while(s.available() > 0)
    {
      //Serial.println("Serial data available");
       inChar = s.read();
       if(index < 3)
       {
         inData[index]=inChar;
         index++;  
       }
       delay(10);
    }
   
    //inData.trim();
    if(inData == "ZZZ" || inData == "zzz")
    {
      return true;
    }
  }
  else if(i==2)
  {
       //Serial.println("Wont work without this print for some weird crazy reason");
    while(s.available() > 0)
    {
       inChar = s.read();
       if(index < 3)
       {
         inData[index]=inChar;
         index++;  
       }
       delay(10);
    }
   
    //inData.trim();
    if(inData == "XXX" || inData == "xxx")
    {
      return true;
    }  
  }
  return false;
}


//main file


#include "functions.h"

// the setup routine runs once when you press reset:
void setup() {              
  // initialize the digital pin as an output.
  pinMode(R_rock, OUTPUT);
  pinMode(G_paper, OUTPUT);
  pinMode(B_scissors, OUTPUT);

  pinMode(R_stat, OUTPUT);
  pinMode(G_stat, OUTPUT);
  pinMode(B_stat, OUTPUT);

  pinMode(pot_pin, INPUT);
  pinMode(switch_pin, INPUT);

 s.begin(9600);
 Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
 
  switch (state){
    case 0:
            //Waiting for someone to press "reset"
            if(switch_pressed())
            {
               send_reset(1); //send the first reset signal
               set_stat_color(0,0,255); //set status to blue
               state ++; //advance state to wait for opponent
               break;
            }
            else if(listen_for_reset(1))
            { //opponent pressed reset
              set_stat_color(0,0,255); //set status color to blue
              state+=2; //advance state to wait for me to press reset
              break;
            }
            break;
    case 1:
            //waiting for opponent to press reset
            if(listen_for_reset(1))
            {
              set_stat_color(155,0,255);//set status color to magenta
              state+=2;//advance state to choose color
              break;
            }
            break;
    case 2:
            //waiting for me to press reset
            if(switch_pressed())
            {
              send_reset(1);//send the first reset signal
              set_stat_color(155,0,255);
              state++; //advance state to choose color
              break;
            }
            break;      
    case 3:
            //Allow our player to select color
            set_rps_color(); //can change color as much as we want
            if(switch_pressed()) //when done press switch
            {
              send_choice();
              set_stat_color(155,255,255);//set stat color to signify I have chosen
              state++;//advance state to wait on opponent
              break;
            }
            if(get_opponent()>=0)//also listen for opponent choice
            {
              set_stat_color(0,255,255);//set stat color to signal opp chose and is waiting on me
              state+=2;//advance state for opp to wait on me
              break;
            }
            break;
     case 4:
            //Serial.println("In case 4");
            //Wait for other player to select color
            if(get_opponent()>=0)
            {
              set_stat_color(0,255,255); //set stat color
              state+=2; //advance state to determine winner
            }
            break;
      case 5:
            //Opponent is waiting on me to choose
            set_rps_color(); //can change color as much as we want
            if(switch_pressed())
            {
              send_choice();
              set_stat_color(155,255,255);//set stat color to signify I have chosen
              state++; //advance state to determine winner
            }
            break;
      case 6:
            //determine winner
            determine_winner(my_choice,opponent_choice); //This sets the stat light color
            state++; //advance state to wait for reset
            break;
      case 7:
            //Either opponent or I must press reset to start over
            if( switch_pressed() || listen_for_reset(2))
            {
              send_reset(2); //send the second reset
             
              //Clean up
              R_stat_val = 0;
              G_stat_val = 0;
              B_stat_val = 0;
           
              R_val = 0;
              G_val = 0;
              B_val = 0;
         
              //Start back at case 0
              state = 0;
          }
  }
           
   analogWrite(R_rock,R_val);
   analogWrite(G_paper,G_val);
   analogWrite(B_scissors,B_val);
 
   analogWrite(R_stat,R_stat_val);
   analogWrite(G_stat,G_stat_val);
   analogWrite(B_stat,B_stat_val);

}


No comments:

Post a Comment