I am trying to make a connect4 game. need help

i am trying to make a connect 4 game with led's being wired to each output of a mega arduino. My problem right now is that when i press the buttons to move around the led if one has been saved as on it turns off after i move off it.

const int buttonPin = 2;
const int subButtonPin = 3;
const int add4ButtonPin = 4;
const int sub4ButtonPin = 5;
const int groupTogglePin = 6;

const int group1LedPins[] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37};
const int group2LedPins[] = {38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53};

const int numLeds = sizeof(group1LedPins) / sizeof(group1LedPins[0]);

int currentLedGroup = 1;
int lastActiveLedGroup1 = 0;
int lastActiveLedGroup2 = 0;

bool group1Initialized = false;
bool group2Initialized = false;

int group1win[] = {22, 23, 24, 25};
int group2win[] = {26, 27, 28, 29};
int group3win[] = {30, 31, 32, 33};
int group4win[] = {34, 35, 36, 37};

int group5win[] = {22, 26, 30, 34};
int group6win[] = {23, 27, 31, 35};
int group7win[] = {24, 28, 32, 36};
int group8win[] = {25, 29, 33, 37};

int group9win[] = {22, 27, 32, 37};
int group10win[] = {25, 28, 31, 34};

int group11win[] = {38, 39, 40, 41};
int group12win[] = {42, 43, 44, 45};
int group13win[] = {46, 47, 48, 49};
int group14win[] = {50, 51, 52, 53};

int group15win[] = {38, 42, 46, 50};
int group16win[] = {39, 43, 47, 51};
int group17win[] = {40, 44, 48, 52};
int group18win[] = {41, 45, 49, 53};

int group19win[] = {38, 43, 48, 53};
int group20win[] = {41, 44, 47, 50};


const int numGroups = 20;
int* winningGroups[numGroups] = {
  group1win, group2win, group3win, group4win,
  group5win, group6win, group7win, group8win,
  group9win, group10win, group11win, group12win,
   group13win, group14win,
  group15win, group16win, group17win, group18win,
  group19win, group20win,
};

const int numLedss = 32; 




void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(subButtonPin, INPUT);
  pinMode(add4ButtonPin, INPUT);
  pinMode(sub4ButtonPin, INPUT);
  pinMode(groupTogglePin, INPUT);

  for (int i = 0; i < numLeds; i++) {
    pinMode(group1LedPins[i], OUTPUT);
    pinMode(group2LedPins[i], OUTPUT);
    digitalWrite(group1LedPins[i], LOW);
    digitalWrite(group2LedPins[i], LOW);
  }

  // Set the first LED in the first group (pin 22) to HIGH at the start
  digitalWrite(group1LedPins[lastActiveLedGroup1], HIGH);

for (int i = 0; i < numLeds; i++) {
    pinMode(i + 22, OUTPUT);  // Assuming LEDs are connected to pins 22 to 29
     pinMode(i + 38, OUTPUT);
  }




  


}


void loop() {
  if (digitalRead(groupTogglePin) == HIGH) {
    toggleLedGroup();
    delay(200);
  }

  if (currentLedGroup == 1) {
    handleButtonPress(group1LedPins, lastActiveLedGroup1, group2LedPins);
  } else if (currentLedGroup == 2) {
    handleButtonPress(group2LedPins, lastActiveLedGroup2, group1LedPins);
  }
}

void handleButtonPress(int ledGroup[], int &lastActiveLed, const int otherGroupPins[]) {
  if (digitalRead(buttonPin) == HIGH) {
    if (digitalRead(ledGroup[lastActiveLed]) == LOW && !isCorrespondingLedOn(otherGroupPins, lastActiveLed)) {
      digitalWrite(ledGroup[lastActiveLed], HIGH);
    } else {
      advanceLed(ledGroup, lastActiveLed);
    }
    delay(200);
  }

  if (digitalRead(subButtonPin) == HIGH) {
    if (digitalRead(ledGroup[lastActiveLed]) == LOW && !isCorrespondingLedOn(otherGroupPins, lastActiveLed)) {
      digitalWrite(ledGroup[lastActiveLed], HIGH);
    } else {
      subtractLed(ledGroup, lastActiveLed);
    }
    delay(200);
  }

  if (digitalRead(add4ButtonPin) == HIGH) {
    advanceLedBy(ledGroup, lastActiveLed, 4);
    delay(200);
  }

  if (digitalRead(sub4ButtonPin) == HIGH) {
    subtractLedBy(ledGroup, lastActiveLed, 4);
    delay(200);
  }
}

