ECE 4180 Spring 2016 Lab 4

Dependencies:   Memory_Card_Game SDFileSystem mbed

Dependents:   Memory_Card_Game

main.cpp

Committer:
kravemind
Date:
2016-03-14
Revision:
6:88e284f2063c
Parent:
5:6853dc5bd06d

File content as of revision 6:88e284f2063c:

// Authors: Kristen Fernandez, Krish Ravindranath
// Target: MBED nxp lpc1768

#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,p26);    // 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( p9, p6, p7, p5, p8);

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);
}