Nested Case Switches Giving duplicate case value error ?

I am building a project / sketch where there are four steps to completing a final solution.

The original Sketch needed only one attempt (gameState) and worked fine, which is when I tried to implement a more complex sketch, which required four correct attempts (numAttempts) and this is where I have hit problems with my Nested Case Switches.

I have poured over the sketch for Hours and just cant see, why I am getting a “duplicate case value” error, at the “case GameState::SUCCESS:” point ??

I am now at a point where I am starting to think that what I am trying to achieve is not possible and I might have to resort to “if” statements instead which might get very messy.

I would welcome any suggestions on where I might be going wrong or if indeed what I am trying to do is achievable.

Thanks in advance.

Fimez.

// Used to control a panel of MAX7219 LED displays showing the input sequence - https://github.com/wayoda/LedControl
#include "src/LedControl.h"
// Header file contains definition of the values appearing on the display
#include "short_detective.h"

// CONSTANTS
// Starting Point used to start the Attempt each time
int startPin = 6;
// Attempt Failed
const byte failPin = 2;
// End Point used to complete each Attempt.
int endPin = 8;
// A piezo buzzer chirps to signify success/failure
const byte buzzerPin = 4;
// The total number of sucsessful attempts to complete the puzzle
const byte totalAttempts = 4;


// GLOBALS
// Initialise a LedControl object
// Parameters are DataIn (Din), Clock (Clk), ChipSelect (CS), Number of MAX72XX modules
LedControl lc = LedControl(11, 13, 10, 4);
// Keep track of the current states of the game
enum GameState {FAILED, IN_PROGRESS, SUCCESS};
// Keep track of the number of attempts
GameState gameState = GameState::FAILED;
enum NumAttempts {FIRST, SECOND, THIRD, FOURTH};
NumAttempts numAttempts = NumAttempts::FIRST;


void setup() {
  // Set the pins to the correct mode
  pinMode(startPin, INPUT_PULLUP);
  pinMode(failPin, INPUT_PULLUP);
  pinMode(endPin, INPUT_PULLUP);
  pinMode(buzzerPin, OUTPUT);

  // Initialise LED Matrix
  lc.shutdown(0, false);
  lc.setIntensity(0, 1);
  lc.shutdown(1, false);
  lc.setIntensity(1, 1);
  lc.shutdown(2, false);
  lc.setIntensity(2, 1);
  lc.shutdown(3, false);
  lc.setIntensity(3, 1);



  // Begin a serial connection for debugging
  Serial.begin(9600);
}

void loop() {

  switch (numAttempts) {
      char buf[25];
      sprintf(buf, "Game State %d", gameState);
      Serial.println(buf);

      char buf2[25];
      sprintf(buf2, "Number Of Attempts %d", numAttempts);
      Serial.println(buf2);

      switch (gameState) {

        case GameState::IN_PROGRESS:
          delay(100);
          if (!digitalRead(endPin)) {
            gameState = GameState::SUCCESS;
            Serial.println("Attempt Completed Successfully");
            tone(buzzerPin, 370, 200);
            delay(200);
            tone(buzzerPin, 392, 200);
            delay(200);
            tone(buzzerPin, 415, 200);
            delay(200);
            tone(buzzerPin, 440, 200);

            char buf[25];
            sprintf(buf, "Number Of Attempts %d", numAttempts);
            Serial.println(buf);
            delay(500);

          // Display the Hidden Code on the LED matrix dependant on the # of attempts.
          case NumAttempts::FIRST:
            for (int row = 0; row < 8; row++) {
              lc.setRow(3, row, digits[4][row]);// 4
              lc.setRow(2, row, digits[38][row]);// <
              lc.setRow(1, row, digits[38][row]);// <
              lc.setRow(0, row, digits[38][row]);// <
              // Swap Start and End Points For Next Attempt
              startPin = 8;
              endPin = 6;
            }
            break;

          case NumAttempts::SECOND:
            for (int row = 0; row < 8; row++) {
              lc.setRow(3, row, digits[32][row]);// 4
              lc.setRow(2, row, digits[30][row]);// 2
              lc.setRow(1, row, digits[39][row]);// >
              lc.setRow(0, row, digits[39][row]);// >
              // Swap Start and End Points For Next Attempt
              startPin = 6;
              endPin = 8;
            }
            break;

          case NumAttempts::THIRD:
            for (int row = 0; row < 8; row++) {
              lc.setRow(3, row, digits[32][row]);// 4
              lc.setRow(2, row, digits[30][row]);// 2
              lc.setRow(1, row, digits[34][row]);// 6
              lc.setRow(0, row, digits[38][row]);// <
              // Swap Start and End Points For Next Attempt
              startPin = 8;
              endPin = 6;
            }
            break;

          case NumAttempts::FOURTH:
            for (int row = 0; row < 8; row++) {
              lc.setRow(3, row, digits[32][row]);// 4
              lc.setRow(2, row, digits[30][row]);// 2
              lc.setRow(1, row, digits[34][row]);// 6
              lc.setRow(0, row, digits[37][row]);// 9
            }

          }
          else if (!digitalRead(failPin)) {
            delay(100);
            gameState = GameState::FAILED;
            Serial.println("Failed----Try Again");
            tone(buzzerPin, 440, 200);
            delay(200);
            tone(buzzerPin, 415, 200);
            delay(200);
            tone(buzzerPin, 392, 200);
            delay(200);
            tone(buzzerPin, 370, 400);

            // Set !!!! on the LED matrix
            for (int row = 0; row < 8; row++) {
              lc.setRow(3, row, digits[27][row]); // !
              lc.setRow(2, row, digits[27][row]); // !
              lc.setRow(1, row, digits[27][row]); // !
              lc.setRow(0, row, digits[27][row]); // !
            }
          }
          break;

        case GameState::FAILED:
          delay(100);

        case GameState::SUCCESS:
          if (!digitalRead(startPin)) {
            delay(100);
            gameState = GameState::IN_PROGRESS;
            Serial.println("New Attempt Started");
            tone(buzzerPin, 440, 100);
            delay(120);
            tone(buzzerPin, 554, 100);
            delay(120);
            tone(buzzerPin, 659, 200);

            // Set "????" on the LED matrix
            for (int row = 0; row < 8; row++) {
              lc.setRow(3, row, digits[40][row]); // ?
              lc.setRow(2, row, digits[40][row]); // ?
              lc.setRow(1, row, digits[40][row]); // ?
              lc.setRow(0, row, digits[40][row]); // ?
            }
          }
          break;

      }
  }

}