void toggleLedGroup() {
  if (currentLedGroup == 1) {
    lastActiveLedGroup1 = findLastActiveLed(group1LedPins);
    turnOffCorrespondingLed(group2LedPins, lastActiveLedGroup1);

    lastActiveLedGroup2 = 0;
    digitalWrite(group2LedPins[lastActiveLedGroup2], HIGH);

    currentLedGroup = 2;
  } else {
    lastActiveLedGroup2 = findLastActiveLed(group2LedPins);
    turnOffCorrespondingLed(group1LedPins, lastActiveLedGroup2);

    lastActiveLedGroup1 = 0;
    digitalWrite(group1LedPins[lastActiveLedGroup1], HIGH);

    currentLedGroup = 1;
  }
}

void advanceLed(int ledGroup[], int &lastActiveLed) {
  digitalWrite(ledGroup[lastActiveLed], LOW);
  lastActiveLed = (lastActiveLed + 1) % numLeds;
  digitalWrite(ledGroup[lastActiveLed], HIGH);
}

void subtractLed(int ledGroup[], int &lastActiveLed) {
  digitalWrite(ledGroup[lastActiveLed], LOW);
  lastActiveLed = (lastActiveLed - 1 + numLeds) % numLeds;
  digitalWrite(ledGroup[lastActiveLed], HIGH);
}

void advanceLedBy(int ledGroup[], int &lastActiveLed, int steps) {
  for (int i = 0; i < steps; i++) {
    advanceLed(ledGroup, lastActiveLed);
    delay(50);
  }
}

void subtractLedBy(int ledGroup[], int &lastActiveLed, int steps) {
  for (int i = 0; i < steps; i++) {
    subtractLed(ledGroup, lastActiveLed);
    delay(50);
  }
}

int findLastActiveLed(const int ledGroup[]) {
  for (int i = 0; i < numLeds; i++) {
    if (digitalRead(ledGroup[i]) == HIGH) {
      return i;
    }
  }
  return -1;
}

bool isCorrespondingLedOn(const int otherGroupPins[], int currentLedIndex) {
  int correspondingLedIndex = (currentLedIndex + numLeds / 2) % numLeds;
  return digitalRead(otherGroupPins[correspondingLedIndex]) == HIGH;
}

void turnOffCorrespondingLed(int otherGroupPins[], int currentLedIndex) {
  int correspondingLedIndex = (currentLedIndex + numLeds / 2) % numLeds;
  digitalWrite(otherGroupPins[correspondingLedIndex], LOW);


for (int i = 0; i < numGroups; i++) {
    if (checkWinningGroup(winningGroups[i])) {
      flashLeds(5000);
      break;
    }
  }
}

bool checkWinningGroup(int* group) {
  for (int i = 0; i < 4; i++) {
    if (digitalRead(group[i]) != HIGH) {
      return false;
    }
  }
  return true;
}

void flashLeds(int duration) {
  unsigned long startTime = millis();

  while (millis() - startTime < duration) {
    for (int i = 0; i < numLeds; i++) {
      digitalWrite(i + 22, HIGH);
      digitalWrite(i + 38, HIGH);
    }
    delay(250);  // Flash on for 250ms
    for (int i = 0; i < numLeds; i++) {
      digitalWrite(i + 22, LOW);
      digitalWrite(i + 38, LOW);
    }
    delay(250);  // Off for 250ms
  }


}

Are these on/off LEDs? PWM LEDs (Dim/Bright)? RGBLEDs? WS2812? How do you distinguish one player from the other?

The grid for connect4 is 7 wide by 6 tall. Maybe you can use a pre-made grid of Neopixels and cut it to size?

yes on/off leds and i have 5 push buttons (left, right, up, down, toggle) to move the position of the lit led and switch players.

How do you tell who has each LED?

I would like to be able to help, but I have some questions about your project:

  1. Because you used pinMode(x, INPUT); not pinMode(x, INPUT_PULLUP); ?
    Did you use external PULL UP or PULL DOWN resistors?

Using only INPUT, you need to use external resistors and using PULL_UP, you use the Mega's internal resistors.

If you used PULL DOWN resistors, when using PULL_UP internals, you need to invert the logic of the switches from HIGH to LOW and vice versa.

2 You inform that you use 5 buttons:
" 5 push buttons (left, right, up, down, toggle) ", so I suggest that you give these names to reference them in your code, thus making it easier to understand their use.
Rather than :

const int buttonPin = 2;
const int subButtonPin = 3;
const int add4ButtonPin = 4;
const int sub4ButtonPin = 5;
const int groupTogglePin = 6;

I suggest:

