#include <Adafruit_ILI9341.h>
#include <Adafruit_GFX.h>
#define TFT_CS 5
#define TFT_DC 22
#define BUTTON1_PIN 14
#define BUTTON2_PIN 27
#define BUTTON3_PIN 12
#define BUTTON4_PIN 13
#define TFT_WIDTH 240
#define TFT_HEIGHT 320
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
const int BOARD_WIDTH = 7;
const int BOARD_HEIGHT = 6;
const int WINNING_CONDITION = 4;
const int BUTTON_DEBOUNCE_MS = 50;
int board[BOARD_HEIGHT][BOARD_WIDTH] = {0};
int currentPlayer = 1;
bool gameOver = false;
// Button variables
unsigned long buttonLastPressedTime[4] = {0};
int buttonPins[4] = {BUTTON1_PIN, BUTTON2_PIN, BUTTON3_PIN, BUTTON4_PIN};
void setup() {
Serial.begin(9600);
for (int i = 0; i < 4; i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
}
tft.begin();
tft.setRotation(3);
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
drawBoard();
}
void loop() {
unsigned long currentMillis = millis();
// Check button presses
for (int i = 0; i < 4; i++) {
if (currentMillis - buttonLastPressedTime[i] >= BUTTON_DEBOUNCE_MS) {
if (digitalRead(buttonPins[i]) == LOW) {
buttonLastPressedTime[i] = currentMillis;
handleButtonPress(i);
}
}
}
// Add the rest of your game logic here
}
int diskSize; // Declare diskSize variable outside the function
void drawBoard() {
tft.fillScreen(ILI9341_BLACK);
int cellWidth = tft.width() / BOARD_WIDTH;
int cellHeight = tft.height() / BOARD_HEIGHT;
// Draw grid lines
for (int x = cellWidth; x < tft.width(); x += cellWidth) {
tft.drawFastVLine(x, 0, tft.height(), ILI9341_WHITE);
}
for (int y = cellHeight; y < tft.height(); y += cellHeight) {
tft.drawFastHLine(0, y, tft.width(), ILI9341_WHITE);
}
}
void drawDisk(int row, int col) {
int cellWidth = tft.width() / BOARD_WIDTH;
int cellHeight = tft.height() / BOARD_HEIGHT;
int x = col * cellWidth;
int y = row * cellHeight;
int radius = min(cellWidth, cellHeight) / 2 - 2;
int centerX = x + cellWidth / 2;
int centerY = y + cellHeight / 2;
int color = (currentPlayer == 1) ? ILI9341_RED : ILI9341_YELLOW;
tft.fillCircle(centerX, centerY, radius, color);
}
void handleButtonPress(int buttonIndex) {
if (!gameOver) {
int column = buttonIndex; // Map button index to column number
if (isValidMove(column)) {
int row = dropDisk(column, currentPlayer);
drawDisk(row, column);
if (checkWin(row, column)) {
drawGameOver(currentPlayer);
gameOver = true;
} else if (isBoardFull()) {
drawGameOver(0); // Draw for a tie
gameOver = true;
} else {
switchPlayer();
}
}
} else {
resetGame();
}
}
bool isValidMove(int column) {
return (board[0][column] == 0);
}
int dropDisk(int column, int player) {
for (int row = BOARD_HEIGHT - 1; row >= 0; --row) {
if (board[row][column] == 0) {
board[row][column] = player;
return row;
}
}
return -1; // Invalid move
}
bool checkWin(int row, int col) {
int player = board[row][col];
// Check horizontal
int count = 1;
int left = col - 1;
int right = col + 1;
while (left >= 0 && board[row][left] == player) {
count++;
left--;
}
while (right < BOARD_WIDTH && board[row][right] == player) {
count++;
right++;
}
if (count >= WINNING_CONDITION) {
return true;
}
// Check vertical
count = 1;
int up = row - 1;
int down = row + 1;
while (up >= 0 && board[up][col] == player) {
count++;
up--;
}
while (down < BOARD_HEIGHT && board[down][col] == player) {
count++;
down++;
}
if (count >= WINNING_CONDITION) {
return true;
}
// Check diagonal (top-left to bottom-right)
count = 1;
int diagUpLeftRow = row - 1;
int diagUpLeftCol = col - 1;
int diagDownRightRow = row + 1;
int diagDownRightCol = col + 1;
while (diagUpLeftRow >= 0 && diagUpLeftCol >= 0 && board[diagUpLeftRow][diagUpLeftCol] == player) {
count++;
diagUpLeftRow--;
diagUpLeftCol--;
}
while (diagDownRightRow < BOARD_HEIGHT && diagDownRightCol < BOARD_WIDTH &&
board[diagDownRightRow][diagDownRightCol] == player) {
count++;
diagDownRightRow++;
diagDownRightCol++;
}
if (count >= WINNING_CONDITION) {
return true;
}
// Check diagonal (top-right to bottom-left)
count = 1;
int diagUpRightRow = row - 1;
int diagUpRightCol = col + 1;
int diagDownLeftRow = row + 1;
int diagDownLeftCol = col - 1;
while (diagUpRightRow >= 0 && diagUpRightCol < BOARD_WIDTH && board[diagUpRightRow][diagUpRightCol] == player) {
count++;
diagUpRightRow--;
diagUpRightCol++;
}
while (diagDownLeftRow < BOARD_HEIGHT && diagDownLeftCol >= 0 &&
board[diagDownLeftRow][diagDownLeftCol] == player) {
count++;
diagDownLeftRow++;
diagDownLeftCol--;
}
if (count >= WINNING_CONDITION) {
return true;
}
return false;
}
bool isBoardFull() {
for (int row = 0; row < BOARD_HEIGHT; row++) {
for (int col = 0; col < BOARD_WIDTH; col++) {
if (board[row][col] == 0) {
return false;
}
}
}
return true;
}
void switchPlayer() {
currentPlayer = (currentPlayer == 1) ? 2 : 1;
}
void resetGame() {
for (int row = 0; row < BOARD_HEIGHT; row++) {
for (int col = 0; col < BOARD_WIDTH; col++) {
board[row][col] = 0;
}
}
currentPlayer = 1;
gameOver = false;
drawBoard();
}
void drawGameOver(int winner) {
tft.setTextSize(3);
tft.setCursor(50, TFT_HEIGHT / 2 - 10);
if (winner == 0) {
tft.print("It's a tie!");
} else {
tft.print("Player ");
tft.print(winner);
tft.print(" wins!");
}
tft.setTextSize(2);
tft.setCursor(80, TFT_HEIGHT / 2 + 30);
tft.print("Press any button to restart");
}