ECE 4180 Lab 4 - Magic Square game

/media/uploads/jsobchuk3/20141020_192325.jpg

Overview

Dhru Desai and I made a simple "magic square" game using the 12-key touchpad for input controls and the uLCD as output. The object of the game is to illuminate all nine lights using a combination of button presses. Each button corresponds to one light, and pressing a button toggles its light as well as some of the lights around it. The effects of pressing a corner, side, or middle button are shown in the picture below. The actual button pressed is represented by the red light, while the blue lights represent the other affected spaces.

/media/uploads/jsobchuk3/square.png

Implementation

The game begins with all lights off when the mbed is powered up. If the player successfully illuminates all nine lights, a congratulatory message is displayed. After a victory, the board is reset to a random configuration. The player can also reset the board by pressing the '0' key.

The following picture shows the mapping of the keys to the lights.

/media/uploads/jsobchuk3/20141020_192309.jpg

Components

Connections

mbeduLCDTouchpad
5V=VU5V
GndGnd
TX=P28RX
RX=P27TX
P29Reset
P9SDA
P10SCL
P26IRQ

Remember to put pull-up resistors to Vout on the SDA and SCL lines

Program

Import programTouchPuzzle_full

4180 Lab 4 v1.0

Code

Touch Puzzle main.cpp

/*
Dhruvin Desai and Joseph Sobchuk

fallInterrupt() and API for mpr121 written by Anthony Buckton in 2011
*/

#include <mbed.h>
#include <mpr121.h> // Thanks to Anthony Buckton
#include "uLCD_4DGL.h"
 
uLCD_4DGL uLCD(p28,p27,p29);

// Create the interrupt receiver object on pin 26
InterruptIn interrupt(p26);

// Setup the i2c bus on pins 9 and 10
I2C i2c(p9, p10);

// Setup the Mpr121:
// constructor(i2c object, i2c address of the mpr121)
Mpr121 mpr121(&i2c, Mpr121::ADD_VSS);

int on [9] = {0,0,0,0,0,0,0,0,0};
int key;
int radius = 15;
int initpos = 23; // Initial x and y shift from the edge of the display
int shift = 40; // Space in between each circle

// Function to invert any specified circle
void invert(int on [9], int circleN) {
  switch (circleN) {
  
  case 1: 
    if (on[0] == 0) { // If circle 1 is off then Fill 1st Circle
        uLCD.filled_circle(initpos, initpos, radius, RED); // Fill 1st Circle
        on[0] = 1; // Then change status of circle 1 to on
    }
    else if (on[0] == 1) { // If circle 1 is on then erase 1st circle
        uLCD.filled_circle(initpos, initpos, radius, BLACK); 
        uLCD.circle(initpos, initpos, radius, RED); // Erase 1st Circle
        on[0] = 0;
    }        
    break;  
  
  case 2:
      if (on[1] == 0) {
        uLCD.filled_circle(initpos + shift, initpos, radius, RED); // Fill 2nd Circle
        on[1] = 1;
      }
    
      else if (on[1] == 1) {
        uLCD.filled_circle(initpos + shift, initpos, radius, BLACK);
        uLCD.circle(initpos + shift, initpos, radius, RED); // Erase 2nd Circle        
        on[1] = 0;
      } 
      break;
  
  
  case 3:
      if (on[2] == 0) {
        uLCD.filled_circle(initpos + 2*shift, initpos, radius, RED);
        on[2] = 1;
      }
      else if (on[2] == 1) {
        uLCD.filled_circle(initpos + 2*shift, initpos, radius, BLACK);
        uLCD.circle(initpos + 2*shift, initpos, radius, RED);
        on[2] = 0;
      } 
      break;
  
  
  case 4:
     if (on[3] == 0) {
        uLCD.filled_circle(initpos, initpos + shift, radius, RED); // Fill 4th Circle
        on[3] = 1;
      }
    
      else if (on[3] == 1) {
        uLCD.filled_circle(initpos, initpos + shift, radius, BLACK);
        uLCD.circle(initpos, initpos + shift, radius, RED); // Erase 4th Circle                     
        on[3] = 0;
      }
      break;
  
  case 5:
      if (on[4] == 0) {
        uLCD.filled_circle(initpos + shift, initpos + shift, radius, RED); // Fill 5th Circle
        on[4] = 1;
      }
    
      else if (on[4] == 1) {
        uLCD.filled_circle(initpos + shift, initpos + shift, radius, BLACK);
        uLCD.circle(initpos + shift, initpos + shift, radius, RED); // Erase 5th Circle           
        on[4] = 0;
      }
      break;
  
  case 6: 
      if (on[5] == 0) {
        uLCD.filled_circle(initpos + 2*shift, initpos + shift, radius, RED); // Fill 6th Circle
        on[5] = 1;
      }
    
      else if (on[5] == 1) {
        uLCD.filled_circle(initpos + 2*shift, initpos + shift, radius, BLACK);
        uLCD.circle(initpos + 2*shift, initpos + shift, radius, RED); // Erase 6th Circle                
        on[5] = 0;
      }
      break;
      
  
  
  case 7: 
      if (on[6] == 0) {
        uLCD.filled_circle(initpos, initpos + 2*shift, radius, RED); // Fill 7th Circle
        on[6] = 1;
      }
    
      else if (on[6] == 1) {
        uLCD.filled_circle(initpos, initpos + 2*shift, radius, BLACK); // Erase 7th Circle
        uLCD.circle(initpos, initpos + 2*shift, radius, RED);         
        on[6] = 0;
      }
      break;
     
  
  
  case 8: 
      if (on[7] == 0) {
        uLCD.filled_circle(initpos + shift, initpos + 2*shift, radius, RED); // Fill 8th Circle
        on[7] = 1;
      }
    
      else if (on[7] == 1) {
        uLCD.filled_circle(initpos + shift, initpos + 2*shift, radius, BLACK); // Erase 8th Circle
        uLCD.circle(initpos + shift, initpos + 2*shift, radius, RED);        
        on[7] = 0;
      }
      break;
      
  
  
  case 9: 
      if (on[8] == 0) {
        uLCD.filled_circle(initpos + 2*shift, initpos + 2*shift, radius, RED); // Fill 9th Circle
        on[8] = 1;
      }
    
      else if (on[8] == 1) {
        uLCD.filled_circle(initpos + 2*shift, initpos + 2*shift, radius, BLACK);
        uLCD.circle(initpos + 2*shift, initpos + 2*shift, radius, RED); // Erase 9th Circle        
        on[8] = 0;
      }
      break;
      
    
}
} 