const int left_bt = 2;
const int right_bt = 3;
const int up_bt = 4;
const int down_bt = 5;
const int toggle_bt= 6;
  1. What is the format of the display with the LEDs? There are 32 LEDs

Would it be 4 rows and 8 columns?

And finally, a brief description of how players should proceed to play the game?

Probably.

Connect4 is any size grid "tic-tac-toe" / "naughts-and-crosses" game with two players. Object is: 4 uninterrupted pieces connected vertically, horizontally or diagonally.


My question, with LEDs, who is "A" and who is "B" - maybe brightness level?

Its 4x4 but each place will have a lense that is two different colors so there can be two resistors in one spot. So if pin 22 is on then the left side of the two colored lense will be on and pin 38 should be turned off so a player couldn'tselect the same spot. They will be external resistors 220 ohms.

hi @cha111,
Welcome to the forum..
must apologize, started on this yesterday and got very busy..
just now came back to it..
fun stuff, took a stab at it..
used a grid of addressable leds..
should match original layout, added one row for player positioning..
flashes the win and resets game..
a bit tricky, probably could do it differently, but seems to work..
maybe it gives you some inspiration..

/*
Uno Link 4
created 10.19.2023 -q
*/


#include <Adafruit_NeoPixel.h>
#define NUMPIXELS 49
#define PIN 2
#define BTN_R 3
#define BTN_D 4
#define BTN_L 5
#define PLAYR_1 1
#define PLAYR_2 2

#define MAX_COL 6
#define MAX_ROW 5
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_RGB + NEO_KHZ800);

uint32_t empty = strip.Color(255, 255, 255);
uint32_t blu = strip.Color(0, 0, 255);
uint32_t red = strip.Color(0, 255, 0);
uint32_t off = strip.Color(0, 0, 0);
uint32_t currentPlayer = blu;

int16_t cur_bright = 255;

byte playerUp = PLAYR_1;
byte dropPosistion = 3;
byte gameMode = 0;

byte WinLeds[4];

byte GameGrid[7][6] = {
  {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}
};

byte LedGrid[7][6] = {
  {7, 14, 21, 28, 35, 42},
  {8, 15, 22, 29, 36, 43},
  {9, 16, 23, 30, 37, 44},
  {10, 17, 24, 31, 38, 45},
  {11, 18, 25, 32, 39, 46},
  {12, 19, 26, 33, 40, 47},
  {13, 20, 27, 34, 41, 48}
};

byte btnPins[3] = {5, 4, 3};
unsigned long debouncers[3];
byte lastButtons[3] = {1, 1, 1};
int  dropToo = 0;
byte dropStep = 0;
unsigned long lastStep;
int dropSpeed = 100;
int blinkSpeed = 250;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("ready..");
  pinMode(BTN_L, INPUT_PULLUP);
  pinMode(BTN_D, INPUT_PULLUP);
  pinMode(BTN_R, INPUT_PULLUP);
  strip.begin();
  for (int i = 0; i < NUMPIXELS; i++) {
    strip.setPixelColor(i, empty);
  }
  strip.setPixelColor(dropPosistion, blu);
  strip.show();

  for (int col = 0; col < 7; col++) {
    for (int row = 0; row < 6; row++) {
      GameGrid[col][row] = 0;
    }
  }
}

