ECE 4180 - Lab 4 Tower of Hanoi

Dependencies:   4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player

Files at this revision

API Documentation at this revision

Comitter:
molorvida3
Date:
Wed Nov 02 17:29:14 2016 +0000
Commit message:
ECE 4180 - Lab 4 Tower of Hanoi

Changed in this revision

4DGL-uLCD-SE.lib Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
wave_player.lib Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 159d50728af0 4DGL-uLCD-SE.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/4DGL-uLCD-SE.lib	Wed Nov 02 17:29:14 2016 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/4180_1/code/4DGL-uLCD-SE/#e39a44de229a
diff -r 000000000000 -r 159d50728af0 SDFileSystem.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Wed Nov 02 17:29:14 2016 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/mbed_official/code/SDFileSystem/#8db0d3b02cec
diff -r 000000000000 -r 159d50728af0 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Nov 02 17:29:14 2016 +0000
@@ -0,0 +1,528 @@
+//ECE 4180 Lab 4
+//Tower of Hanoi Game - uLCD, joystick, sd card, speakers
+//Mark Francisco Olorvida, Khayame Maiki
+#include "mbed.h"
+#include "uLCD_4DGL.h"
+#include "SDFileSystem.h"
+#include "wave_player.h"
+#include "rtos.h"
+#include "stdlib.h"
+#include <stack>
+
+
+#define BROWN 0x663300
+#define YELLOW 0xFFFF00
+#define ORANGE 0xFFA500
+
+using namespace std;
+
+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();
+}
+
+Nav_Switch myNav( p16, p13, p14, p12, p15); //up, down, left, right, fire
+
+uLCD_4DGL uLCD(p28,p27,p30); // serial tx, serial rx, reset pin;
+
+SDFileSystem sd(p5, p6, p7, p8, "sd"); // sd(SPI mosi, SPI miso, SPI sck, digital out cs)
+
+Mutex stdio_mutex;  //mutex for the uLCD
+
+AnalogOut DACout(p18); // used to play sound on speaker
+
+PwmOut Speaker(p21);
+
+//wave player plays a *.wav file to D/A and a PWM
+wave_player waver(&DACout);
+
+
+
+
+
+
+stack<int>  col1; //
+stack<int>  col2;
+stack<int>  col3;
+
+
+
+int source; // Source of ring that is going to be moved
+int destination; // Destination of ring that is going to be moved
+int direction; // don't actually use this right now
+int numRings;
+bool select; // 0 if selecting source, 1 if selecting destination
+int cursor; // position of destination selecting cursor
+int count = 0; 
+
+
+void move(); //move rectangles between columns
+void drawMove( int , int , int  ); //draw the change in Rings i.e. moving Ring 1 from Src1 --> Src 2 results in col. 1 = 4 3 2 and col.2 = 1
+bool checkVictory(); //function to check win condition (all rings move to a separate column from the starting column
+void drawCursor(int , int ); 
+void drawSourceSelect();
+void drawDestinationSelect();
+void game(); //main game function
+
+int main()
+{
+    //Title Screen
+    
+    uLCD.printf("\n  Tower of Hanoi\n"); 
+    //3 vertical lines at x = 32, 64, 96
+    //have circles to mark the positions of columns
+    uLCD.filled_circle(32, 110, 2, BLUE);
+    uLCD.filled_circle(64, 110, 2, BLUE);
+    uLCD.filled_circle(96, 110, 2, BLUE);
+    //rectangles - each rectangle increases in width based on its number
+    //rectangles go from 1-6 going down
+    uLCD.filled_rectangle(32-2*1, 35+15*1-1, 32+2*1, 35+15*1, RED); //(filled_rectangle*(32(x-coordinate of vertical line)-2*(num_rectangle (1,2,3 or 4)), 35 + (60/num_rectangles)-1, first param but with addition, 2nd param but no extra 1 subtracted))
+    uLCD.filled_rectangle(32-2*2, 35+15*2-1, 32+2*2, 35+15*2, ORANGE);
+    uLCD.filled_rectangle(32-2*3, 35+15*3-1, 32+2*3, 35+15*3, YELLOW);
+    uLCD.filled_rectangle(32-2*4, 35+15*4-1, 32+2*4, 35+15*4, GREEN);
+    
+    //play intro wave file
+    FILE *wave_file; 
+    //open file
+    wave_file = fopen("/sd/wavfiles/intro.wav" ,"r");
+    if (wave_file == NULL){
+        error("Could not open file for read\n");
+        }
+    //play file
+    Speaker.period(1.0/400000.0);
+    waver.play(wave_file);
+    //close file
+    fclose(wave_file);
+
+    uLCD.cls(); // clear screen
+    //tutorial
+    uLCD.printf("\n    HOW TO PLAY\n");
+    uLCD.printf("Goal: Move all rectangles to another pole.\n");
+    uLCD.printf("\n1. You can only move one rectangle at a time.\n");
+    uLCD.printf("\n2. Large rectangles can not be put on top of smaller rectangles.\n");
+    while(1){ //loop until user pushes left right or fire after reading tutorial
+        if (myNav.left() or myNav.right() or myNav.fire()){ break;}
+        else {}
+        }
+    uLCD.cls();
+    uLCD.printf("\n     CONTROLS\n");
+    uLCD.printf("\nUse Left/Right to choose column \n");
+    uLCD.printf("-Red Circle = Source column\n");
+    uLCD.printf("-Yellow Cursor = Dest. column\n");
+    uLCD.printf("\nUse Center to select column.\n");
+    while(1){ //loop until user pushes left right or fire after reading tutorial
+        if (myNav.left() or myNav.right() or myNav.fire()){ break;}
+        else {}
+        }
+    game();
+}
+void game()  // main game function
+{
+    uLCD.cls();
+    // Game init
+
+    uLCD.filled_circle(32, 110, 2, BLUE);
+    uLCD.filled_circle(64, 110, 2, BLUE);
+    uLCD.filled_circle(96, 110, 2, BLUE);
+    uLCD.filled_rectangle(32-2*1, 35+12*1-1, 32+2*1, 35+12*1, RED);
+    uLCD.filled_rectangle(32-2*2, 35+12*2-1, 32+2*2, 35+12*2, ORANGE);
+    uLCD.filled_rectangle(32-2*3, 35+12*3-1, 32+2*3, 35+12*3, YELLOW);
+    uLCD.filled_rectangle(32-2*4, 35+12*4-1, 32+2*4, 35+12*4, GREEN);
+
+    numRings = 4;
+    col1.push(4);
+    col1.push(3);
+    col1.push(2);
+    col1.push(1);
+
+    // draw game
+    source = 1;
+    destination = 2;
+    cursor = 2;
+    drawSourceSelect();
+    drawDestinationSelect();
+    uLCD.filled_rectangle(32-2*1, 35+12*1-1, 32+2*1, 35+12*1, RED);
+    uLCD.filled_rectangle(32-2*2, 35+12*2-1, 32+2*2, 35+12*2, ORANGE);
+    uLCD.filled_rectangle(32-2*3, 35+12*3-1, 32+2*3, 35+12*3, YELLOW);
+    uLCD.filled_rectangle(32-2*4, 35+12*4-1, 32+2*4, 35+12*4, GREEN);
+
+
+
+
+    uLCD.locate(0,0);
+    uLCD.printf("# of Moves: %i\n",count); //update move count
+    while (1) {  // Game loop
+        
+        if (checkVictory()) { // checks to see if the win condition has been met... will either reset, or go victory screen or something
+            wait(1);
+            uLCD.cls();
+            uLCD.locate(0,0);
+            uLCD.printf("\n   You won!\n");
+            uLCD.printf("\nMin. Moves: 15 \n");
+            uLCD.printf("\nYour # of moves : %i \n" , count );
+            //play intro wave file
+            FILE *wave_file;
+            //open file
+            wave_file = fopen("/sd/wavfiles/outro.wav" ,"r");
+            if (wave_file == NULL) {
+                error("Could not open file for read\n");
+            }
+            //play file
+            Speaker.period(1.0/400000.0);
+            waver.play(wave_file);
+            //close file
+            fclose(wave_file);
+            count = 0;  //reset count
+            break;
+        }
+
+
+        if ( myNav.left() ) {                   // moves either source or destination pointer to the left based on
+            if (!select) {                      // the variable select
+                if (source == 1) {
+                    source = 3;
+
+                } else {
+                    source = source - 1;
+
+                }
+                drawSourceSelect();
+            } else {
+                if (destination == 1) {
+                    destination = 3;
+
+                } else {
+                    destination = destination - 1;
+
+                }
+                drawDestinationSelect();
+            }
+
+        }
+
+        else if ( myNav.right() ) {
+            if (!select) {
+                if (source == 3) {
+                    source = 1;
+
+                } else {
+                    source = source + 1;
+                }
+                drawSourceSelect();
+            } else {
+                if (destination == 3) {
+                    destination = 1;
+                } else {
+                    destination = destination + 1;
+                }
+                drawDestinationSelect();
+            }
+        }
+
+        else if ( myNav.fire()) {
+            if (!select) { // source chosen, toggle to choose destination
+                select = !select; // toggles
+            } else if (select) { // Destination chosen, move ring
+                move();
+                count ++;
+                uLCD.locate(0,0);
+                uLCD.printf("# of Moves: %i\n",count); //update move count
+                select = !select; // Go back to source selection regardless of the outcome of move
+            }
+            wait(.4);
+        }
+
+    }
+    if (col3.size() == numRings){ //if col3 has numRings, pop all rings
+        for (int x = 0; x < 4 ; x++){
+            col3.pop();
+            }
+        }
+    else if (col2.size() == numRings){ //same with col 2
+        for (int x = 0; x < 4 ; x++){
+            col2.pop();
+            }
+        }
+    game();
+}
+void move()
+{
+    int sourceSize, destSize, ringNum, top;
+
+    
+
+    switch (source) {
+
+        case 1:
+            sourceSize = col1.size();  // to figure out where on the Y axis to black out a ring
+            if (sourceSize == 0)
+                break;
+
+            if ( destination == 2) {
+                if (col2.empty()) {
+                    top = col1.top();
+                    col2.push(top);     // move the ring over
+
+                    col1.pop();
+
+                    destSize = col2.size(); // to figure out where on Y axis to draw new ring
+                    ringNum = top;
+                    //uLCD.printf("Ring Number: %i " , ringNum);
+                    drawMove(sourceSize, destSize, ringNum);
+                }
+
+
+                else if ( col1.top() < col2.top()) { // if the ring on column 1 is smaller than the ring in column 2
+                    top = col1.top();
+                    col2.push(top);     // move the ring over
+                    col1.pop();
+                    destSize = col2.size(); // to figure out where on Y axis to draw new ring
+                    ringNum = top;
+                    drawMove(sourceSize, destSize, ringNum);
+
+                }
+
+
+            }
+
+            else if ( destination == 3) {
+                if (col3.empty()) {
+                    top = col1.top();
+                    col3.push(top);     // move the ring over
+                    col1.pop();
+                    destSize = col3.size();
+                    ringNum = top;
+                    drawMove(sourceSize, destSize, ringNum);
+                } else if ( col1.top() < col3.top()) { // if the ring on column 1 is smaller than the ring in column 3
+                    top = col1.top();
+                    col3.push(top);     // move the ring over
+                    col1.pop();
+                    destSize = col3.size();
+                    ringNum = top;
+                    drawMove(sourceSize, destSize, ringNum);
+                }
+            }
+
+
+            break;
+
+
+
+
+        case 2:
+            sourceSize = col2.size();
+            if (sourceSize == 0)
+                break;
+            if ( destination == 1) {
+                if (col1.empty()) {
+                    col1.push(col2.top());
+                    col2.pop();
+                    destSize = col1.size();
+                    ringNum = col1.top();
+                    drawMove(sourceSize, destSize, ringNum);
+                } else if ( col2.top() < col1.top()) {
+                    col1.push(col2.top());
+                    col2.pop();
+                    destSize = col1.size();
+                    ringNum = col1.top();
+                    drawMove(sourceSize, destSize, ringNum);
+                }
+            }
+
+            else  if ( destination == 3) {
+                if (col3.empty()) {
+                    col3.push(col2.top());
+                    col2.pop();
+                    destSize = col3.size();
+                    ringNum = col3.top();
+                    drawMove(sourceSize, destSize, ringNum);
+                } else  if ( col2.top() < col3.top()) {
+
+                    col3.push(col2.top());
+                    col2.pop();
+                    destSize = col3.size();
+                    ringNum = col3.top();
+                    drawMove(sourceSize, destSize, ringNum);
+                }
+            }
+            break;
+
+        case 3:
+            sourceSize = col3.size();
+            if (sourceSize == 0)
+                break;
+            if ( destination == 1) {
+                if ( col1.empty()) {
+                    col1.push(col3.top());
+                    col3.pop();
+                    destSize = col1.size();
+                    ringNum = col1.top();
+                    drawMove(sourceSize, destSize, ringNum);
+                } else  if ( col3.top() < col1.top()) {
+                    col1.push(col3.top());
+                    col3.pop();
+                    destSize = col1.size();
+                    ringNum = col1.top();
+                    drawMove(sourceSize, destSize, ringNum);
+                }
+            }
+
+            else if ( destination == 2) {
+                if (col2.empty()) {
+                    col2.push(col3.top());
+                    col3.pop();
+                    destSize = col2.size();
+                    ringNum = col2.top();
+                    drawMove(sourceSize, destSize, ringNum);
+                }
+
+                else if ( col3.top() < col2.top()) {
+                    col2.push(col3.top());
+                    col3.pop();
+                    destSize = col2.size();
+                    ringNum = col2.top();
+                    drawMove(sourceSize, destSize, ringNum);
+                }
+            }
+            break;
+
+
+    }
+
+
+
+
+
+}
+
+void drawMove( int sourceSize, int destSize, int numRing )
+{
+
+    int x1Source = 32 * source - 2*numRing;
+    int y1Source =  35 + 12*(5- sourceSize) - 1;
+    int x2Source = 32 * source + 2*numRing;
+    int y2Source = 35 + 12*(5- sourceSize);
+
+    int x1Dest = 32 * destination - 2*numRing;
+    int y1Dest = 35 + 12*(5-destSize) - 1;
+    int x2Dest = 32 * destination + 2*numRing;
+    int y2Dest = 35 + 12*(5- destSize);
+
+
+    switch (numRing) {
+        case 1 :
+            uLCD.filled_rectangle(x1Dest, y1Dest, x2Dest, y2Dest, RED);
+            //uLCD.filled_rectangle(x1Dest, 35+12*4-1, x2Dest, 35+12*4, RED);
+            break;
+        case 2 :
+            uLCD.filled_rectangle(x1Dest, y1Dest, x2Dest, y2Dest, ORANGE);
+            break;
+        case 3 :
+            uLCD.filled_rectangle(x1Dest, y1Dest, x2Dest, y2Dest, YELLOW);
+            break;
+        case 4 :
+            uLCD.filled_rectangle(x1Dest, y1Dest, x2Dest, y2Dest, GREEN);
+            break;
+    }
+
+    uLCD.filled_rectangle(x1Source, y1Source, x2Source, y2Source, BLACK);
+
+}
+
+
+
+
+
+
+
+bool checkVictory()
+{
+    return (col3.size() == numRings or col2.size() == numRings); // if column 3 has all the rings game is done. This should only be possible if it's correct
+}
+
+void drawCursor(int columnX, int color)  //columnX = x-coordinate of column, color
+{
+//draws a 9 pixel triangle(5 on 1 row, 3 on row 2, 1 on row 3)
+    uLCD.pixel(columnX,30,color);
+    uLCD.pixel(columnX-1,29,color);
+    uLCD.pixel(columnX,29,color);
+    uLCD.pixel(columnX+1,29,color);
+    uLCD.pixel(columnX-2,28,color);
+    uLCD.pixel(columnX-1,28,color);
+    uLCD.pixel(columnX,28,color);
+    uLCD.pixel(columnX+1,28,color);
+    uLCD.pixel(columnX+2,28,color);
+}
+
+void drawSourceSelect()
+{
+    uLCD.filled_circle(32, 110, 2, BLUE);
+    uLCD.filled_circle(64, 110, 2, BLUE);
+    uLCD.filled_circle(96, 110, 2, BLUE);
+    if (source == 1 )
+        uLCD.filled_circle(32, 110, 2, RED);
+    else if ( source == 2 )
+        uLCD.filled_circle(64, 110, 2, RED);
+    else if (source == 3 )
+        uLCD.filled_circle(96, 110, 2, RED);
+    wait(.3);
+}
+
+void drawDestinationSelect()  // also changes cursor global to new destination
+{
+    drawCursor( cursor*32, BLACK);
+    drawCursor( destination*32, YELLOW);
+    cursor = destination;
+    wait(.3);
+}
diff -r 000000000000 -r 159d50728af0 mbed-rtos.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Wed Nov 02 17:29:14 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#d3d0e710b443
diff -r 000000000000 -r 159d50728af0 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Nov 02 17:29:14 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/9bcdf88f62b0
\ No newline at end of file
diff -r 000000000000 -r 159d50728af0 wave_player.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wave_player.lib	Wed Nov 02 17:29:14 2016 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/sravet/code/wave_player/#acc3e18e77ad