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

Committer:
hdao9
Date:
Sun Apr 22 00:25:22 2018 +0000
Revision:
2:1525f7ae330e
Parent:
1:85d63d7193e3
Child:
4:37b7ed4aa26b
finished code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hdao9 0:f0807589902f 1 #include "mbed.h"
hdao9 0:f0807589902f 2 #include "NeoStrip.h"
hdao9 0:f0807589902f 3 #include "PinDetect.h"
hdao9 1:85d63d7193e3 4 #include "Matrix.h"
hdao9 0:f0807589902f 5
hdao9 0:f0807589902f 6 #define N 64
hdao9 0:f0807589902f 7
hdao9 2:1525f7ae330e 8 NeoStrip strip(p18, N); //8x8 neopixel matrix with each neopixel addressable by its index which range from 0 to 63
hdao9 2:1525f7ae330e 9 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
hdao9 1:85d63d7193e3 10
hdao9 0:f0807589902f 11 PinDetect right(p5);
hdao9 0:f0807589902f 12 PinDetect left(p7);
hdao9 0:f0807589902f 13 PinDetect center(p8);
hdao9 0:f0807589902f 14
hdao9 2:1525f7ae330e 15 int pos = 0; //current position of led in Neopixel index
hdao9 1:85d63d7193e3 16 int row = 0;
hdao9 1:85d63d7193e3 17 int col = 0;
hdao9 2:1525f7ae330e 18 int winmode = 0; //0 means the game is not won, 1-4 are different ways to win
hdao9 0:f0807589902f 19
hdao9 0:f0807589902f 20 int red = 0xFF0000;
hdao9 0:f0807589902f 21 int blue = 0x0000FF;
hdao9 0:f0807589902f 22 int color = red;
hdao9 1:85d63d7193e3 23 int winningcolor = 0;
hdao9 0:f0807589902f 24
hdao9 2:1525f7ae330e 25 void alloff() //turn off all neopixel at the beginning
hdao9 0:f0807589902f 26 {
hdao9 0:f0807589902f 27 for (int i = 0; i < N; i++)
hdao9 0:f0807589902f 28 strip.setPixel(i, 0, 0, 0);
hdao9 0:f0807589902f 29 strip.write();
hdao9 0:f0807589902f 30 }
hdao9 0:f0807589902f 31
hdao9 2:1525f7ae330e 32 int matrix2index(int r, int c) //convert row,col of matrix to index of neopixel that range from 0 to 63
hdao9 1:85d63d7193e3 33 {
hdao9 1:85d63d7193e3 34 return (r-1)*8 + c - 1;
hdao9 1:85d63d7193e3 35 }
hdao9 1:85d63d7193e3 36
hdao9 2:1525f7ae330e 37 //when the game is won, flash the neopixels that lead to winning forever until the game is restarted
hdao9 1:85d63d7193e3 38 void display_winner(int mode, int r, int c, int wincolor)
hdao9 1:85d63d7193e3 39 {
hdao9 1:85d63d7193e3 40 switch (mode)
hdao9 1:85d63d7193e3 41 {
hdao9 1:85d63d7193e3 42 case 1:
hdao9 1:85d63d7193e3 43 while (1)
hdao9 1:85d63d7193e3 44 {
hdao9 1:85d63d7193e3 45 strip.setPixel(matrix2index(r,c), wincolor);
hdao9 1:85d63d7193e3 46 strip.setPixel(matrix2index(r,c+1), wincolor);
hdao9 1:85d63d7193e3 47 strip.setPixel(matrix2index(r,c+2), wincolor);
hdao9 1:85d63d7193e3 48 strip.setPixel(matrix2index(r,c+3), wincolor);
hdao9 1:85d63d7193e3 49 strip.write();
hdao9 1:85d63d7193e3 50 wait(0.2);
hdao9 1:85d63d7193e3 51 strip.setPixel(matrix2index(r,c), 0, 0, 0);
hdao9 1:85d63d7193e3 52 strip.setPixel(matrix2index(r,c+1), 0, 0, 0);
hdao9 1:85d63d7193e3 53 strip.setPixel(matrix2index(r,c+2), 0, 0, 0);
hdao9 1:85d63d7193e3 54 strip.setPixel(matrix2index(r,c+3), 0, 0, 0);
hdao9 1:85d63d7193e3 55 strip.write();
hdao9 1:85d63d7193e3 56 wait(0.2);
hdao9 1:85d63d7193e3 57 }
hdao9 1:85d63d7193e3 58 case 2:
hdao9 1:85d63d7193e3 59 while (1)
hdao9 1:85d63d7193e3 60 {
hdao9 1:85d63d7193e3 61 strip.setPixel(matrix2index(r,c), wincolor);
hdao9 1:85d63d7193e3 62 strip.setPixel(matrix2index(r+1,c), wincolor);
hdao9 1:85d63d7193e3 63 strip.setPixel(matrix2index(r+2,c), wincolor);
hdao9 1:85d63d7193e3 64 strip.setPixel(matrix2index(r+3,c), wincolor);
hdao9 1:85d63d7193e3 65 strip.write();
hdao9 1:85d63d7193e3 66 wait(0.2);
hdao9 1:85d63d7193e3 67 strip.setPixel(matrix2index(r,c), 0, 0, 0);
hdao9 1:85d63d7193e3 68 strip.setPixel(matrix2index(r+1,c), 0, 0, 0);
hdao9 1:85d63d7193e3 69 strip.setPixel(matrix2index(r+2,c), 0, 0, 0);
hdao9 1:85d63d7193e3 70 strip.setPixel(matrix2index(r+3,c), 0, 0, 0);
hdao9 1:85d63d7193e3 71 strip.write();
hdao9 1:85d63d7193e3 72 wait(0.2);
hdao9 1:85d63d7193e3 73 }
hdao9 1:85d63d7193e3 74 case 3:
hdao9 1:85d63d7193e3 75 while (1)
hdao9 1:85d63d7193e3 76 {
hdao9 1:85d63d7193e3 77 strip.setPixel(matrix2index(r,c), wincolor);
hdao9 1:85d63d7193e3 78 strip.setPixel(matrix2index(r+1,c+1), wincolor);
hdao9 1:85d63d7193e3 79 strip.setPixel(matrix2index(r+2,c+2), wincolor);
hdao9 1:85d63d7193e3 80 strip.setPixel(matrix2index(r+3,c+3), wincolor);
hdao9 1:85d63d7193e3 81 strip.write();
hdao9 1:85d63d7193e3 82 wait(0.2);
hdao9 1:85d63d7193e3 83 strip.setPixel(matrix2index(r,c), 0, 0, 0);
hdao9 1:85d63d7193e3 84 strip.setPixel(matrix2index(r+1,c+1), 0, 0, 0);
hdao9 1:85d63d7193e3 85 strip.setPixel(matrix2index(r+2,c+2), 0, 0, 0);
hdao9 1:85d63d7193e3 86 strip.setPixel(matrix2index(r+3,c+3), 0, 0, 0);
hdao9 1:85d63d7193e3 87 strip.write();
hdao9 1:85d63d7193e3 88 wait(0.2);
hdao9 1:85d63d7193e3 89 }
hdao9 1:85d63d7193e3 90 case 4:
hdao9 1:85d63d7193e3 91 while (1)
hdao9 1:85d63d7193e3 92 {
hdao9 1:85d63d7193e3 93 strip.setPixel(matrix2index(r,c), wincolor);
hdao9 1:85d63d7193e3 94 strip.setPixel(matrix2index(r+1,c-1), wincolor);
hdao9 1:85d63d7193e3 95 strip.setPixel(matrix2index(r+2,c-2), wincolor);
hdao9 1:85d63d7193e3 96 strip.setPixel(matrix2index(r+3,c-3), wincolor);
hdao9 1:85d63d7193e3 97 strip.write();
hdao9 1:85d63d7193e3 98 wait(0.2);
hdao9 1:85d63d7193e3 99 strip.setPixel(matrix2index(r,c), 0, 0, 0);
hdao9 1:85d63d7193e3 100 strip.setPixel(matrix2index(r+1,c-1), 0, 0, 0);
hdao9 1:85d63d7193e3 101 strip.setPixel(matrix2index(r+2,c-2), 0, 0, 0);
hdao9 1:85d63d7193e3 102 strip.setPixel(matrix2index(r+3,c-3), 0, 0, 0);
hdao9 1:85d63d7193e3 103 strip.write();
hdao9 1:85d63d7193e3 104 wait(0.2);
hdao9 1:85d63d7193e3 105 }
hdao9 1:85d63d7193e3 106 default:
hdao9 1:85d63d7193e3 107 break;
hdao9 1:85d63d7193e3 108 }
hdao9 1:85d63d7193e3 109 }
hdao9 1:85d63d7193e3 110
hdao9 1:85d63d7193e3 111 void check_winner()
hdao9 1:85d63d7193e3 112 {
hdao9 1:85d63d7193e3 113 //check 4 in a row
hdao9 1:85d63d7193e3 114 for (int r = 1; r < 9; r++)
hdao9 1:85d63d7193e3 115 {
hdao9 1:85d63d7193e3 116 for (int c = 1; c < 6; c++)
hdao9 1:85d63d7193e3 117 {
hdao9 1:85d63d7193e3 118 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))
hdao9 1:85d63d7193e3 119 {//have winner
hdao9 1:85d63d7193e3 120 row = r; col = c; winmode = 1; winningcolor = color;
hdao9 2:1525f7ae330e 121 return; //avoid the uncessary of continue to check
hdao9 1:85d63d7193e3 122 }
hdao9 1:85d63d7193e3 123 }
hdao9 1:85d63d7193e3 124 }
hdao9 1:85d63d7193e3 125 //check 4 in a col
hdao9 1:85d63d7193e3 126 for (int c = 1; c < 9; c++)
hdao9 1:85d63d7193e3 127 {
hdao9 1:85d63d7193e3 128 for (int r = 1; r < 6; r++)
hdao9 1:85d63d7193e3 129 {
hdao9 1:85d63d7193e3 130 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))
hdao9 1:85d63d7193e3 131 {//have winner
hdao9 1:85d63d7193e3 132 row = r; col = c; winmode = 2; winningcolor = color;
hdao9 2:1525f7ae330e 133 return;
hdao9 1:85d63d7193e3 134 }
hdao9 1:85d63d7193e3 135 }
hdao9 1:85d63d7193e3 136 }
hdao9 1:85d63d7193e3 137 //check 4 in a forward diagonal
hdao9 1:85d63d7193e3 138 for (int r = 3; r < 6; r++)
hdao9 1:85d63d7193e3 139 {
hdao9 1:85d63d7193e3 140 for (int c = 1; c < 5; c++)
hdao9 1:85d63d7193e3 141 {
hdao9 1:85d63d7193e3 142 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))
hdao9 2:1525f7ae330e 143 {//have winner
hdao9 1:85d63d7193e3 144 row = r; col = c; winmode = 3; winningcolor = color;
hdao9 2:1525f7ae330e 145 return;
hdao9 1:85d63d7193e3 146 }
hdao9 1:85d63d7193e3 147 }
hdao9 1:85d63d7193e3 148 }
hdao9 1:85d63d7193e3 149 //check 4 in a reverse diagonal
hdao9 1:85d63d7193e3 150 for (int r = 3; r < 6; r++)
hdao9 1:85d63d7193e3 151 {
hdao9 1:85d63d7193e3 152 for (int c = 4; c < 8; c++)
hdao9 1:85d63d7193e3 153 {
hdao9 1:85d63d7193e3 154 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))
hdao9 2:1525f7ae330e 155 {//have winner
hdao9 1:85d63d7193e3 156 row = r; col = c; winmode = 4; winningcolor = color;
hdao9 2:1525f7ae330e 157 return;
hdao9 1:85d63d7193e3 158 }
hdao9 1:85d63d7193e3 159 }
hdao9 1:85d63d7193e3 160 }
hdao9 1:85d63d7193e3 161 }
hdao9 1:85d63d7193e3 162
hdao9 2:1525f7ae330e 163 void right_hit_callback (void) { //move to the flashing neopixel to the right
hdao9 0:f0807589902f 164 //led1 = !led1;
hdao9 2:1525f7ae330e 165 strip.setPixel(pos, 0, 0, 0); //turn off the current neopixel
hdao9 2:1525f7ae330e 166 if (pos < 6) pos = pos + 1; //move the neopixel to the right if not out of range
hdao9 0:f0807589902f 167 }
hdao9 2:1525f7ae330e 168 void left_hit_callback (void) { //move the flashing neopixel to the left
hdao9 0:f0807589902f 169 //led3 = !led3;
hdao9 0:f0807589902f 170 strip.setPixel(pos, 0, 0, 0);
hdao9 0:f0807589902f 171 if (pos > 0) pos = pos - 1;
hdao9 0:f0807589902f 172 }
hdao9 0:f0807589902f 173
hdao9 0:f0807589902f 174 void center_hit_callback (void) { //drop the coin
hdao9 2:1525f7ae330e 175 //turn off the flashing neopixel on top row
hdao9 0:f0807589902f 176 strip.setPixel(pos, 0, 0, 0);
hdao9 2:1525f7ae330e 177 //then coin need to appear at the current column, on the lowest row that not occupied
hdao9 0:f0807589902f 178 col = pos + 1;
hdao9 1:85d63d7193e3 179 for(row = 8; row > 1; row-- )
hdao9 0:f0807589902f 180 {
hdao9 2:1525f7ae330e 181 if (board.getNumber(row,col) == 0) break; //break out of loop when found the lowest unoccupied row
hdao9 0:f0807589902f 182 }
hdao9 2:1525f7ae330e 183 //convert to neopixel index to turn of that neopixel, but only if not all rows in 6x7 board are occupied
hdao9 1:85d63d7193e3 184 if (row > 2) strip.setPixel(matrix2index(row,col), color);
hdao9 1:85d63d7193e3 185 else return;
hdao9 0:f0807589902f 186 //after added LED to that position
hdao9 1:85d63d7193e3 187 if (color == red)
hdao9 1:85d63d7193e3 188 {
hdao9 1:85d63d7193e3 189 board.add( row, col, 1.0);//update matrix to have a matrix to check winner
hdao9 2:1525f7ae330e 190 check_winner(); //check if the winning move is made
hdao9 1:85d63d7193e3 191 color = blue; //change player/color
hdao9 1:85d63d7193e3 192 }
hdao9 1:85d63d7193e3 193 else
hdao9 1:85d63d7193e3 194 {
hdao9 1:85d63d7193e3 195 board.add( row, col, 2.0);
hdao9 1:85d63d7193e3 196 check_winner();
hdao9 1:85d63d7193e3 197 color = red;
hdao9 2:1525f7ae330e 198 }
hdao9 0:f0807589902f 199 }
hdao9 0:f0807589902f 200
hdao9 2:1525f7ae330e 201 int main() {
hdao9 2:1525f7ae330e 202 //initialize the matrix to 0 meaning all rows and cols are unoccupied
hdao9 2:1525f7ae330e 203 board << 0 << 0 << 0 << 0 << 0 << 0 << 0
hdao9 1:85d63d7193e3 204 << 0 << 0 << 0 << 0 << 0 << 0 << 0
hdao9 1:85d63d7193e3 205 << 0 << 0 << 0 << 0 << 0 << 0 << 0
hdao9 1:85d63d7193e3 206 << 0 << 0 << 0 << 0 << 0 << 0 << 0
hdao9 1:85d63d7193e3 207 << 0 << 0 << 0 << 0 << 0 << 0 << 0
hdao9 1:85d63d7193e3 208 << 0 << 0 << 0 << 0 << 0 << 0 << 0
hdao9 1:85d63d7193e3 209 << 0 << 0 << 0 << 0 << 0 << 0 << 0
hdao9 1:85d63d7193e3 210 << 0 << 0 << 0 << 0 << 0 << 0 << 0;
hdao9 1:85d63d7193e3 211
hdao9 0:f0807589902f 212 // Use internal pullups for pushbutton
hdao9 0:f0807589902f 213 right.mode(PullUp);
hdao9 0:f0807589902f 214 left.mode(PullUp);
hdao9 2:1525f7ae330e 215 center.mode(PullUp);
hdao9 0:f0807589902f 216 // Delay for initial pullup to take effect
hdao9 0:f0807589902f 217 wait(.05);
hdao9 0:f0807589902f 218 // Setup Interrupt callback functions for a pb hit
hdao9 0:f0807589902f 219 right.attach_deasserted(&right_hit_callback); //used to move coin
hdao9 0:f0807589902f 220 left.attach_deasserted(&left_hit_callback); //used to move coin
hdao9 0:f0807589902f 221 center.attach_deasserted(&center_hit_callback); //used to drop coin
hdao9 0:f0807589902f 222 // Start sampling pb inputs using interrupts
hdao9 0:f0807589902f 223 right.setSampleFrequency();
hdao9 0:f0807589902f 224 left.setSampleFrequency();
hdao9 0:f0807589902f 225 center.setSampleFrequency();
hdao9 0:f0807589902f 226 wait(.01);
hdao9 0:f0807589902f 227
hdao9 0:f0807589902f 228 float bright = 0.2; // 20% is plenty for indoor use
hdao9 0:f0807589902f 229 strip.setBrightness(bright); // set default brightness
hdao9 2:1525f7ae330e 230 alloff(); //initial all neopixels to off
hdao9 0:f0807589902f 231
hdao9 2:1525f7ae330e 232 while(1)
hdao9 0:f0807589902f 233 {
hdao9 2:1525f7ae330e 234 //winmode is initialized to 0 (not won and the function return)
hdao9 2:1525f7ae330e 235 //winmode is changed in check_winner
hdao9 2:1525f7ae330e 236 //need to call display_winner here rather than calling from interrupt fuction because display_winner loop forever if the game is won
hdao9 1:85d63d7193e3 237 display_winner(winmode,row,col,winningcolor);
hdao9 2:1525f7ae330e 238 //flashing the current position indicating which col will the disc be dropped at
hdao9 0:f0807589902f 239 strip.setPixel(pos, color);
hdao9 0:f0807589902f 240 strip.write();
hdao9 0:f0807589902f 241 wait(0.2);
hdao9 0:f0807589902f 242 strip.setPixel(pos, 0, 0, 0);
hdao9 0:f0807589902f 243 strip.write();
hdao9 0:f0807589902f 244 wait(0.2);
hdao9 2:1525f7ae330e 245 }
hdao9 0:f0807589902f 246 }