void loop() {

  unsigned long now = millis();

  if (gameMode == 0) {
    for (int i = 0; i < 3; i++) {
      if (now - debouncers[i] >= 50) {
        byte btn = digitalRead(btnPins[i]);
        if (btn != lastButtons[i]) {
          lastButtons[i] = btn;
          debouncers[i] = now;
          if (btn == LOW) {
            switch (i) {
              case 0: if (dropPosistion > 0) {
                  dropPosistion--;
                  strip.setPixelColor(dropPosistion, currentPlayer);
                  strip.setPixelColor(dropPosistion + 1, empty);
                  strip.show();
                }
                break;
              case 1: if (CanDrop(dropPosistion) > 0) {
                  dropToo = CanDrop(dropPosistion);
                  GameGrid[dropPosistion][dropToo - 2] = playerUp;
                  lastStep = now;
                  dropStep = 0;
                  gameMode = 1;
                } else {
                  dropToo = CanDrop(dropPosistion);
                } break;
              case 2: if (dropPosistion < 6) {
                  dropPosistion++;
                  strip.setPixelColor(dropPosistion, currentPlayer);
                  strip.setPixelColor(dropPosistion - 1, empty);
                  strip.show();
                }  break;
            }
          }
        }
      }
    }
  } else if (gameMode == 1) {
    //dropping..
    if (now - lastStep >= dropSpeed) {
      lastStep = now;
      strip.setPixelColor(dropPosistion + (dropStep * 7), currentPlayer);
      if (dropStep > 0)
        strip.setPixelColor(dropPosistion + ((dropStep - 1) * 7), empty);
      strip.show();
      dropStep++;
      if (dropStep == dropToo) {
        //check for a winning drop..
        if (DropWins(dropToo - 2)) {
          Serial.println("Winner");
          dropStep = 0;
          dropToo = 11;
          gameMode = 2;
          return;
        }

        gameMode = 0;
        if (currentPlayer == blu) currentPlayer = red; else currentPlayer = blu;
        if (playerUp == PLAYR_1) playerUp = PLAYR_2; else playerUp = PLAYR_1;
        strip.setPixelColor(dropPosistion, currentPlayer);
        strip.show();
      }
    }
  } else if (gameMode == 2) {
    if (now - lastStep >= blinkSpeed) {
      lastStep = now;
      for (int i = 0; i < 4; i++) {
        if (dropStep == 0) {
          strip.setPixelColor(WinLeds[i], currentPlayer);
        } else {
          strip.setPixelColor(WinLeds[i], empty);
        }
      }
      strip.show();
      dropStep++;
      if (dropStep > 1) dropStep = 0;
      dropToo--;
      if (dropToo == 0) {
        gameMode = 0;
        ResetGame();
      }
    }
  }
}

void ResetGame() {
  //clear leds..
  for (int i = 0; i < NUMPIXELS; i++) {
    strip.setPixelColor(i, empty);
  }
  strip.show();
  //clear gamegrid
  for (int col = 0; col < 7; col++) {
    for (int row = 0; row < 6; row++) {
      GameGrid[col][row] = 0;
    }
  }
  //set next player up..
  dropPosistion = 3;
  if (currentPlayer == blu) currentPlayer = red; else currentPlayer = blu;
  if (playerUp == PLAYR_1) playerUp = PLAYR_2; else playerUp = PLAYR_1;
  strip.setPixelColor(dropPosistion, currentPlayer);
  strip.show();
}

bool DropWins(int drop) {
  bool result = false;
  byte col = dropPosistion;
  byte row = drop;
  result = CheckCol(col);
  if (!result) result = CheckRow(row);
  if (!result) result = CheckDiag(col, row);
  return (result);
}

bool CheckCol(int col) {
  bool result = false;
  byte cnt = 0;
  for (int i = 0; i < 6; i++)
  {
    if (GameGrid[col][i] == playerUp) {
      if (cnt < 4) WinLeds[cnt] = LedGrid[col][i];
      cnt++;
    } else if (cnt < 4) cnt = 0;
  }
  if (cnt > 3) result = true;
  return (result);
}

bool CheckRow(int row) {
  bool result = false;
  byte cnt = 0;
  for (int i = 0; i < 7; i++)
  {
    if (GameGrid[i][row] == playerUp) {
      if (cnt < 4) WinLeds[cnt] = LedGrid[i][row];
      cnt++;
    } else if (cnt < 4) cnt = 0;
  }
  if (cnt > 3) result = true;
  return (result);
}


bool CheckDiag(int col, int row) {
  bool result = false;
  int startCol, startRow, count;
  //top left..
  if (col > row) {
    startCol = col - row;
    startRow = 0;
  } else {
    startCol = 0;
    startRow = row - col;
  }
  int rowStep = 0;
  for (int c = startCol; c < MAX_COL + 1; c++) {
    if (GameGrid[c][startRow + rowStep] == playerUp) {
      if (count < 4) WinLeds[count] = LedGrid[c][startRow + rowStep];
      count++;
    } else if (count < 4) count = 0;
    rowStep++;
  }
  //top right
  if (count < 4) {
    count = 0;
    startCol = row + col;
    if (startCol > MAX_COL) {
      startCol = MAX_COL;
      startRow = row - ((col + row) - startCol);
    }
    else
      startRow = 0;
    int rowStep = 0;
    for (int c = startCol; c > -1; c--) {
      if (GameGrid[c][startRow + rowStep] == playerUp) {
        if (count < 4) WinLeds[count] = LedGrid[c][startRow + rowStep];
        count++;
      } else if (count < 4) count = 0;
      rowStep++;
    }
  }
  if (count > 3) result = true;
  return (result);
}


int CanDrop(byte col) {
  int result = -1;
  for (int i = 0; i < 6; i++) {
    if (GameGrid[col][i] != 0) {
      byte val = GameGrid[col][i];
      break;
    } else result = i;
  }
  if (result > -1) result += 2;
  return (result);
}

