Lab 4 for ECE4180, final verison

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

Fork of Lab4-Reversi-v2 by Emeril Huang

Overview

For our project, we created the 2 player game “Reversi”, otherwise known as Othello using the uLCD-144-G2, a Sparkfun 5-way Tactile Switch Joystick, a speaker with a Class D audio amp breakout board, and SD card reader. The program begins with the dark player’s turn, and the joystick is used to move the red cursor box around. Pressing down on the joystick will attempt to put a piece down, resulting in a flipping sound, and will show an X on the screen for invalid moves. The game will finish when the board is filled, and go to a result screen, playing a victory sound. The result screen allows for a play again option. /media/uploads/EvolutionOfWar/reversimbed.jpg

Components

Wiring

mbedCableuLCD
P28TXRX
P27RXTX
P29RESRESET
VU+5V+5V
GNDGNDGND
mbedSD Card Reader
P5DI
P6DO
P7SCK
P8CS
GNDGND
VoutVCC
mbedAmpliferSpeaker
P18In +
GNDGND
VUPWR +
Out ++
Out --
GNDPWR -
mbedJoystick
P14Up
P13Center
P12Left
P11Down
P10Right
GND-
Vout+

Program

Import programLab4-Reversi-Final

Lab 4 for ECE4180, final verison

Revision:
1:cc72ad58982b
Parent:
0:fce0f9489de3
Child:
2:1f7c6cc19a9a
--- a/Reversi.cpp	Mon Oct 31 19:22:51 2016 +0000
+++ b/Reversi.cpp	Tue Nov 01 11:46:09 2016 +0000
@@ -1,9 +1,13 @@
 #include "mbed.h"
 #include "uLCD_4DGL.h"
+#include "SDFileSystem.h"
+#include "wave_player.h"
 uLCD_4DGL uLCD(p28, p27, p29); // create a global lcd object
+SDFileSystem sd(p5, p6, p7, p8, "sd"); // the pinout on the mbed Cool Components workshop board
+PwmOut Speaker(p21);
+AnalogOut DACout(p18);
 
-// black <=> 2
-// white <=> 1
+wave_player waver(&DACout);
 
 class Nav_Switch
 {
@@ -63,41 +67,17 @@
  
 Nav_Switch myNav( p14, p11, p12, p10, p13); //pin order on Sparkfun breakout
  
-int whosTurn = 1;
+int turn = 1; // black goes on 1, white goes on 2 (or 0)
 int gb[8][8];
 int NUM_COLS = 8;
 int NUM_ROWS = 8;
- /*var isEmpty = function(r,c) {
-    return board[r][c] == 0;
-}
-var score = function(boardIn) {
-    var blackScore = 0;
-    var whiteScore = 0;
-    for(var r=0; r<8; r++)
-    {
-        for(var c=0; c<8; c++)
-        {
-            var current = board[r][c];
-            if(current === 1)
-            {
-                whiteScore++;
-            }
-            if(current === -1)
-            {
-                blackScore++;
-            }
-        }
-    }
-    var score = {black: blackScore, white: whiteScore};
-    return score;
-}
-var displayScore = function() {
-    var currentScore = score(board);
-    textSize(20);
-    fill(255, 0, 0);
-    text(currentScore.black+" - "+currentScore.white,180,390);
-}
- */
+int xCoor = 3;
+int yCoor = 4;
+int numBlack = 0;
+int numWhite = 0;
+bool moved = false;
+bool gameover = false;
+
 void initialize_game_board()
 {
     //This is a nested loop to make sure every cell is empty
@@ -113,7 +93,7 @@
     gb[4][3] = 2;//Put down black piece
     
     uLCD.cls();
-    uLCD.background_color(0x007f00);
+    uLCD.filled_rectangle(0,0,127,127,0x007f00);
     
     uLCD.rectangle(7,7,120,120,DGREY);
     uLCD.rectangle(8,8,119,119,DGREY);
@@ -129,63 +109,30 @@
     }
 }
 
