ECE 4180 - Lab 4 Tower of Hanoi
Dependencies: 4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player
Revision 0:159d50728af0, committed 2016-11-02
- Comitter:
- molorvida3
- Date:
- Wed Nov 02 17:29:14 2016 +0000
- Commit message:
- ECE 4180 - Lab 4 Tower of Hanoi
Changed in this revision
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