Play it here..

have fun.. ~q

I've optimized your code and hopefully fixed it to your satisfaction. I've also included details on every fix and optimization. I hope this helps out.

const int buttonPin = 2;
const int subButtonPin = 3;
const int add4ButtonPin = 4;
const int sub4ButtonPin = 5;
const int groupTogglePin = 6;

const int group1LedPins[] = {22, 23, 24, 25, 26, 27, 28, 29};
const int group2LedPins[] = {38, 39, 40, 41, 42, 43, 44, 45};

const int numLeds = sizeof(group1LedPins) / sizeof(group1LedPins[0]);

int currentLedGroup = 1;
int lastActiveLedGroup1 = 0;
int lastActiveLedGroup2 = 0;

bool group1Initialized = false;
bool group2Initialized = false;

int group1win[] = {22, 23, 24, 25};
int group2win[] = {26, 27, 28, 29};
int group3win[] = {30, 31, 32, 33};
int group4win[] = {34, 35, 36, 37};

// Define winning groups...

const int numGroups = 20;
int* winningGroups[numGroups] = {
  group1win, group2win, group3win, group4win,
  // Add the rest of the winning groups...
};

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(subButtonPin, INPUT);
  pinMode(add4ButtonPin, INPUT);
  pinMode(sub4ButtonPin, INPUT);
  pinMode(groupTogglePin, INPUT);

  for (int i = 0; i < numLeds; i++) {
    pinMode(group1LedPins[i], OUTPUT);
    pinMode(group2LedPins[i], OUTPUT);
    digitalWrite(group1LedPins[i], LOW);
    digitalWrite(group2LedPins[i], LOW);
  }

  // Set the first LED in the first group (pin 22) to HIGH at the start
  digitalWrite(group1LedPins[lastActiveLedGroup1], HIGH);
}

void loop() {
  if (digitalRead(groupTogglePin) == HIGH) {
    toggleLedGroup();
    delay(200);
  }

  if (currentLedGroup == 1) {
    handleButtonPress(group1LedPins, lastActiveLedGroup1, group2LedPins);
  } else if (currentLedGroup == 2) {
    handleButtonPress(group2LedPins, lastActiveLedGroup2, group1LedPins);
  }
}

void handleButtonPress(int ledGroup[], int &lastActiveLed, const int otherGroupPins[]) {
  if (digitalRead(buttonPin) == HIGH) {
    if (digitalRead(ledGroup[lastActiveLed]) == LOW) {
      digitalWrite(ledGroup[lastActiveLed], HIGH);
    }
    delay(200);
  }

  if (digitalRead(subButtonPin) == HIGH) {
    subtractLed(ledGroup, lastActiveLed);
    delay(200);
  }

  if (digitalRead(add4ButtonPin) == HIGH) {
    advanceLedBy(ledGroup, lastActiveLed, 4);
    delay(200);
  }

  if (digitalRead(sub4ButtonPin) == HIGH) {
    subtractLedBy(ledGroup, lastActiveLed, 4);
    delay(200);
  }
}

void toggleLedGroup() {
  if (currentLedGroup == 1) {
    lastActiveLedGroup1 = findLastActiveLed(group1LedPins);
    currentLedGroup = 2;
  } else {
    lastActiveLedGroup2 = findLastActiveLed(group2LedPins);
    currentLedGroup = 1;
  }
}

void advanceLedBy(int ledGroup[], int &lastActiveLed, int steps) {
  for (int i = 0; i < steps; i++) {
    advanceLed(ledGroup, lastActiveLed);
    delay(50);
  }
}

void advanceLed(int ledGroup[], int &lastActiveLed) {
  digitalWrite(ledGroup[lastActiveLed], LOW);
  lastActiveLed = (lastActiveLed + 1) % numLeds;
  digitalWrite(ledGroup[lastActiveLed], HIGH);
}

void subtractLedBy(int ledGroup[], int &lastActiveLed, int steps) {
  for (int i = 0; i < steps; i++) {
    subtractLed(ledGroup, lastActiveLed);
    delay(50);
  }
}

void subtractLed(int ledGroup[], int &lastActiveLed) {
  digitalWrite(ledGroup[lastActiveLed], LOW);
  lastActiveLed = (lastActiveLed - 1 + numLeds) % numLeds;
  digitalWrite(ledGroup[lastActiveLed], HIGH);
}

int findLastActiveLed(const int ledGroup[]) {
  for (int i = 0; i < numLeds; i++) {
    if (digitalRead(ledGroup[i]) == HIGH) {
      return i;
    }
  }
  return -1;
}

