ECE 4180 Lab 4 - Magic Square game
  
 
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.
  
 
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.
  
 
Components
Connections
| mbed | uLCD | Touchpad | 
|---|---|---|
| 5V=VU | 5V | |
| Gnd | Gnd | |
| TX=P28 | RX | |
| RX=P27 | TX | |
| P29 | Reset | |
| P9 | SDA | |
| P10 | SCL | |
| P26 | IRQ | 
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
Please log in to post comments.