You need to read up on switch statements. Do not put code within the switch block that is outside of a case. Your switch (numAttempts) block does not have any case statements but it looks like you tried to put case statements for the switch (numAttempts) block within a conditional which is within a switch (gameState) case block.

I cannot even begin to tell what you want to do.

I see what you are trying to say, but I imagined that was how "Nested" Switches would work, but obviously I was wrong.

I have searched for examples of Nested Switch statements but haven't come across any which suit my particular needs, or which I can get my head around.

If I can't do what I need to using nested switches, then I might look at using "if statements instead"

Regards,

Fimez.

Would this be close to what you want?

// Used to control a panel of MAX7219 LED displays showing the input sequence - https://github.com/wayoda/LedControl
#include "src/LedControl.h"
// Header file contains definition of the values appearing on the display
#include "short_detective.h"

// CONSTANTS
// Starting Point used to start the Attempt each time
int startPin = 6;
// Attempt Failed
const byte failPin = 2;
// End Point used to complete each Attempt.
int endPin = 8;
// A piezo buzzer chirps to signify success/failure
const byte buzzerPin = 4;
// The total number of sucsessful attempts to complete the puzzle
const byte totalAttempts = 4;


// GLOBALS
// Initialise a LedControl object
// Parameters are DataIn (Din), Clock (Clk), ChipSelect (CS), Number of MAX72XX modules
LedControl lc = LedControl(11, 13, 10, 4);
// Keep track of the current states of the game
enum GameState {FAILED, IN_PROGRESS, SUCCESS};
// Keep track of the number of attempts
GameState gameState = GameState::FAILED;
enum NumAttempts {FIRST, SECOND, THIRD, FOURTH};
NumAttempts numAttempts = NumAttempts::FIRST;


void setup() {
  // Set the pins to the correct mode
  pinMode(startPin, INPUT_PULLUP);
  pinMode(failPin, INPUT_PULLUP);
  pinMode(endPin, INPUT_PULLUP);
  pinMode(buzzerPin, OUTPUT);

  // Initialise LED Matrix
  lc.shutdown(0, false);
  lc.setIntensity(0, 1);
  lc.shutdown(1, false);
  lc.setIntensity(1, 1);
  lc.shutdown(2, false);
  lc.setIntensity(2, 1);
  lc.shutdown(3, false);
  lc.setIntensity(3, 1);



  // Begin a serial connection for debugging
  Serial.begin(9600);
}