void pushButton(int on [9],int key_code) {
   // The winning combination of buttons is 0,2,4,8 (1,3,5,9 in key_codes)
   // The rest of the buttons are programmed to give bogus combinations to confuse the player, but one of them might coincidently win the game.
   switch (key_code) {
   
   case 2:
        invert(on,7);
        invert(on,4);
        invert(on,5);
        invert(on,8);
        break; 
   
   case 3:
        invert(on,7);
        invert(on,4);
        invert(on,1);
        break;
   
   case 4:
        invert(on,2);
        invert(on,4);
        invert(on,5);
        invert(on,1);
        break;
   
   case 6:
        invert(on,9);
        invert(on,7);
        invert(on,8);
        break;
   
   case 7:
        invert(on,2);
        invert(on,5);
        invert(on,4);
        invert(on,8);
        invert(on,6);
        break;
   
   case 8:
        invert(on,1);
        invert(on,2);
        invert(on,3);
        break;
   
   case 10:
        invert(on,8);
        invert(on,9);
        invert(on,5);
        invert(on,6);
        break;
   
   case 11:
        invert(on,9);
        invert(on,6);
        invert(on,3);
        break;
        
   case 12:
        invert(on,2);
        invert(on,3);
        invert(on,6);
        invert(on,5);
        break;
}   
}





// Key hit/release interrupt routine thanks to Anthony Buckton
void fallInterrupt() {
  int key_code = 0;
  int i = 0;
  int value = mpr121.read(0x00);
  value += mpr121.read(0x01) << 8;
  // LED demo mod
  i = 0;
  // puts key number out to LEDs for demo
  for (i=0; i<12; i++) {
      if (((value>>i)&0x01)==1) {
          key_code=i+1;
      }    
  }
  key = key_code;
}


 
int main() {
  int j;
  uLCD.rectangle(0,0,127,127,WHITE); // Draw border
  // Draw empty circles in correct positions
  uLCD.circle(initpos, initpos, radius, RED);
  uLCD.circle(initpos + shift, initpos, radius, RED);
  uLCD.circle(initpos + 2*shift, initpos, radius, RED);
  uLCD.circle(initpos, initpos + shift, radius, RED);
  uLCD.circle(initpos + shift, initpos + shift, radius, RED);
  uLCD.circle(initpos + 2*shift, initpos + shift, radius, RED);
  uLCD.circle(initpos, initpos + 2*shift, radius, RED);
  uLCD.circle(initpos + shift, initpos + 2*shift, radius, RED);
  uLCD.circle(initpos + 2*shift, initpos + 2*shift, radius, RED);
  
  interrupt.fall(&fallInterrupt);
  interrupt.mode(PullUp); 
  while (1) {
      // Call pushButton once button is pressed by passing the key of the button pushed and the status of the circles
      if(key != 0) {
        pushButton(on, key);
        if(key != 1)key = 0;
      }
      // If all circles are filled, then print You win!!! Reset the mbed
      if (key == 1 || (on[0] && on[1] && on[2] && on[3] && on[4] && on[5] && on[6] && on[7] && on[8])) {
        uLCD.locate(5,5);
        if(key != 1) uLCD.printf("You Win!!!");
        uLCD.locate(0,7);
        uLCD.printf("Resetting the game");
        wait(3);
        
        for (j = 0; j < 9; j++) {
            on[j] = rand() % 2;
        }
        uLCD.filled_rectangle(0,0,127,127,BLACK);// Erase Everything
        
        uLCD.rectangle(0,0,127,127,WHITE); // Draw border
        
        
        // Draw empty circles in correct positions
        uLCD.circle(initpos, initpos, radius, RED);
        uLCD.circle(initpos + shift, initpos, radius, RED);
        uLCD.circle(initpos + 2*shift, initpos, radius, RED);
        uLCD.circle(initpos, initpos + shift, radius, RED);
        uLCD.circle(initpos + shift, initpos + shift, radius, RED);
        uLCD.circle(initpos + 2*shift, initpos + shift, radius, RED);
        uLCD.circle(initpos, initpos + 2*shift, radius, RED);
        uLCD.circle(initpos + shift, initpos + 2*shift, radius, RED);
        uLCD.circle(initpos + 2*shift, initpos + 2*shift, radius, RED);
        
        //Make sure they match the array
        for(j = 0; j < 9; j++) {
            invert(on,j);
        }
        
      }    
      //wait(0.2); // Used wait to eliminate multiple presses of button. <- Done somewhere else
  }
}

Demonstration

/media/uploads/jsobchuk3/4180lab4.wmv


Please log in to post comments.