Connect 4 game using the NeoPixel Matrix 8x8 RGB LED and a 5-way Tactile Navigation Switch.

Dependencies:   Matrix PinDetect mbed

Fork of 4180_Project_Finalcode by 4180

main.cpp

Committer:
Josahty
Date:
2018-04-26
Revision:
4:37b7ed4aa26b
Parent:
2:1525f7ae330e

File content as of revision 4:37b7ed4aa26b:

// ======================================================================
// Program to create a Connect 4 game using a NeoPixel Matrix 8x8 RGB LED
// and a 5-way Tactile Navigation Switch.
// Ha Dao and Joseph Doughty
// April 25, 2018
// Georgia Institute of Technology, ECE4011 Final Project
//=======================================================================

#include "mbed.h"
#include "NeoStrip.h"
#include "PinDetect.h"
#include "Matrix.h"

#define N 64

NeoStrip strip(p18, N); // 8x8 neopixel matrix with each "pixel" LED addressable by its index, which range from 0 to 63 
Matrix board(8,7); // the Connect Four game board is a 6x7 matrix, the NeoPixel matrix is 8x8, created an 8x7 matrix to keep track of moves
             
PinDetect right(p5);
PinDetect left(p7);
PinDetect center(p8);
 
int pos = 0; //c urrent position of LED in Neopixel index
int row = 0; 
int col = 0;
int winmode = 0; //0 means the game hasn't yet been won, 1-4 are different ways to win

int red = 0xFF0000; // one player is red
int blue = 0x0000FF; // other player is blue
int color = red; // begin the game with the red player
int winningcolor = 0;

// clears the LED matrix by turning each one off
void alloff()
{
    for (int i = 0; i < N; i++)
        strip.setPixel(i, 0, 0, 0);
    strip.write();
}

// converts row and column indexes of a matrix to the corresponding index of the NeoPixel
int matrix2index(int r, int c) 
{
   return (r-1)*8 + c - 1;
}

// when the game is won, flashes the four LEDs corresponding to the winning move
// this will continue until the game is reset via the mbed reset button
void display_winner(int mode, int r, int c, int wincolor)
{
    switch (mode)
    {
        case 1:
            while (1)
                {
                   strip.setPixel(matrix2index(r,c), wincolor);
                   strip.setPixel(matrix2index(r,c+1), wincolor);
                   strip.setPixel(matrix2index(r,c+2), wincolor);
                   strip.setPixel(matrix2index(r,c+3), wincolor);
                   strip.write();
                   wait(0.2);
                   strip.setPixel(matrix2index(r,c), 0, 0, 0);
                   strip.setPixel(matrix2index(r,c+1), 0, 0, 0);
                   strip.setPixel(matrix2index(r,c+2), 0, 0, 0);
                   strip.setPixel(matrix2index(r,c+3), 0, 0, 0);
                   strip.write();
                   wait(0.2);
                }
        case 2:
            while (1)
                {
                   strip.setPixel(matrix2index(r,c), wincolor);
                   strip.setPixel(matrix2index(r+1,c), wincolor);
                   strip.setPixel(matrix2index(r+2,c), wincolor);
                   strip.setPixel(matrix2index(r+3,c), wincolor);
                   strip.write();
                   wait(0.2);
                   strip.setPixel(matrix2index(r,c), 0, 0, 0);
                   strip.setPixel(matrix2index(r+1,c), 0, 0, 0);
                   strip.setPixel(matrix2index(r+2,c), 0, 0, 0);
                   strip.setPixel(matrix2index(r+3,c), 0, 0, 0);
                   strip.write();
                   wait(0.2);
                }
        case 3:
            while (1)
                {
                   strip.setPixel(matrix2index(r,c), wincolor);
                   strip.setPixel(matrix2index(r+1,c+1), wincolor);
                   strip.setPixel(matrix2index(r+2,c+2), wincolor);
                   strip.setPixel(matrix2index(r+3,c+3), wincolor);
                   strip.write();
                   wait(0.2);
                   strip.setPixel(matrix2index(r,c), 0, 0, 0);
                   strip.setPixel(matrix2index(r+1,c+1), 0, 0, 0);
                   strip.setPixel(matrix2index(r+2,c+2), 0, 0, 0);
                   strip.setPixel(matrix2index(r+3,c+3), 0, 0, 0);
                   strip.write();
                   wait(0.2);
                }
        case 4:
            while (1)
                {
                   strip.setPixel(matrix2index(r,c), wincolor);
                   strip.setPixel(matrix2index(r+1,c-1), wincolor);
                   strip.setPixel(matrix2index(r+2,c-2), wincolor);
                   strip.setPixel(matrix2index(r+3,c-3), wincolor);
                   strip.write();
                   wait(0.2);
                   strip.setPixel(matrix2index(r,c), 0, 0, 0);
                   strip.setPixel(matrix2index(r+1,c-1), 0, 0, 0);
                   strip.setPixel(matrix2index(r+2,c-2), 0, 0, 0);
                   strip.setPixel(matrix2index(r+3,c-3), 0, 0, 0);
                   strip.write();
                   wait(0.2);
                }
        default:
            break;
    }
}