void flashLeds(int duration) {
  unsigned long startTime = millis();

  while (millis() - startTime < duration) {
    for (int i = 0; i < numLeds; i++) {
      digitalWrite(group1LedPins[i], HIGH);
      digitalWrite(group2LedPins[i], HIGH);
    }
    delay(250);  // Flash on for 250ms
    for (int i = 0; i < numLeds; i++) {
      digitalWrite(group1LedPins[i], LOW);
      digitalWrite(group2LedPins[i], LOW);
    }
    delay(250);  // Off for 250ms
  }
}

bool checkWinningGroup(int* group) {
  for (int i = 0; i < 4; i++) {
    if (digitalRead(group[i]) != HIGH) {
      return false;
    }
  }
  return true;
}

Explanation of the fixes and optimizations:

  1. Fixed LED Button Handling:
    In the handleButtonPress function, I removed the unnecessary condition that toggled the LED state. Now, the LED stays on when the button is pressed.

  2. Simplified Toggle Function:
    The toggleLedGroup function was simplified to switch between LED groups without turning off LEDs of the other group.

  3. Reorganized Winning Group Check:
    The code for checking winning groups was left unchanged, but it was included as part of the optimized code.

These changes should help keep the LEDs on when a button is pressed and improve the overall organization of the code.

hey thank you for helping. I still hand some problems with your code and some i was able to fix. First i had to make the add button work which i was able to figure out but the toggle button between both groups isnt working because its not saving the led in the last group on.

const int buttonPin = 2;
const int subButtonPin = 3;
const int add4ButtonPin = 4;
const int sub4ButtonPin = 5;
const int groupTogglePin = 6;

const int group1LedPins[] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31,32,33,34,35,36,37};
const int group2LedPins[] = {38, 39, 40, 41, 42, 43, 44, 45, 46,47,48,49,50,51, 52,53};

const int numLeds = sizeof(group1LedPins) / sizeof(group1LedPins[0]);

int currentLedGroup = 1;
int lastActiveLedGroup1 = 0;
int lastActiveLedGroup2 = 0;

bool group1Initialized = false;
bool group2Initialized = false;

int group1win[] = {22, 23, 24, 25};
int group2win[] = {26, 27, 28, 29};
int group3win[] = {30, 31, 32, 33};
int group4win[] = {34, 35, 36, 37};

// Define winning groups...

const int numGroups = 20;
int* winningGroups[numGroups] = {
  group1win, group2win, group3win, group4win,
  // Add the rest of the winning groups...
};
 int lastActiveLed1 = lastActiveLedGroup1;
  int lastActiveLed2 = lastActiveLedGroup2;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(subButtonPin, INPUT);
  pinMode(add4ButtonPin, INPUT);
  pinMode(sub4ButtonPin, INPUT);
  pinMode(groupTogglePin, INPUT);

  for (int i = 0; i < numLeds; i++) {
    pinMode(group1LedPins[i], OUTPUT);
    pinMode(group2LedPins[i], OUTPUT);
    digitalWrite(group1LedPins[i], LOW);
    digitalWrite(group2LedPins[i], LOW);
  }

  // Set the first LED in the first group (pin 22) to HIGH at the start
  digitalWrite(group1LedPins[lastActiveLedGroup1], HIGH);
}

void loop() {
  if (digitalRead(groupTogglePin) == HIGH) {
    toggleLedGroup();
    delay(200);
  }

  if (currentLedGroup == 1) {
    handleButtonPress(group1LedPins, lastActiveLedGroup1, group2LedPins);
  } else if (currentLedGroup == 2) {
    handleButtonPress(group2LedPins, lastActiveLedGroup2, group1LedPins);
  }
}

void handleButtonPress(int ledGroup[], int &lastActiveLed, const int otherGroupPins[]) {
  
  if (digitalRead(buttonPin) == HIGH) {
    advanceLed(ledGroup, lastActiveLed);
    delay(200);
  }

  if (digitalRead(subButtonPin) == HIGH) {
    subtractLed(ledGroup, lastActiveLed);
    delay(200);
  }

  if (digitalRead(add4ButtonPin) == HIGH) {
    advanceLedBy(ledGroup, lastActiveLed, 4);
    delay(200);
  }

  if (digitalRead(sub4ButtonPin) == HIGH) {
    subtractLedBy(ledGroup, lastActiveLed, 4);
    delay(200);
  }
}

