/*
Connect 4
Arduinoified
Dec 30, 2023
- Added joystick
- Added action button
- Added 16x2 display functionality
- Wired 7x7 WS2812 RGBs
- Added reset game button
- Added horizontal and vertical win functionality
Dec 31, 2023
- Added 16x2 potentiotometer
- Added diagonal win functionality
*/
// include the library code:
#include <LiquidCrystal.h>
#include <FastLED.h>
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 11, en = 9, d4 = 4, d5 = 3, d6 = 2, d7 = 1;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int buttonPin = 5; // pin number of pushbutton
const int buttonResetPin = 6; // pin number of pushbutton
const int rows = 7;
const int cols = 7;
const int brightness = 255;
const int LED_PIN = 12;
const int NUM_LEDS = rows * cols;
CRGB leds[NUM_LEDS];
// variables will change:
int buttonState; // variable for reading the pushbutton status
int buttonResetState;
int rowPosition = 3; // selected column to drop piece
int PLAYER = 1;
int BOARD[cols][rows]; // 7x6 connect 4 board
int GAMEOVER = 0;
int REFRESH = 1;
/*
Board Map:
6 5 4 3 2 1 0
13 12 11 10 9 8 7
20 19 18 17 16 15 14
27 26 25 24 23 22 21
34 33 32 31 30 29 28
41 40 39 38 37 36 35
48 47 46 45 44 43 42
*/
void initializeGame();
void printBoard(int BOARD[cols][rows]);
void selectedPosition(int horzX, int &rowP, int PLAYER);
void storePosition(int &PLAYER);
void resetBoard();
void checkStatus();
void gameWon(int P);
void setup() {
initializeGame();
lcd.setCursor(0, 0);
lcd.print("Game is Ready.");
printBoard(BOARD);
Serial.begin(9600);
}
void loop() {
buttonState = digitalRead(buttonPin);
buttonResetState = digitalRead(buttonResetPin);
delay(100);
if (!GAMEOVER) selectedPosition(map(analogRead(A0), 0, 1023, 0, 2), rowPosition, PLAYER); // 0 is right, 2 is left
if (buttonState == HIGH && GAMEOVER == 0 && REFRESH == 0) {
storePosition(PLAYER);
lcd.setCursor(1, 1);
lcd.print(" STORED ");
checkStatus();
REFRESH = 1;
} else if (buttonState == LOW && GAMEOVER == 0 && REFRESH == 1) {
lcd.setCursor(1, 1);
lcd.print(" ");
REFRESH = 0;
}
if (buttonResetState == HIGH) {
resetBoard();
lcd.setCursor(0, 1);
lcd.print("BOARD RESET");
delay(200);
}
}
void initializeGame() {
lcd.begin(16, 2); // intializes the 16x2 lcd display
pinMode(buttonPin, INPUT); // initializes the pushbutton
pinMode(buttonResetPin, INPUT); // initializes the pushbutton
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS); // initialize leds
FastLED.setBrightness(brightness);
lcd.setCursor(4, 0);
lcd.print("Connect 4");
lcd.setCursor(2, 1);
lcd.print("Arduinoified!");
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(255, 0, 0);
FastLED.show();
delay(25);
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Align 4 in a row");
lcd.setCursor(5, 1);
lcd.print("to win!");
delay(3000);
lcd.clear();
}
void printBoard(int BOARD[cols][rows]) {
int i = 0;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (BOARD[c][r] == 3) { // PURPLE
leds[i] = CRGB(255,0,255);
} else if (BOARD[c][r] == 2) { // RED
leds[i] = CRGB(255,0,0);
} else if (BOARD[c][r] == 1) { // BLUE
leds[i] = CRGB(0,0,255);
} else if (BOARD[c][r] == 0) { // BLUE
leds[i] = CRGB(0,0,0);
}
i++;
}
}
FastLED.show();
return;
}
void selectedPosition(int horzX, int &rowP, int PLAYER) {
if (horzX == 1) {
} else if (horzX == 0 && rowPosition < (rows - 1)) {
rowP++;
} else if (horzX == 2 && rowPosition > 0) {
rowP--;
}
for (int i = 0; i < cols; i++) {
BOARD[i][0] = 3;
}
BOARD[rowP][0] = PLAYER;
printBoard(BOARD);
}
void storePosition(int &PLAYER) {
int x = rowPosition;
// position 3, add something here.
for (int y = 6; y >= 0; y--) {
if (BOARD[x][y] != 0) {
continue;
} else {
BOARD[x][y] = PLAYER;
if (PLAYER == 1) {
PLAYER = 2;
delay(100);
return;
} else if (PLAYER == 2) {
PLAYER = 1;
delay(100);
return;
}
break;
}
}
}
void resetBoard() {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
BOARD[i][j] = 0;
}
}
rowPosition = 3;
GAMEOVER = 0;
REFRESH = 1;
}
void checkStatus() {
// Winning counters if reached 4
int c1R = 0; // row for Player 1
int c2R = 0; // row for Player 2
int c1C = 0; // col for P1
int c2C = 0; // row for P2
int c1D = 0; // diag for P1
int c2D = 0; // diag for P2
// CHECK FOR VERTICAL WIN
for (int i = 0; i < cols; i++) {
for (int j = 3; j > 0; j--) {
if (BOARD[i][j] == 0) {
break;
} else if (BOARD[i][j] == 1) { // VERTICAL for P1
for (int k = 0; k < 4; k++) {
if (BOARD[i][j+k] == 1) {
c1C++;
} else {
c1C = 0;
break;
}
}
} else if (BOARD[i][j] == 2) { // VERTICAL for P2
for (int k = 0; k < 4; k++) {
if (BOARD[i][j+k] == 2) {
c2C++;
} else {
c2C = 0;
break;
}
}
}
if (c1C == 4) {
gameWon(1);
} else if (c2C == 4) {
gameWon(2);
}
//c1C, c2C = 0;
}
}
// CHECK FOR HORIZONTAL WIN
for (int j = 1; j < rows; j++) {
for (int i = 3; i > -1; i--) {
if (BOARD[i][j] == 0) {
break;
} else if (BOARD[i][j] == 1) { // HORIZONTAL for P1
for (int k = 0; k < 4; k++) {
if (BOARD[i+k][j] == 1) {
c1R++;
} else {
c1R = 0;
break;
}
}
} else if (BOARD[i][j] == 2) { // HORIZONTAL for P2
for (int k = 0; k < 4; k++) {
if (BOARD[i+k][j] == 2) {
c2R++;
} else {
c2R = 0;
break;
}
}
}
if (c1R == 4) {
gameWon(1);
} else if (c2R == 4) {
gameWon(2);
}
//c1R, c2R = 0;
}
}
// CHECK FOR DIAGONAL WIN
for (int i = 0; i < cols; i++) {
for (int j = 3; j > 0; j--) {
if (BOARD[i][j] == 0) {
continue;
} else
{
c1D=0;
c2D=0;
for (int k = 0; k < 4; k++) { // diagonally down and right
if ((i-3) < 0 || (j+3) > cols) {
break;
} else if (BOARD[i-k][j+k] == 1) {
c1D++;
} else if (BOARD[i+k][j+k] == 2) {
c2D++;
}
}
if (c1D == 4) {
gameWon(1);
} else if (c2D == 4) {
gameWon(2);
}
c1D=0;
c2D=0;
for (int k = 0; k < 4; k++) { // diagonally down and left
if ((i+3) > rows || (j+3) > cols) {
break;
} else if (BOARD[i+k][j+k] == 1) {
c1D++;
} else if (BOARD[i+k][j+k] == 2) {
c2D++;
}
}
if (c1D == 4) {
gameWon(1);
} else if (c2D == 4) {
gameWon(2);
}
}
}
}
}
void gameWon(int P) {
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("GAME OVER");
lcd.setCursor(0, 1);
lcd.print("PLAYER ");
lcd.print(P);
lcd.print(" W!");
Serial.println();
Serial.print("PLAYER ");
Serial.print(P);
Serial.print(" WINS!");
for (int i = 0; i < cols; i++) {
BOARD[i][0] = P;
}
printBoard(BOARD);
GAMEOVER = 1;
}