-void drawCursor(int xCoor, int yCoor) //Expecting x ={0,7} and y ={0,7}
+void drawCursor(int x, int y) //Expecting x ={0,7} and y ={0,7}
 {
-    uLCD.filled_rectangle(7 + 14*xCoor, 7 + 14*yCoor,8 + 14*xCoor,22 + 14*yCoor,RED);
-    uLCD.filled_rectangle(7 + 14*xCoor, 7 + 14*yCoor,22 + 14*xCoor,8 + 14*yCoor,RED);
-    uLCD.filled_rectangle(7 + 14*xCoor, 21 + 14*yCoor,22 + 14*xCoor,22 + 14*yCoor,RED);
-    uLCD.filled_rectangle(21 + 14*xCoor, 7 + 14*yCoor,22 + 14*xCoor,22 + 14*yCoor,RED);
+    uLCD.filled_rectangle(7 + 14*x, 7 + 14*y,8 + 14*x,22 + 14*y,RED);
+    uLCD.filled_rectangle(7 + 14*x, 7 + 14*y,22 + 14*x,8 + 14*y,RED);
+    uLCD.filled_rectangle(7 + 14*x, 21 + 14*y,22 + 14*x,22 + 14*y,RED);
+    uLCD.filled_rectangle(21 + 14*x, 7 + 14*y,22 + 14*x,22 + 14*y,RED);
 }
     
-void removeCursor(int xCoor,int yCoor)
+void removeCursor(int x,int y)
 {
-    uLCD.filled_rectangle(7 + 14*xCoor, 7 + 14*yCoor,8 + 14*xCoor,22 + 14*yCoor,DGREY);
-    uLCD.filled_rectangle(7 + 14*xCoor, 7 + 14*yCoor,22 + 14*xCoor,8 + 14*yCoor,DGREY);
-    uLCD.filled_rectangle(7 + 14*xCoor, 21 + 14*yCoor,22 + 14*xCoor,22 + 14*yCoor,DGREY);
-    uLCD.filled_rectangle(21 + 14*xCoor, 7 + 14*yCoor,22 + 14*xCoor,22 + 14*yCoor,DGREY);
+    uLCD.filled_rectangle(7 + 14*x, 7 + 14*y,8 + 14*x,22 + 14*y,DGREY);
+    uLCD.filled_rectangle(7 + 14*x, 7 + 14*y,22 + 14*x,8 + 14*y,DGREY);
+    uLCD.filled_rectangle(7 + 14*x, 21 + 14*y,22 + 14*x,22 + 14*y,DGREY);
+    uLCD.filled_rectangle(21 + 14*x, 7 + 14*y,22 + 14*x,22 + 14*y,DGREY);
 }
 