void toggleLedGroup() {
  digitalWrite(group1LedPins[lastActiveLedGroup1], LOW);  // Turn off last active LED in group 1
  digitalWrite(group2LedPins[lastActiveLedGroup2], LOW);  // Turn off last active LED in group 2

  if (currentLedGroup == 1) {
    currentLedGroup = 2;
    lastActiveLedGroup2 = findLastActiveLed(group2LedPins);  // Find the least active LED in group 2
    digitalWrite(group2LedPins[lastActiveLedGroup2], HIGH);  // Turn on the least active LED in group 2
  } else {
    currentLedGroup = 1;
    lastActiveLedGroup1 = findLastActiveLed(group1LedPins);  // Find the least active LED in group 1
    digitalWrite(group1LedPins[lastActiveLedGroup1], HIGH);  // Turn on the least active LED in group 1
  }
}


void advanceLedBy(int ledGroup[], int &lastActiveLed, int steps) {
  for (int i = 0; i < steps; i++) {
    advanceLed(ledGroup, lastActiveLed);
    delay(50);
  }
}

void advanceLed(int ledGroup[], int &lastActiveLed) {
  digitalWrite(ledGroup[lastActiveLed], LOW);
  lastActiveLed = (lastActiveLed + 1) % numLeds;
  digitalWrite(ledGroup[lastActiveLed], HIGH);
}

void subtractLedBy(int ledGroup[], int &lastActiveLed, int steps) {
  for (int i = 0; i < steps; i++) {
    subtractLed(ledGroup, lastActiveLed);
    delay(50);
  }
}

void subtractLed(int ledGroup[], int &lastActiveLed) {
  digitalWrite(ledGroup[lastActiveLed], LOW);
  lastActiveLed = (lastActiveLed - 1 + numLeds) % numLeds;
  digitalWrite(ledGroup[lastActiveLed], HIGH);
}

int findLastActiveLed(const int ledGroup[]) {
  for (int i = 0; i < numLeds; i++) {
    if (digitalRead(ledGroup[i]) == HIGH) {
      return i;
    }
  }
  return -1;
}

void flashLeds(int duration) {
  unsigned long startTime = millis();

  while (millis() - startTime < duration) {
    for (int i = 0; i < numLeds; i++) {
      digitalWrite(group1LedPins[i], HIGH);
      digitalWrite(group2LedPins[i], HIGH);
    }
    delay(250);  // Flash on for 250ms
    for (int i = 0; i < numLeds; i++) {
      digitalWrite(group1LedPins[i], LOW);
      digitalWrite(group2LedPins[i], LOW);
    }
    delay(250);  // Off for 250ms
  }
}

bool checkWinningGroup(int* group) {
  for (int i = 0; i < 4; i++) {
    if (digitalRead(group[i]) != HIGH) {
      return false;
    }
  }
  return true;
}

int findLeastActiveLed(const int ledGroup[]) {
  int leastActiveLedIndex = 0;
  int leastActiveLedCount = numLeds;  // Set it to a high value initially

  for (int i = 0; i < numLeds; i++) {
    int activeLedCount = 0;
    for (int j = 0; j < numLeds; j++) {
      if (digitalRead(ledGroup[j]) == HIGH) {
        activeLedCount++;
      }
    }

    if (activeLedCount < leastActiveLedCount) {
      leastActiveLedCount = activeLedCount;
      leastActiveLedIndex = i;
    }
  }

  return leastActiveLedIndex;
}


Here's what i was able to do on my end. if you are able to help "Thank you". if not thank you for what you have already done.

I'm not using a led screen like this but it was really fun to play thank you.

1 Like

I've made some further fixes and optimizations to your code hopefully fixing your issue.

const int buttonPin = 2;
const int subButtonPin = 3;
const int add4ButtonPin = 4;
const int sub4ButtonPin = 5;
const int groupTogglePin = 6;

const int group1LedPins[] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37};
const int group2LedPins[] = {38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53};

const int numLeds = sizeof(group1LedPins) / sizeof(group1LedPins[0]);

int currentLedGroup = 1;
int lastActiveLedGroup1 = 0;
int lastActiveLedGroup2 = 0;

int group1win[] = {22, 23, 24, 25};
int group2win[] = {26, 27, 28, 29};
int group3win[] = {30, 31, 32, 33};
int group4win[] = {34, 35, 36, 37};

const int numGroups = 20;
int* winningGroups[numGroups] = {
  group1win, group2win, group3win, group4win,
  // Add the rest of the winning groups...
};

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(subButtonPin, INPUT);
  pinMode(add4ButtonPin, INPUT);
  pinMode(sub4ButtonPin, INPUT);
  pinMode(groupTogglePin, INPUT);

  for (int i = 0; i < numLeds; i++) {
    pinMode(group1LedPins[i], OUTPUT);
    pinMode(group2LedPins[i], OUTPUT);
    digitalWrite(group1LedPins[i], LOW);
    digitalWrite(group2LedPins[i], LOW);
  }

  // Set the first LED in the first group (pin 22) to HIGH at the start
  digitalWrite(group1LedPins[lastActiveLedGroup1], HIGH);
}

