Replace abusive use of Switch case:

Hi there!

Context: I'm making a homemade controler for n64 to do macros (Combos) on SuperSmash Bros. Each characters(12 of them) has 4 combos for every maps (9 of thems). Wich makes a possibility of 432 combos!

Basics of my code:

1-My loop function starts by stocking the infos above in three int variables, that way it know what characters is played on what map and which combo I want to do.

2-If a certain button is pressed, it goes through three stades of switch (Character -> map -> 1 out of 4 combo) that leads to the calling of the sub fonctions containing the wanted macro (combo).

Here's a fragment to give you the big idea (warning: french comments:

switch (Per) //Regarde quel personnage est joué
{
case 1: //Luigi

switch(Map) //Regarde sur quel Map le personnage est joué

case 1: //Peach Castle

switch(MacSel) //Regarde quel Macro (Combo) est activé et fait appel à la fonction Combo désiré

case 1: //Combo 1
//CALLING THE VOID FONCTION PERFORMING THE COMBO1//

break;

case 2: //Combo 2
//CALLING THE VOID FONCTION PERFORMING THE COMBO2//

break;

case 3: //Combo 3
//CALLING THE VOID FONCTION PERFORMING THE COMBO3//

break;

case 4: //Combo 4
//CALLING THE VOID FONCTION PERFORMING THE COMBO4//

break;

end it goes on for the 432 possibilities...

Problem: I want to know if there could be is a simpler or cleaner way to call my 'combos' subfunctions...

I'm trying to recall my C courses notion to find something that could help me but I thought that you guys might be interested in giving me a hint!

Thank you in advance and greetings from Quebec!

It sounds like an array of function pointers would help

A small example. Not using an array but you should get the idea

typedef void (* functionPtrs) (void);

functionPtrs funcs[3] = {&zero, &one, &two};

void setup()
{
  Serial.begin(115200);
  funcs[0]();
  funcs[1]();
  funcs[2]();
}

void loop()
{
}

void zero()
{
  Serial.println("zero");
}

void one()
{
  Serial.println("one");
}

void two()
{
  Serial.println("two");
}

However, memory may be a problem with so many functions.

//CALLING THE VOID FONCTION PERFORMING THE COMBO1//

First off it is called a function, NOT a void function. Void is simply the data type the function returns.

Second are all those functions very different? Most of the time you can simply pass the data you need in an array index to the function.

A bit of thought using arrays will go a long way.

Function pointers come to mind, possibly in combination with a structs or (multidimensional) arrays. That way you can use (nested) for-loop to call the specific function.

Below an example with an array of structs. A struct is like a record in a phone book combining e.g. name and phone number.

struct GAME
{
  byte per;
  byte map;
  byte macSel;
  void (*func)();
};

GAME game[] =
{
  {1, 1, 1, Luigi_Peach_Combo1},
  {1, 1, 2, Luigi_Peach_Combo2},
};

You can find a better name for the struct and the array name.

Next you can loop through the array, check if your variables match one of the entries in the array and execute the function

 // loop through array
  for (uint16_t cnt = 0; cnt < NUMELEMENTS(game); cnt++)
  {
    // check if there is a match
    if (game[cnt].per == Per && game[cnt].map == Map && game[cnt].macSel == MacSel)
    {
      // execute function
      game[cnt].func();

      // break once executed
      break;
    }
  }

NUMELEMENTS is a macro that calculates (at compile time) how many elements are in the array.

Full demo code

#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))

void Luigi_Peach_Combo1()
{
  Serial.println("Luigi, Peach, Combo 1");
}

void Luigi_Peach_Combo2()
{
  Serial.println("Luigi, Peach, Combo 2");
}

struct GAME
{
  byte per;
  byte map;
  byte macSel;
  void (*func)();
};

GAME game[] =
{
  {1, 1, 1, Luigi_Peach_Combo1},
  {1, 1, 2, Luigi_Peach_Combo2},
};


void setup()
{
  Serial.begin(57600);
  while (!Serial);
  Serial.println("Hello, I'm here");

  Serial.print("Number of entries in array = "); Serial.println(NUMELEMENTS(game));

  byte Per = 1;
  byte Map = 1;
  byte MacSel = 2;



  // loop through array
  for (uint16_t cnt = 0; cnt < NUMELEMENTS(game); cnt++)
  {
    // check if there is a match
    if (game[cnt].per == Per && game[cnt].map == Map && game[cnt].macSel == MacSel)
    {
      // execute function
      game[cnt].func();

      // break once executed
      break;
    }
  }
}

void loop()
{
}

More complete options are possible, e.g. an array of function pointers if you have standard functions that need to be called. Difficult to say without seeing your complete code.

Thank you guys!!

I've add a 3D-array with the functions pointers and it works perfectly fine!

Thanks again!