void loop() {

  char buf[25];
  sprintf(buf, "Game State %d", gameState);
  Serial.println(buf);

  char buf2[25];
  sprintf(buf2, "Number Of Attempts %d", numAttempts);
  Serial.println(buf2);

  switch (gameState) {

    case GameState::IN_PROGRESS:
      delay(100);
      if (!digitalRead(endPin)) {
        gameState = GameState::SUCCESS;
        Serial.println("Attempt Completed Successfully");
        tone(buzzerPin, 370, 200);
        delay(200);
        tone(buzzerPin, 392, 200);
        delay(200);
        tone(buzzerPin, 415, 200);
        delay(200);
        tone(buzzerPin, 440, 200);

        char buf[25];
        sprintf(buf, "Number Of Attempts %d", numAttempts);
        Serial.println(buf);
        delay(500);

        switch (numAttempts) {
          // Display the Hidden Code on the LED matrix dependant on the # of attempts.
          case NumAttempts::FIRST:
            for (int row = 0; row < 8; row++) {
              lc.setRow(3, row, digits[4][row]);// 4
              lc.setRow(2, row, digits[38][row]);// <
              lc.setRow(1, row, digits[38][row]);// <
              lc.setRow(0, row, digits[38][row]);// <
              // Swap Start and End Points For Next Attempt
              startPin = 8;
              endPin = 6;
            }
            break;

          case NumAttempts::SECOND:
            for (int row = 0; row < 8; row++) {
              lc.setRow(3, row, digits[32][row]);// 4
              lc.setRow(2, row, digits[30][row]);// 2
              lc.setRow(1, row, digits[39][row]);// >
              lc.setRow(0, row, digits[39][row]);// >
              // Swap Start and End Points For Next Attempt
              startPin = 6;
              endPin = 8;
            }
            break;

          case NumAttempts::THIRD:
            for (int row = 0; row < 8; row++) {
              lc.setRow(3, row, digits[32][row]);// 4
              lc.setRow(2, row, digits[30][row]);// 2
              lc.setRow(1, row, digits[34][row]);// 6
              lc.setRow(0, row, digits[38][row]);// <
              // Swap Start and End Points For Next Attempt
              startPin = 8;
              endPin = 6;
            }
            break;

          case NumAttempts::FOURTH:
            for (int row = 0; row < 8; row++) {
              lc.setRow(3, row, digits[32][row]);// 4
              lc.setRow(2, row, digits[30][row]);// 2
              lc.setRow(1, row, digits[34][row]);// 6
              lc.setRow(0, row, digits[37][row]);// 9
            }
            break;
        }
      }
      else if (!digitalRead(failPin)) {
        delay(100);
        gameState = GameState::FAILED;
        Serial.println("Failed----Try Again");
        tone(buzzerPin, 440, 200);
        delay(200);
        tone(buzzerPin, 415, 200);
        delay(200);
        tone(buzzerPin, 392, 200);
        delay(200);
        tone(buzzerPin, 370, 400);

        // Set !!!! on the LED matrix
        for (int row = 0; row < 8; row++) {
          lc.setRow(3, row, digits[27][row]); // !
          lc.setRow(2, row, digits[27][row]); // !
          lc.setRow(1, row, digits[27][row]); // !
          lc.setRow(0, row, digits[27][row]); // !
        }
      }
      break;

    case GameState::FAILED:
      delay(100);
      break;

    case GameState::SUCCESS:
      if (!digitalRead(startPin)) {
        delay(100);
        gameState = GameState::IN_PROGRESS;
        Serial.println("New Attempt Started");
        tone(buzzerPin, 440, 100);
        delay(120);
        tone(buzzerPin, 554, 100);
        delay(120);
        tone(buzzerPin, 659, 200);

        // Set "????" on the LED matrix
        for (int row = 0; row < 8; row++) {
          lc.setRow(3, row, digits[40][row]); // ?
          lc.setRow(2, row, digits[40][row]); // ?
          lc.setRow(1, row, digits[40][row]); // ?
          lc.setRow(0, row, digits[40][row]); // ?
        }
      }
      break;

  }
}

}

fimez:
I have searched for examples of Nested Switch statements but haven't come across any which suit my particular needs, or which I can get my head around.

What on earth did you search for? I Googled "c nested switch", and the very first hit gave a perfect example!

Regards,
Ray L.

ToddL1962

Great minds think alike :-), after your previous reply, I realised what I was attempting would not work and that the numAttempts cases had to be contained in the successful gameState.

So I re-organised the sketch with more or less the same code as I had previously and I came up with exactly the same solution, NO HONESTLY I DID :slight_smile:

I think I had been looking at the Sketch for far too long and was just not spotting the obvious, which your fresh pair of eyes obviously did, so thanks for that.

RayLivingston

I was searching for Nested Switches Arduino and got bogged down with lots of complicated examples which looked nothing like what I was trying to achieve, but just tried your search and it gives a much simpler example which is what I was looking for, so thanks also for your reply.

Regards,

Fimez.

The "Arduino language" is plain old c/c++, and switch statements are plain old c constructs, virtually unchanged since the 1970s. So if you want to learn the language, include "c" or "c++" in your search string, but NOT "Arduino". If you're looking for information on Arduino-specific topics, like how to use digitalRead, or Serial, or any other Arduino-specific topic, then you want your search string to include "Arduino".

Yet another reason I think it's stupid to propagate the myth that there even IS such a thing as an "Arduino language".

Regards,
Ray L.