ECE 4180 Spring 2016 Lab 4

Dependencies:   Memory_Card_Game SDFileSystem mbed

Dependents:   Memory_Card_Game

Revision:
0:5b9b9c78552d
Child:
2:9a3154ce8b51
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Mar 14 02:16:45 2016 +0000
@@ -0,0 +1,259 @@
+#include "mbed.h"
+#include "SDFileSystem.h"
+#include "uLCD_4DGL.h"
+#include "wave_player.h"
+//#include <time.h>
+//#include "Nav_Switch.h"
+
+AnalogOut DACout(p18);          // used to play sound on speaker
+wave_player waver(&DACout);     //wave player plays a *.wav file to D/A and a PWM
+uLCD_4DGL uLCD(p28,p27,p30);    // serial tx, serial rx, reset pin;
+SDFileSystem sd(p11, p12, p13, p14, "sd"); //SD card setup
+
+// Function to play wav file
+void playSound(char * wav);
+void playSound(char * wav)
+{
+    // open wav file
+    FILE *wave_file;
+    wave_file=fopen(wav,"r");
+
+    // play wav file
+    waver.play(wave_file);
+
+    // close wav file
+    fclose(wave_file);
+}
+
+// Navigation switch class
+class Nav_Switch
+{
+public:
+    Nav_Switch(PinName up,PinName down,PinName left,PinName right,PinName fire);
+    int read();
+//boolean functions to test each switch
+    bool up();
+    bool down();
+    bool left();
+    bool right();
+    bool fire();
+//automatic read on RHS
+    operator int ();
+//index to any switch array style
+    bool operator[](int index) {
+        return _pins[index];
+    };
+private:
+    BusIn _pins;
+ 
+};
+Nav_Switch::Nav_Switch (PinName up,PinName down,PinName left,PinName right,PinName fire):
+    _pins(up, down, left, right, fire)
+{
+    _pins.mode(PullUp); //needed if pullups not on board or a bare nav switch is used - delete otherwise
+    wait(0.001); //delays just a bit for pullups to pull inputs high
+}
+inline bool Nav_Switch::up()
+{
+    return !(_pins[0]);
+}
+inline bool Nav_Switch::down()
+{
+    return !(_pins[1]);
+}
+inline bool Nav_Switch::left()
+{
+    return !(_pins[2]);
+}
+inline bool Nav_Switch::right()
+{
+    return !(_pins[3]);
+}
+inline bool Nav_Switch::fire()
+{
+    return !(_pins[4]);
+}
+inline int Nav_Switch::read()
+{
+    return _pins.read();
+}
+inline Nav_Switch::operator int ()
+{
+    return _pins.read();
+}
+
+ //up, down, left, right, center
+ Nav_Switch myNav( p8, p6, p7, p5, p17);
+
+Timer t;
+
+// Game Variables
+const int BLOCK_SIDE = 29;  // side of card
+const int BUFFER = 5;       // space between cards
+const int NUM_ROWS = 4;     // num of rows and also columns since it's a square grid
+int score = 0;              // initialize score
+float time_limit = 60.0;    // set time limit
+
+bool start_game = 1;        // Determines if it is the start of the game
+typedef enum {
+    red_circle, blue_circle, green_circle, pink_circle, red_square, blue_square, green_square, pink_square
+    } shapes;
+int final_shapes[4][4] = {red_circle, blue_circle, green_circle, pink_circle, red_square, blue_square, green_square, pink_square, red_circle, blue_circle, green_circle, pink_circle, red_square, blue_square, green_square, pink_square};
+int temp_shape; // temp shape array
+int block_arr[NUM_ROWS][NUM_ROWS] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+int current_x = 0;
+int current_y = 0;
+int prev_x = 0;
+int prev_y = 0; 
+int num_flips = 0;
+int current_shape = 0;
+int prev_shape = 0;
+int k = 0;
+int main() {
+    t.start();
+    while(score<8 && t.read() < time_limit) {
+        if (start_game) {
+            //set_time(1256729737);
+            srand(time(0)); // create random seed so rand() will generate new random numbers each time
+            for (int i = 0; i < NUM_ROWS; i++ ) {
+                for (int j = 0; j < NUM_ROWS; j++ ) {
+                    // randomize elements within the array using "shuffle" algorithm
+                    int rand_x = rand() % 4;
+                    int rand_y = rand() % 4;
+                    int temp = final_shapes[i][j];
+                    final_shapes[i][j] = final_shapes[rand_x][rand_y];
+                    final_shapes[rand_x][rand_y] = temp;
+                    
+                    // draw all white blocks
+                    uLCD.filled_rectangle(BUFFER + (j * BLOCK_SIDE), BUFFER  + (i * BLOCK_SIDE), BLOCK_SIDE + (j * BLOCK_SIDE), BLOCK_SIDE  + (i * BLOCK_SIDE), WHITE);
+                }
+            }          
+            uLCD.rectangle(BUFFER, BUFFER, BLOCK_SIDE, BLOCK_SIDE, RED); // initialize player at top left block
+            start_game = 0;
+        }
+        uLCD.locate(0,15);
+        uLCD.color(0xFFCCCC);
+        uLCD.printf("Time left: %2.0F", time_limit - t.read());
+        
+        /*
+        * Handle player input for movement
+        */
+        
+        if (myNav.right() && current_x < NUM_ROWS - 1) {
+            uLCD.rectangle(BUFFER + (current_x * BLOCK_SIDE), BUFFER + (current_y * BLOCK_SIDE), BLOCK_SIDE + (current_x * BLOCK_SIDE), BLOCK_SIDE + (current_y * BLOCK_SIDE), WHITE);
+            current_x++;
+            uLCD.rectangle(BUFFER + (current_x * BLOCK_SIDE), BUFFER + (current_y * BLOCK_SIDE), BLOCK_SIDE + (current_x * BLOCK_SIDE), BLOCK_SIDE + (current_y * BLOCK_SIDE), RED);
+           // playSound("/sd/wavfiles/shoot.wav");
+            wait(.2);
+        }
+        if (myNav.left() && current_x > 0) {
+            uLCD.rectangle(BUFFER + (current_x * BLOCK_SIDE), BUFFER + (current_y * BLOCK_SIDE), BLOCK_SIDE + (current_x * BLOCK_SIDE), BLOCK_SIDE + (current_y * BLOCK_SIDE), WHITE);
+            current_x--;
+            uLCD.rectangle(BUFFER + (current_x * BLOCK_SIDE), BUFFER + (current_y * BLOCK_SIDE), BLOCK_SIDE + (current_x * BLOCK_SIDE), BLOCK_SIDE + (current_y * BLOCK_SIDE), RED);
+            wait(.2);
+        }      
+        if (myNav.down() && current_y < NUM_ROWS - 1) {
+            uLCD.rectangle(BUFFER + (current_x * BLOCK_SIDE), BUFFER + (current_y * BLOCK_SIDE), BLOCK_SIDE + (current_x * BLOCK_SIDE), BLOCK_SIDE + (current_y * BLOCK_SIDE), WHITE);
+            current_y++;
+            uLCD.rectangle(BUFFER + (current_x * BLOCK_SIDE), BUFFER + (current_y * BLOCK_SIDE), BLOCK_SIDE + (current_x * BLOCK_SIDE), BLOCK_SIDE + (current_y * BLOCK_SIDE), RED);
+            wait(.2);
+        }        
+        if (myNav.up() && current_y > 0) {
+            uLCD.rectangle(BUFFER + (current_x * BLOCK_SIDE), BUFFER + (current_y * BLOCK_SIDE), BLOCK_SIDE + (current_x * BLOCK_SIDE), BLOCK_SIDE + (current_y * BLOCK_SIDE), WHITE);
+            current_y--;
+            uLCD.rectangle(BUFFER + (current_x * BLOCK_SIDE), BUFFER + (current_y * BLOCK_SIDE), BLOCK_SIDE + (current_x * BLOCK_SIDE), BLOCK_SIDE + (current_y * BLOCK_SIDE), RED);
+            wait(.2);
+        }   
+  
+        /*
+        * When user clicks, draw the according shape from the final_shapes array in that spot
+        */
+        if(myNav.fire() && num_flips < 2 && final_shapes[current_x][current_y]!= -1) {
+            // keep track of shape's position from first click
+            if(num_flips == 0) {
+                prev_x = current_x;
+                prev_y = current_y; 
+            }
+            playSound("/sd/wavfiles/buttonpress.wav");
+            // fill block background with black
+            uLCD.filled_rectangle(BUFFER + (current_x * BLOCK_SIDE), BUFFER + (current_y * BLOCK_SIDE), BLOCK_SIDE + (current_x * BLOCK_SIDE), BLOCK_SIDE + (current_y * BLOCK_SIDE), BLACK);
+            prev_shape = current_shape;
+            switch(final_shapes[current_x][current_y]) {
+                case red_circle: 
+                    uLCD.filled_circle(BUFFER + BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BUFFER + BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), 5, RED);
+                    current_shape =  red_circle; 
+                    break;
+                case blue_circle:
+                    uLCD.filled_circle(BUFFER + BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BUFFER + BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), 5, BLUE);
+                    current_shape = blue_circle;
+                    break;
+                case green_circle:
+                    uLCD.filled_circle(BUFFER + BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BUFFER + BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), 5, GREEN);
+                    current_shape = green_circle;
+                    break;
+                case pink_circle:
+                    uLCD.filled_circle(BUFFER + BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BUFFER + BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), 5, PINK);
+                    current_shape = pink_circle;
+                    break;
+                case red_square:
+                    uLCD.filled_rectangle(BUFFER + BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BUFFER + BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), BLOCK_SIDE - BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BLOCK_SIDE - BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), RED);
+                    current_shape = red_square;
+                    break;
+                case green_square:
+                    uLCD.filled_rectangle(BUFFER + BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BUFFER + BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), BLOCK_SIDE - BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BLOCK_SIDE - BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), BLUE);
+                    current_shape = green_square;
+                    break;
+                case blue_square:
+                    uLCD.filled_rectangle(BUFFER + BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BUFFER + BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), BLOCK_SIDE - BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BLOCK_SIDE - BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), GREEN);
+                    current_shape = blue_square;
+                    break;
+                case pink_square:
+                    uLCD.filled_rectangle(BUFFER + BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BUFFER + BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), BLOCK_SIDE - BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BLOCK_SIDE - BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), PINK);
+                    current_shape = pink_square;
+                    break;
+                default:
+                    uLCD.filled_circle(BUFFER + BLOCK_SIDE / 2 + (current_x * BLOCK_SIDE), BUFFER + BLOCK_SIDE / 2 + (current_y * BLOCK_SIDE), 5, BLACK);
+                    break;
+            }
+            num_flips++;
+            //wait(.2);    
+        }   
+    
+        // Prevents double click from registering as match
+        if(num_flips == 2 && current_x == prev_x && current_y == prev_y){
+            num_flips--;
+            }
+        /*
+        * After user flips 2 cards, check to see if they are correct 
+        */ 
+        if(num_flips == 2) {
+            num_flips = 0;
+             wait(.5); // seconds before shapes disappears (time to memorize shapes)
+            
+            //user is correct (shapes match)
+            if (prev_shape == current_shape) {
+                // draws black rectangles over the two blocks so they go away
+                uLCD.filled_rectangle(BUFFER + (prev_x * BLOCK_SIDE), BUFFER + (prev_y * BLOCK_SIDE), BLOCK_SIDE + (prev_x * BLOCK_SIDE), BLOCK_SIDE + (prev_y * BLOCK_SIDE), BLACK);
+                uLCD.filled_rectangle(BUFFER + (current_x * BLOCK_SIDE), BUFFER + (current_y * BLOCK_SIDE), BLOCK_SIDE + (current_x * BLOCK_SIDE), BLOCK_SIDE + (current_y * BLOCK_SIDE), BLACK);
+                playSound("/sd/wavfiles/supermissile.wav");
+                final_shapes[current_x][current_y] = -1;
+                final_shapes[prev_x][prev_y] = -1;
+                score++;
+            }
+            // user did not match shapes
+            else { 
+                // draws white blocks back over them (back to unflipped)
+                uLCD.filled_rectangle(BUFFER + (prev_x * BLOCK_SIDE), BUFFER + (prev_y * BLOCK_SIDE), BLOCK_SIDE + (prev_x * BLOCK_SIDE), BLOCK_SIDE + (prev_y * BLOCK_SIDE), WHITE);
+                uLCD.filled_rectangle(BUFFER + (current_x * BLOCK_SIDE), BUFFER + (current_y * BLOCK_SIDE), BLOCK_SIDE + (current_x * BLOCK_SIDE), BLOCK_SIDE + (current_y * BLOCK_SIDE), WHITE);
+            }
+            uLCD.rectangle(BUFFER + (prev_x * BLOCK_SIDE), BUFFER + (prev_y * BLOCK_SIDE), BLOCK_SIDE + (prev_x * BLOCK_SIDE), BLOCK_SIDE + (prev_y * BLOCK_SIDE), WHITE);
+            uLCD.rectangle(BUFFER + (current_x * BLOCK_SIDE), BUFFER + (current_y * BLOCK_SIDE), BLOCK_SIDE + (current_x * BLOCK_SIDE), BLOCK_SIDE + (current_y * BLOCK_SIDE), WHITE);
+        }
+    }
+    // End Screen
+    t.stop();
+    uLCD.cls();
+    uLCD.text_string("GAME OVER", 5, 5, FONT_7X8, 0xFFCCCC);
+    uLCD.locate(5,8);
+    uLCD.printf("Score = %D",score);
+}