-/*
-var copyBoard = function() {
-    var boardCopy = [[0,0,0,0,0,0,0,0],
-             [0,0,0,0,0,0,0,0],
-             [0,0,0,0,0,0,0,0],
-             [0,0,0,0,0,0,0,0],
-             [0,0,0,0,0,0,0,0],
-             [0,0,0,0,0,0,0,0],
-             [0,0,0,0,0,0,0,0],
-             [0,0,0,0,0,0,0,0]];
-    for(var r=0; r<8; r++)
-    {
-        for(var c=0; c<8; c++)
-        {
-            boardCopy[r][c] = board[r][c];
-        }
-    }
-    return boardCopy;
-}; */
-//Removed DrawEmptyBoard function
-
-/*var drawPiece = function(r,c,player) {
-    var xPos = 400/8*c+400/16;
-    var yPos = 400/8*r+400/16;
-    if(player === 0)
-    {
-        return;
-    }
-    fill(0, 0, 0);
-    if(player===1)
-    {
-        fill(255, 255, 255);
-    }
-    ellipse(xPos,yPos,40,40);
-}; */
-
 void drawPieces(){
     for (int i = 0; i < NUM_ROWS; i++)
     {
         for (int j = 0; j < NUM_COLS; j++)
         {
+            if(gb[i][j] == 0){
+                uLCD.filled_circle(14 * (i + 1), 14 * (j + 1), 5 , 0x007f00);
+            }
             if(gb[i][j] == 1){
                 uLCD.filled_circle(14 * (i + 1), 14 * (j + 1), 5 , WHITE);
             }
@@ -197,6 +144,11 @@
 }
 
 void drawPiece(int i, int j) { //xCoor, yCoor
+    if (turn == 0) {
+        gb[i][j] = 1;
+    } else {
+        gb[i][j] = 2;
+    }
     if(gb[i][j] == 1){
         uLCD.filled_circle(14 * (i + 1), 14 * (j + 1), 5 , WHITE);
     }
@@ -206,7 +158,9 @@
 }
 
 void flippingPiece(int i, int j) { //xCoor, yCoor, animation
-    if(gb[i][j] == 1){ //Gradually changes a piece White
+    
+    if(gb[i][j] == 2){ //Gradually changes a piece White
+        gb[i][j] = 1;
         uLCD.filled_circle(14 * (i + 1), 14 * (j + 1), 1 , 0x4c4c4c);
         wait(0.1);
         uLCD.filled_circle(14 * (i + 1), 14 * (j + 1), 1 , 0xb2b2b2);
@@ -221,8 +175,8 @@
         wait(0.1);
         uLCD.filled_circle(14 * (i + 1), 14 * (j + 1), 5 , 0xffffff);
         wait(0.1);
-    }
-    if(gb[i][j] == 2){ //Gradually changes a piece Black
+    } else if(gb[i][j] == 1){ //Gradually changes a piece Black
+        gb[i][j] = 2;
         uLCD.filled_circle(14 * (i + 1), 14 * (j + 1), 1 , 0xb2b2b2);
         wait(0.1);
         uLCD.filled_circle(14 * (i + 1), 14 * (j + 1), 1 , 0x4c4c4c);
@@ -240,23 +194,6 @@
     }  
 }
 
-void Select(int xCoor, int yCoor){ //function should determine what happens when joy stick pressed
-    if(whosTurn%2 == 0) ( //Whites Turn
-        //Valid Check, see if move is possible
-        
-        //Place Piece
-        drawPiece(xCoor, yCoor);
-        //Convert pieces in 2D Array
-        int counter; //Count number of converted pieces
-        
-        
-        //Flip pieces on screen
-        for( int m = 0; m<counter; m++) {
-                
-        }
-    }      
-}
-
 /*var fillBoard = function() {
     for(var r=0; r<8; r++)
     {
@@ -270,7 +207,7 @@
     drawEmptyBoard();
     fillBoard();
 };  --------------------------------------------WAS NOT USED VVVVV ----------------------------
-/*var flipFromInDir = function(r,c,player,rDir,cDir)
+var flipFromInDir = function(r,c,player,rDir,cDir)
 {
     //debug("Checking direction rDir: "+rDir+"    cDir: "+cDir+" for player "+player);
     var currentR = r;
@@ -420,34 +357,318 @@
     }
     return false;
 };
-var mouseClicked = function() {
-    var r = floor(mouseY*8/400);
-    var c = floor(mouseX*8/400);
-    if(isValidMove(r,c,whosTurn))
-    {
-        move(r,c);
+*/
+void invalid(int x, int y, int oldColor){
+    gb[x][y] = oldColor;
+    drawPieces();
+    uLCD.line(9 + 14 * xCoor, 11+ 14 * yCoor, 11+ 14 * xCoor, 9+ 14 * yCoor, RED);
+    uLCD.line(11+ 14 * xCoor, 9+ 14 * yCoor, 20+ 14 * xCoor, 18+ 14 * yCoor, RED);
+    uLCD.line(20+ 14 * xCoor, 18+ 14 * yCoor, 18+ 14 * xCoor, 20+ 14 * yCoor, RED);
+    uLCD.line(18+ 14 * xCoor, 20+ 14 * yCoor, 9+ 14 * xCoor, 11+ 14 * yCoor, RED);
+    uLCD.line(9+ 14 * xCoor, 18+ 14 * yCoor, 18+ 14 * xCoor, 9+ 14 * yCoor, RED);
+    uLCD.line(18+ 14 * xCoor, 9+ 14 * yCoor, 20+ 14 * xCoor, 11+ 14 * yCoor, RED);
+    uLCD.line(20+ 14 * xCoor, 11+ 14 * yCoor, 11+ 14 * xCoor, 20+ 14 * yCoor, RED);
+    uLCD.line(11+ 14 * xCoor, 20+ 14 * yCoor, 9+ 14 * xCoor, 18+ 14 * yCoor, RED);
+    wait(1);
+    uLCD.line(9 + 14 * xCoor, 11+ 14 * yCoor, 11+ 14 * xCoor, 9+ 14 * yCoor, 0x007F00);
+    uLCD.line(11+ 14 * xCoor, 9+ 14 * yCoor, 20+ 14 * xCoor, 18+ 14 * yCoor, 0x007F00);
+    uLCD.line(20+ 14 * xCoor, 18+ 14 * yCoor, 18+ 14 * xCoor, 20+ 14 * yCoor, 0x007F00);
+    uLCD.line(18+ 14 * xCoor, 20+ 14 * yCoor, 9+ 14 * xCoor, 11+ 14 * yCoor, 0x007F00);
+    uLCD.line(9+ 14 * xCoor, 18+ 14 * yCoor, 18+ 14 * xCoor, 9+ 14 * yCoor, 0x007F00);
+    uLCD.line(18+ 14 * xCoor, 9+ 14 * yCoor, 20+ 14 * xCoor, 11+ 14 * yCoor, 0x007F00);
+    uLCD.line(20+ 14 * xCoor, 11+ 14 * yCoor, 11+ 14 * xCoor, 20+ 14 * yCoor, 0x007F00);
+    uLCD.line(11+ 14 * xCoor, 20+ 14 * yCoor, 9+ 14 * xCoor, 18+ 14 * yCoor, 0x007F00);
+    drawPieces();
+}
+
+void valid_move(int x, int y) {
+    int opp, pl;
+    bool invalidD[] = {false, false, false, false, false, false, false, false}; //flip checker
+    if (turn == 1) { //pl is black
+        opp = 1;
+        pl = 2;
+    } else { // pl is white
+        opp = 2;
+        pl = 1;
     }
-    displayScore();
-}; 
-*/
+    int oldColor = gb[x][y]; //save old color for drawing over X
+    bool flipped = false;
+    if (gb[x][y] == 0) { // check empty space
+        drawPiece(x, y); // emtpy so draw
+        for (int i = 0; i < 8; i++) { // check for opponent around emtpy space and fill
+            if (i == 0) { // right
+                if (x + 1 < 7 && gb[x + 1][y] == opp) { //check to see if not beyond board and has to be next to the opponent
+                    for (int j = x + 2; j < 8; j++) {
+                        if (gb[j][y] == pl && !flipped) {
+                            for (int k = x + 1; k < j; k++) {
+                                flippingPiece(k, y);
+                            }
+                            flipped = true;
+                        } else if (gb[j][y] == 0) {
+                            j = 8;
+                        }
+                    }
+                    if (flipped) {
+                        flipped = false;
+                    } else {
+                        invalidD[0] = true;
+                    }
+                } else {
+                    invalidD[0] = true;
+                }
+            } else if (i == 1) { // down-right
+                if (x + 1 < 7 && y + 1 < 7 && gb[x + 1][y + 1] == opp) { // check if within margin and next to other color
+                    for (int j = 2; j < 8 - x && j < 8 - y; j++) { // start finding next same color
+                        if (gb[x + j][y + j] == pl && !flipped) { // if same color and not already been flipping
+                            for (int k = 1; k < j; k++) { // between other color to this same color
+                                flippingPiece(x + k, y + k); // flip
+                            }
+                            flipped = true; // marked flipped
+                        } else if (gb[x + j][y + j] == 0) { // if you find an empty instead
+                            j = 8; // skip for loop
+                        }
+                    }
+                    if (flipped) { // if flipped
+                        flipped = false; // set variable back to false
+                    } else {
+                        invalidD[1] = true; // no flip happened, so set invalid tracker to true
+                    }
+                } else {
+                    invalidD[1] = true; // not within margin or next to other color
+                }
+            } else if (i == 2) { // down
+                if (y + 1 < 7 && gb[x][y + 1] == opp) {
+                    for (int j = y + 2; j < 8; j++) {
+                        if (gb[x][j] == pl && !flipped) {
+                            for (int k = y + 1; k < j; k++) {
+                                flippingPiece(x, k);
+                            }
+                            flipped = true;
+                        } else if (gb[x][j] == 0) {
+                            j = 8;
+                        }
+                    }
+                    if (flipped) {
+                        flipped = false;
+                    } else {
+                        invalidD[2] = true;
+                    }
+                } else {
+                    invalidD[2] = true;
+                }
+            } else if (i == 3) { // down-left
+                if (x - 1 > 0 && y + 1 < 7 && gb[x - 1][y + 1] == opp) {
+                    for (int j = 2; j < x + 1 && j < 8 - y; j++) {
+                        if (gb[x - j][y + j] == pl && !flipped) {
+                            for (int k = 1; k < j; k++) {
+                                flippingPiece(x - k, y + k);
+                            }
+                            flipped = true;
+                        } else if (gb[x - j][y + j] == 0) {
+                            j = 5;
+                        }
+                    }
+                    if (flipped) {
+                        flipped = false;
+                    } else {
+                        invalidD[3] = true;
+                    }
+                } else {
+                    invalidD[3] = true;
+                }
+            } else if (i == 4) { // left
+                if (x - 1 > 0 && gb[x - 1][y] == opp) {
+                    for (int j = x - 2; j > -1; j--) {
+                        if (gb[j][y] == pl && !flipped) {
+                            for (int k = x - 1; k > j; k--) {
+                                flippingPiece(k, y);
+                            }
+                            flipped = true;
+                        } else if (gb[j][y] == 0) {
+                            j = -1;
+                        }
+                    }
+                    if (flipped) {
+                        flipped = false;
+                    } else {
+                        invalidD[4] = true;
+                    }
+                } else {
+                    invalidD[4] = true;
+                }
+            } else if (i == 5) { // up-left
+                if (x - 1 > 0 && y - 1 > 0 && gb[x - 1][y - 1] == opp) {
+                    for (int j = 2; j < x + 1 && j < y + 1; j++) {
+                        if (gb[x - j][y - j] == pl && !flipped) {
+                            for (int k = 1; k < j; k++) {
+                                flippingPiece(x - k, y - k);
+                            }
+                            flipped = true;
+                        } else if (gb[x - j][y - j] == 0) {
+                            j = 8;
+                        }
+                    }
+                    if (flipped) {
+                        flipped = false;
+                    } else {
+                        invalidD[5] = true;
+                    }
+                } else {
+                    invalidD[5] = true;
+                }
+            } else if (i == 6) { // up
+                if (y - 1 > 0 && gb[x][y - 1] == opp) {
+                    for (int j = y - 2; j > -1; j--) {
+                        if (gb[x][j] == pl && !flipped) {
+                            for (int k = y - 1; k > j; k--) {
+                                flippingPiece(x, k);
+                            }
+                            flipped = true;
+                        } else if (gb[x][j] == 0) {
+                            j = -1;
+                        }
+                    }
+                    if (flipped) {
+                        flipped = false;
+                    } else {
+                        invalidD[6] = true;
+                    }
+                } else {
+                    invalidD[6] = true;
+                }
+            } else if (i == 7) { // up-right
+                if (x + 1 < 7 && y - 1 > 0 && gb[x + 1][y - 1] == opp) {
+                    for (int j = 2; j < 8 - x && j < y + 1; j++) {
+                        if (gb[x + j][y - j] == pl && !flipped) {
+                            for (int k = 1; k < j; k++) {
+                                flippingPiece(x + k, y - k);
+                            }
+                            flipped = true;
+                        } else if (gb[x + j][y - j] == 0) {
+                            j = 8;
+                        }
+                    }
+                    if (flipped) {
+                        flipped = false;
+                    } else {
+                        invalidD[7] = true;
+                    }
+                } else {
+                    invalidD[7] = true;
+                }
+            }
+        } // finish checking around
+        flipped = false;
+        for (int i = 0; i < 8; i++) {
+            if (!invalidD[i] && !flipped) { // if a move is found, and only once
+                moved = true; // has moved
+                turn = ++turn%2; // increment turn
+                flipped = true; // check flip
+            }
+        }
+        if (!flipped) { // no changes were made
+            invalid(x, y, oldColor); // change back to old color and revert changes
+        }
+    } else { //invalid
+        invalid(x, y, oldColor); // not empty space
+    }
+}
+
+
+void countPieces()
+{
+    numBlack = 0;
+    numWhite = 0;
+    for(int row = 0; row < 8; row++){
+        for(int col = 0; col < 8; col++){
+            if(gb[row][col]==2)
+            {
+                numBlack++;
+            }
+            if(gb[row][col]==1)
+            {
+                numWhite++;
+            }
+        }
+    } 
+}
+void result() {
+    uLCD.cls(); // THIS CODE ASSUMES BACKGROUND CORRECTLY RESETS TO 0x007F00
+    
+    countPieces();
+    uLCD.color(RED);
+    uLCD.printf("Score\n");
+    uLCD.color(BLACK);
+    uLCD.printf("%D, numBlack");
+    uLCD.color(RED);
+    uLCD.printf(" - ");
+    uLCD.color(WHITE);
+    uLCD.printf("%D \n", numWhite);
+    uLCD.color(RED);
+    uLCD.printf("\n Play again? \n");
+    
+    uLCD.text_char('Y', 4, 9, BLUE);
+    uLCD.text_char('E', 5, 9, BLUE);
+    uLCD.text_char('S', 6, 9, BLUE);
+    uLCD.text_char('N', 11, 9, RED);
+    uLCD.text_char('O', 12, 9, RED);
+    
+    uLCD.rectangle(20,90, 40, 110, 0xffff00); //Default over Yes
+    bool optionSelected = false;
+    int choice = 1; //Default choice Yes
+    while(optionSelected ==false){
+        if(myNav[2] == 0 ){
+            uLCD.rectangle(20,90, 40, 110, 0xffff00);
+            uLCD.rectangle(80,90, 100, 110, 0x007F00);
+            choice = 1;
+            }
+        if(myNav[3] == 0 ){
+            uLCD.rectangle(20,90, 40, 110, 0x007F00);
+            uLCD.rectangle(80,90, 100, 110, 0xffff00);
+            choice = 2;
+            }
+        if(myNav[4] == 0){ //Joystick pressed to Select
+            if(choice == 1) {
+                //Restart and play again
+                initialize_game_board();
+                xCoor = 3;
+                yCoor = 4;
+                }
+            else{ //choice == 0
+                //Quit?
+            }
+        }       
+    } 
+}
+
 int main() {
-    initialize_game_board();
-    int xCoor = 3;
-    int yCoor = 4;
-    
-    
-    while(1) {
-        //with pullups a button hit is a "0" - "~" inverts data to leds
-        //~(myNav & 0x0F); //update leds with nav switch direction inputs
-        if(myNav[0] == 0 && xCoor != 0){xCoor --;}
-        if(myNav[1] == 0 && xCoor != 7){xCoor ++;}
-        if(myNav[2] == 0 && yCoor != 0){xCoor --;}
-        if(myNav[3] == 0 && yCoor != 7){xCoor ++;}
-        if(myNav.fire()) {Select(xCoor, yCoor);} // Press Down Joystick for Select
-        //or use - if(myNav[4]==0) mbedleds = 0x0F; //can index a switch bit like this
-        wait(0.02);
+    while (1) {
+       
+        initialize_game_board();
+        drawPieces();
+        while(!gameover) { //active game, checks game over
+            
+            // check inputs
+            while (!moved) {
+                drawCursor(xCoor, yCoor);
+                wait(0.02);
+                removeCursor(xCoor, yCoor);
+                //with pullups a button hit is a "0" - "~" inverts data to leds
+                //~(myNav & 0x0F); //update leds with nav switch direction inputs
+                if(myNav[0] == 0 && xCoor != 0){xCoor --;}
+                if(myNav[1] == 0 && xCoor != 7){xCoor ++;}
+                if(myNav[2] == 0 && yCoor != 7){yCoor ++;}
+                if(myNav[3] == 0 && yCoor != 0){yCoor --;}
+                if(myNav.fire()) {valid_move(xCoor, yCoor);} // Press Down Joystick for Select
+                //or use - if(myNav[4]==0) mbedleds = 0x0F; //can index a switch bit like this
+            }
+            moved = false;
+            // check game over
+            countPieces();
+            gameover = numBlack + numWhite == 64;
+        }
+        result();
     }
-
 }
 //initializeBoard();
 //drawBoard();