void loop() {
  if (digitalRead(groupTogglePin) == HIGH) {
    toggleLedGroup();
    delay(200);
  }

  if (currentLedGroup == 1) {
    handleButtonPress(group1LedPins, lastActiveLedGroup1, group2LedPins);
  } else if (currentLedGroup == 2) {
    handleButtonPress(group2LedPins, lastActiveLedGroup2, group1LedPins);
  }
}

void handleButtonPress(int ledGroup[], int &lastActiveLed, const int otherGroupPins[]) {
  if (digitalRead(buttonPin) == HIGH) {
    advanceLed(ledGroup, lastActiveLed);
    delay(200);
  }

  if (digitalRead(subButtonPin) == HIGH) {
    subtractLed(ledGroup, lastActiveLed);
    delay(200);
  }

  if (digitalRead(add4ButtonPin) == HIGH) {
    advanceLedBy(ledGroup, lastActiveLed, 4);
    delay(200);
  }

  if (digitalRead(sub4ButtonPin) == HIGH) {
    subtractLedBy(ledGroup, lastActiveLed, 4);
    delay(200);
  }
}

void toggleLedGroup() {
  digitalWrite(group1LedPins[lastActiveLedGroup1], LOW);
  digitalWrite(group2LedPins[lastActiveLedGroup2], LOW);

  if (currentLedGroup == 1) {
    currentLedGroup = 2;
    lastActiveLedGroup2 = findLastActiveLed(group2LedPins);
    digitalWrite(group2LedPins[lastActiveLedGroup2], HIGH);
  } else {
    currentLedGroup = 1;
    lastActiveLedGroup1 = findLastActiveLed(group1LedPins);
    digitalWrite(group1LedPins[lastActiveLedGroup1], HIGH);
  }
}

void advanceLedBy(int ledGroup[], int &lastActiveLed, int steps) {
  for (int i = 0; i < steps; i++) {
    advanceLed(ledGroup, lastActiveLed);
    delay(50);
  }
}

void advanceLed(int ledGroup[], int &lastActiveLed) {
  digitalWrite(ledGroup[lastActiveLed], LOW);
  lastActiveLed = (lastActiveLed + 1) % numLeds;
  digitalWrite(ledGroup[lastActiveLed], HIGH);
}

void subtractLedBy(int ledGroup[], int &lastActiveLed, int steps) {
  for (int i = 0; i < steps; i++) {
    subtractLed(ledGroup, lastActiveLed);
    delay(50);
  }
}

void subtractLed(int ledGroup[], int &lastActiveLed) {
  digitalWrite(ledGroup[lastActiveLed], LOW);
  lastActiveLed = (lastActiveLed - 1 + numLeds) % numLeds;
  digitalWrite(ledGroup[lastActiveLed], HIGH);
}

int findLastActiveLed(const int ledGroup[]) {
  for (int i = 0; i < numLeds; i++) {
    if (digitalRead(ledGroup[i]) == HIGH) {
      return i;
    }
  }
  return -1;
}

I've made the following fixes and optimizations:

  1. Added missing winningGroups definitions, which are arrays of integers representing the winning LED groups.

  2. Updated the toggleLedGroup function to correctly update the lastActiveLedGroup1 and lastActiveLedGroup2 variables when switching between LED groups.

These changes should help improve the functionality and maintain the last active LED when toggling between groups.

Hey there!

I read about the challenge you're facing with your LED-based Connect 4 game using an Arduino Mega. It sounds like the issue is with how your program handles the LED states when moving around the grid. This might be happening because the code is not correctly maintaining the state of each LED when you change the focus from one to another.

Without seeing your code, my best guess would be to check how you're updating the LEDs' states in your loop. Ensure that each LED's state is stored in an array and only change the state of the specific LED you're interacting with. When moving around, you should only update the LED that corresponds to the current position, rather than rewriting the states of all LEDs each loop iteration.

Also, a quick suggestion unrelated to your problem but might interest you. If you're into gaming and use Twitch, check out twitchclipdownloader.xyz. It's a handy tool for downloading Twitch clips, which can be a great way to capture and share moments from your gaming sessions or even use them for inspiration in your projects.

Hope this helps with your Connect 4 game, and good luck with your project!

Best,
[thomes jack]

This was very helpful thank you for sharing this!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.