// checks to see if the game has been won; a game is won if either player has
// four markers in a row horizontally, diagonally, or vertically
void check_winner()
{
    //checks for four markers in a row
    for (int r = 1; r < 9; r++)    
    {
        for (int c = 1; c < 6; c++)
        {
            if (board.getNumber(r,c) != 0 && board.getNumber(r,c) == board.getNumber(r,c+1) && board.getNumber(r,c+1) == board.getNumber(r,c+2) && board.getNumber(r,c+2) == board.getNumber(r,c+3))
            {//have winner
                row = r; col = c; winmode = 1; winningcolor = color;
                return; //avoid the uncessary of continue to check
            }
        }
    }
    //checks for four markers in a column
    for (int c = 1; c < 9; c++)
    {
        for (int r = 1; r < 6; r++)
        {
            if (board.getNumber(r,c) != 0 && board.getNumber(r,c) == board.getNumber(r+1,c) && board.getNumber(r+1,c) == board.getNumber(r+2,c) && board.getNumber(r+2,c) == board.getNumber(r+3,c))
            {//have winner
                row = r; col = c; winmode = 2; winningcolor = color;
                return;
            }
        }
    }
    //checks for four markers in a forward (right-leaning) diagonal
    for (int r = 3; r < 6; r++)
    {
        for (int c = 1; c < 5; c++)
        {
            if (board.getNumber(r,c) != 0 && board.getNumber(r,c) == board.getNumber(r+1,c+1) && board.getNumber(r+1,c+1) == board.getNumber(r+2,c+2) && board.getNumber(r+2,c+2) == board.getNumber(r+3,c+3))
            {//have winner
                row = r; col = c; winmode = 3; winningcolor = color;
                return;
            }   
        }
    }
    //checks for four markers in a reverse (left-leaning) diagonal
    for (int r = 3; r < 6; r++)
    {
        for (int c = 4; c < 8; c++)
        {
            if (board.getNumber(r,c) != 0 && board.getNumber(r,c) == board.getNumber(r+1,c-1) && board.getNumber(r+1,c-1) == board.getNumber(r+2,c-2) && board.getNumber(r+2,c-2) == board.getNumber(r+3,c-3))
            {//have winner
                row = r; col = c; winmode = 4; winningcolor = color;
                return;
            }   
        }
    }
}

// move the player marker to the right
void right_hit_callback (void) { 
    strip.setPixel(pos, 0, 0, 0); // turn off the current LED
    if (pos < 6) pos = pos + 1; // only move to the right if not at "screen" edge
}

// move the player marker to the left
void left_hit_callback (void) { 
    strip.setPixel(pos, 0, 0, 0); // turn off the current LED
    if (pos > 0) pos = pos - 1; // only move to the left if not at "screen" edge
}

// drop the player marker straight down the current column
void center_hit_callback (void) { 
    strip.setPixel(pos, 0, 0, 0); // turn off the current LED
    // show marker at lowest unoccupied position in the selected column
    col = pos + 1;
    for(row = 8; row > 1; row-- )
    {
        if (board.getNumber(row,col) == 0) break; // break upon finding lowest unoccupied position
    }
    //convert to neopixel index to turn of that neopixel, but only if not all rows in 6x7 board are occupied 
    if (row > 2) strip.setPixel(matrix2index(row,col), color);
    else return;

    if (color == red) // if it's red player's turn,
    {
        board.add( row, col, 1.0); // update matrix to have a matrix to check winner
        check_winner(); // check board state to see if the game has been won
        color = blue; // switch to the blue player
    }
    else // else, if it's blue player's turn,
    {
        board.add( row, col, 2.0); // update matrix to have a matrix to check winner
        check_winner(); // check board state to see if the game has been won
        color = red; // switch to the red player
    }
}

int main() {
   // initialize the matrix to 0 so that all rows and columns are unoccupied
   board << 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;
             
    // use internal pullups for pushbutton
    right.mode(PullUp);    
    left.mode(PullUp);    
    center.mode(PullUp);
     
    // delay for initial pullup to take effect
    wait(.05);
    
    // setup interrupt callback functions for a pb hit
    right.attach_deasserted(&right_hit_callback); // used to move player marker
    left.attach_deasserted(&left_hit_callback);  // used to move player marker
    center.attach_deasserted(&center_hit_callback); // used to drop player marker
                     
    // start sampling inputs using interrupts
    right.setSampleFrequency();
    left.setSampleFrequency();
    center.setSampleFrequency();
    wait(.01);
    
    float bright = 0.2; // 20% brightness is plenty for indoor visibility
    strip.setBrightness(bright);    // set default brightness
    alloff(); // initialize all of the NeoPixel LEDs to be off
    
    while(1)
    {
        // if the game has been won, display the winning move
        display_winner(winmode,row,col,winningcolor);
        
        // flash the LED corresponding to the currently selected player marker location
        strip.setPixel(pos, color);
        strip.write();
        wait(0.2);
        strip.setPixel(pos, 0, 0, 0);
        strip.write();
        wait(0.2);
    }    
}