3 buttons, 6 possible combinations, randomize combination order

Hi, im making puzzlebox, imagine you have 3 buttons, thats make 6 possible combinations, i wanna make something that randomly makes combination of these 3 buttons, and you have to click them in order to pass the stage 1 of 6 , then it goes to stage 2 etc, like this

s1 231 s2 321 s3 123 s4 132 s5 312 s6 213

when it fails lets say at stage 4, it would go back to stage 1, generate new order of combination like this

s1 321 s2 123 s3 213 s4 312 s5 231 s6 132

how would i make this? in first stage i would need to generate order of 6 possible combinations of 6 numbers like "314265" or "461523" etc(number1 123, number2 231, number3 312, number4 321...) then i would name them number1, number2, number3...
making this check in stage 1 of combination for that first random number lets say number 4 making it for combination of buttons 321 and it would go to the next stage.

And my question is how would i generate these 6 numbers without duplicates and make check for that number?

I suspect it would be easiest to treat the numbers as groups of characters so you could have a 3 x 6 array

You could populate the first array (group of three chars) using random selections. Then create a random selection for the next group and compare it to all the existing groups and if it is different save it in the next group position.

...R

Its a little bit brute-force, but here's a snippet you could use for generating random sequences of the numbers 1-6:

#define nNumbers 6
int combination[nNumbers];

void setup() {
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  generateCombination();
  delay(50);
}

void generateCombination() {
  // set first digit
  combination[0] = random(nNumbers);
  Serial.print("Combination: ");
  Serial.print(combination[0]);

  // set next digits
  for (int i = 1; i < nNumbers; i++) {
    bool hasAlreadyBeenUsed;
    
    do {
      hasAlreadyBeenUsed = false;
      combination[i] = random(nNumbers); // pick a random number

      for (int j = 0; j < i; j++) { // loop over previous digits
        if (combination[i] == combination[j]) { // check if its been used already
          hasAlreadyBeenUsed = true; 
          break;
        }
      }
      
    } while (hasAlreadyBeenUsed); // if so, pick another one
    Serial.print('-');
    Serial.print(combination[i]); // if not, print it
  } // and continue with the next digit
  Serial.print('\n');

  return;
}

TimMJN:
Its a little bit brute-force, but here's a snippet you could use for generating random sequences of the numbers 1-6:

#define nNumbers 6

int combination[nNumbers];

void setup() {
 Serial.begin(9600);
}

void loop() {
 // put your main code here, to run repeatedly:
 generateCombination();
 delay(50);
}

void generateCombination() {
 // set first digit
 combination[0] = random(nNumbers);
 Serial.print("Combination: ");
 Serial.print(combination[0]);

// set next digits
 for (int i = 1; i < nNumbers; i++) {
   bool hasAlreadyBeenUsed;
   
   do {
     hasAlreadyBeenUsed = false;
     combination[i] = random(nNumbers); // pick a random number

for (int j = 0; j < i; j++) { // loop over previous digits
       if (combination[i] == combination[j]) { // check if its been used already
         hasAlreadyBeenUsed = true;
         break;
       }
     }
     
   } while (hasAlreadyBeenUsed); // if so, pick another one
   Serial.print('-');
   Serial.print(combination[i]); // if not, print it
 } // and continue with the next digit
 Serial.print('\n');

return;
}

how would i use it with states?
like "while (state = 1) generate combination, state = 2;
while (state= 2) if number1 pin high state = 3;"
etc i dont really understand how i can pick number of the combination attribute it to specific input pin and make it in that state to check which buttons(or "macro" of buttons is used) are pressed, anyway thank you so much for showing me how to make random combination of specific numbers :slight_smile:

#define nNumbers 6
int i = 0;
int state = 1;
int combination[nNumbers];

void setup() {
  Serial.begin(9600);
}

void loop()


{

while (state = 1) {
  Serial.println("state 1");
  
  // set first digit
  combination[0] = random(nNumbers);
  Serial.print("Combination: ");
  Serial.print(combination[0]);

  // set next digits
  for (int i = 1; i < nNumbers; i++) {
    bool hasAlreadyBeenUsed;
   
    do {
      hasAlreadyBeenUsed = false;
      combination[i] = random(nNumbers); // pick a random number

      for (int j = 0; j < i; j++) { // loop over previous digits
        if (combination[i] == combination[j]) { // check if its been used already
          hasAlreadyBeenUsed = true;
          break;
        }
      }
     
    } while (hasAlreadyBeenUsed); // if so, pick another one
    Serial.print('-');
    Serial.print(combination[i]); // if not, print it
  } // and continue with the next digit
  Serial.print('\n');

  state = 2;
  break;
};
while (state = 2) {
  Serial.println("state 2");
  
  
}
}

i've put it in states, how can i set specific number to react to pin? like set pin2 to number 1 etc, and how can i pick first number in array in state 2 to check if specified pin to that number is high?

I'm sorry, but I don't think I fully understand your question. The little snippet I gave you just generates a random permutation, and does so almost instantly. It doesn't require any 'state'.

I suggest you take a step back and first learn how to properly read and debounce a button. Then you can add reading the order of the presses and finally checking this against the correct combination.

baronjah:
you have 3 buttons, thats make 6 8 possible combinations

000 001 010 011 100 101 110 111
 0   1   2   3   4   5   6   7

Apart from that I don't understand the question.

With switches, yes,
but with three buttons I count 21 combinations (order of pushes).

111, 112, 113, 122, 123, 132, 133.
Same number if you start with button 2 or button 3.

2121212121*21 possible combinations would be a good safe, but a very annoying puzzle box.
Leo..

Wawa:
With switches, yes,
but with three buttons I count 21 combinations (order of pushes).

111, 112, 113, 122, 123, 132, 133.
Same number if you start with button 2 or button 3.

2121212121*21 possible combinations would be a good safe, but a very annoying puzzle box.
Leo..

If I understand correctly, OP wants every button just pressed once, which gives 6 combinations

123 132 and repeat with 2 and 3 as starting button

TimMJN:
If I understand correctly

You may well be right: I must say I didn't understand what he's on about :wink:

finola_marsaili:
You may well be right: I must say I didn't understand what he's on about :wink:

I still don't.

But I suspect he is interested in the individual digits of each "number" which I is why I made the suggestion in Reply #1

...R

Robin2:
I still don't.

But I suspect he is interested in the individual digits of each "number" which I is why I made the suggestion in Reply #1

...R

Rereading the OP, I think you might be right about that being part of the question. This post seems a bit of a puzzlebox itself.

Another way of going about it would be to record the button presses as integers 1 2 and 3. Then 100press1+10press2+press3 will give you the 'code' as an integer, which can be compared against pre-set values.

Now I'm thinking, will there be any hints to what is the right order? Cause if I'd had to guess six of these codes And they would rescramble at a fail... I think I'd find myself using more percussive methods to open de box quite soon..

TimMJN:
I think I'd find myself using more percussive methods to open de box quite soon..

LOL

...R

There is 6! = 6.5.4.3.2 = 720 possible sequences. If I had such homework I would somehow assign one sequence to each number from 0 to 719 and use function random to generate a number from this range.

EDIT: It looks like numbering permutations is not a trivial task and is not advantageous in this simple scenario. Possibly a "brute force" approach would be better: generate a random number between 1 and 6 until you generate one not used yet and repeat until you get the whole sequence.

Just out of curiousity, I wrote 3 different methods for generating random sequences:

method A: for each digit, generate random values until an unused one is found
method B: start with an ordered sequence and swap two random values N times
method C: for each digit, search for an unused value, starting from a random one

#define nNumbers 20

// globals for A
int combinationA[nNumbers];

// globals for B
int combinationB[nNumbers];

// globals for C
int combinationC[nNumbers];
bool hasBeenUsedC[nNumbers];


unsigned long tic;
unsigned long toc;

void setup() {
  Serial.begin(9600);
}

void loop() {

  tic = millis();
  generateCombinationA();
  toc = millis();
  Serial.print("Elapsed time A: ");
  Serial.print(toc - tic);
  Serial.println(" ms");

  tic = millis();
  generateCombinationB();
  toc = millis();
  Serial.print("Elapsed time B: ");
  Serial.print(toc - tic);
  Serial.println(" ms");

  tic = millis();
  generateCombinationC();
  toc = millis();
  Serial.print("Elapsed time C: ");
  Serial.print(toc - tic);
  Serial.println(" ms");

  delay(50);
}

// generate random sequence by generating number untill an unused digital is found
void generateCombinationA() {
  // set first digit
  combinationA[0] = random(nNumbers);
  //Serial.print("Combination A: ");
  //Serial.print(combinationA[0]);

  // set next digits
  for (int i = 1; i < nNumbers; i++) {
    bool hasAlreadyBeenUsed;

    do {
      hasAlreadyBeenUsed = false;
      combinationA[i] = random(nNumbers); // pick a random number

      for (int j = 0; j < i; j++) { // loop over previous digits
        if (combinationA[i] == combinationA[j]) { // check if its been used already
          hasAlreadyBeenUsed = true;
          break;
        }
      }

    } while (hasAlreadyBeenUsed); // if so, pick another one
    //Serial.print('-');
    //Serial.print(combinationA[i]); // if not, print it
  } // and continue with the next digit
  //Serial.print('\n');

  return;
}

// generate random sequence by swapping random pairs of values
void generateCombinationB() {
  // initialise as 0-(N-1)
  for (int i = 0; i < nNumbers; i++) {
    combinationB[i] = i;
  }

  // preform N swaps
  for (int i = 0; i < nNumbers; i++) {
    // random indeces
    int index1 = random(nNumbers);
    int index2 = random(nNumbers);

    // get values
    int value1 = combinationB[index1];
    int value2 = combinationB[index2];

    // swap them
    combinationB[index1] = value2;
    combinationB[index2] = value1;
  }

  // print
  /*
  Serial.print("Combination B: ");
  Serial.print(combinationB[0]);
  for (int i = 1; i < nNumbers; i++) {
    Serial.print('-');
    Serial.print(combinationB[i]);
  }
  Serial.print('\n');
  */
}

// generate random sequence by searching for an unused value, starting from a random one
void generateCombinationC() {

  // set hasBeenUsed to false
  for (int i = 0; i < nNumbers; i++) {
    hasBeenUsedC[i] = false;
  }

  for (int i = 0; i < nNumbers; i++) {
    int value  = random(nNumbers); // start at a random value

    // increment until an unused value is found
    while (hasBeenUsedC[value]) {
      value = (value + 1) % nNumbers;
    }

    combinationC[i] = value; //use it in the sequence
    hasBeenUsedC[value] = true; // mark the value as used
  }

  // print
  /*
  Serial.print("Combination C: ");
  Serial.print(combinationC[0]);
  for (int i = 1; i < nNumbers; i++) {
    Serial.print('-');
    Serial.print(combinationC[i]);
  }
  Serial.print('\n');
  */
}

(all print statements were turned off for fair comparison of the timings)

For short sequences (like the 6 value one here), all methods are basically instant. Interesting stuff happens when generating longer sequences.

Obviously, the brute-force method A gets outpreformed by the others big time. The difference is a factor 5 when generating 200 value sequences.

As it doesn't rely on finding unused values, method B provides a more constant timing. However, its randomness is debateable, as the user has to set the number of swaps. Here, I chose to swap N (N being the number of values in the sequence) times, so that each values gets swapped twice on average.

Method C is very close to B in timing, being up to 20% slower for 200-value sequences. As it relies on searching, it's timings vary much more than B. Also, C requires a second array (of bools) to mark which values have been used, so it is more memory-demanding.

Thank you for listening to my TED talk. <3

TimMJN:
Just out of curiousity, I wrote 3 different methods for generating random sequences:

method A: for each digit, generate random values until an unused one is found
method B: start with an ordered sequence and swap two random values N times
method C: for each digit, search for an unused value, starting from a random one

#define nNumbers 20

// globals for A
int combinationA[nNumbers];

// globals for B
int combinationB[nNumbers];

// globals for C
int combinationC[nNumbers];
bool hasBeenUsedC[nNumbers];

unsigned long tic;
unsigned long toc;

void setup() {
 Serial.begin(9600);
}

void loop() {

tic = millis();
 generateCombinationA();
 toc = millis();
 Serial.print("Elapsed time A: ");
 Serial.print(toc - tic);
 Serial.println(" ms");

tic = millis();
 generateCombinationB();
 toc = millis();
 Serial.print("Elapsed time B: ");
 Serial.print(toc - tic);
 Serial.println(" ms");

tic = millis();
 generateCombinationC();
 toc = millis();
 Serial.print("Elapsed time C: ");
 Serial.print(toc - tic);
 Serial.println(" ms");

delay(50);
}

// generate random sequence by generating number untill an unused digital is found
void generateCombinationA() {
 // set first digit
 combinationA[0] = random(nNumbers);
 //Serial.print("Combination A: ");
 //Serial.print(combinationA[0]);

// set next digits
 for (int i = 1; i < nNumbers; i++) {
   bool hasAlreadyBeenUsed;

do {
     hasAlreadyBeenUsed = false;
     combinationA[i] = random(nNumbers); // pick a random number

for (int j = 0; j < i; j++) { // loop over previous digits
       if (combinationA[i] == combinationA[j]) { // check if its been used already
         hasAlreadyBeenUsed = true;
         break;
       }
     }

} while (hasAlreadyBeenUsed); // if so, pick another one
   //Serial.print('-');
   //Serial.print(combinationA[i]); // if not, print it
 } // and continue with the next digit
 //Serial.print('\n');

return;
}

// generate random sequence by swapping random pairs of values
void generateCombinationB() {
 // initialise as 0-(N-1)
 for (int i = 0; i < nNumbers; i++) {
   combinationB[i] = i;
 }

// preform N swaps
 for (int i = 0; i < nNumbers; i++) {
   // random indeces
   int index1 = random(nNumbers);
   int index2 = random(nNumbers);

// get values
   int value1 = combinationB[index1];
   int value2 = combinationB[index2];

// swap them
   combinationB[index1] = value2;
   combinationB[index2] = value1;
 }

// print
 /*
 Serial.print("Combination B: ");
 Serial.print(combinationB[0]);
 for (int i = 1; i < nNumbers; i++) {
   Serial.print('-');
   Serial.print(combinationB[i]);
 }
 Serial.print('\n');
 */
}

// generate random sequence by searching for an unused value, starting from a random one
void generateCombinationC() {

// set hasBeenUsed to false
 for (int i = 0; i < nNumbers; i++) {
   hasBeenUsedC[i] = false;
 }

for (int i = 0; i < nNumbers; i++) {
   int value  = random(nNumbers); // start at a random value

// increment until an unused value is found
   while (hasBeenUsedC[value]) {
     value = (value + 1) % nNumbers;
   }

combinationC[i] = value; //use it in the sequence
   hasBeenUsedC[value] = true; // mark the value as used
 }

// print
 /*
 Serial.print("Combination C: ");
 Serial.print(combinationC[0]);
 for (int i = 1; i < nNumbers; i++) {
   Serial.print('-');
   Serial.print(combinationC[i]);
 }
 Serial.print('\n');
 */
}




(all print statements were turned off for fair comparison of the timings)

For short sequences (like the 6 value one here), all methods are basically instant. Interesting stuff happens when generating longer sequences. 

Obviously, the brute-force method A gets outpreformed by the others big time. The difference is a factor 5 when generating 200 value sequences.

As it doesn't rely on finding unused values, method B provides a more constant timing. However, its randomness is debateable, as the user has to set the number of swaps. Here, I chose to swap N (N being the number of values in the sequence) times, so that each values gets swapped twice on average.

Method C is very close to B in timing, being up to 20% slower for 200-value sequences. As it relies on searching, it's timings vary much more than B. Also, C requires a second array (of bools) to mark which values have been used, so it is more memory-demanding.

Thank you for listening to my TED talk. <3

that was interesting TED talk.

I guess i should explain my puzzle box in different way.

The idea is that you have 3 things that look the same, with help of other thing you know that one is 3, second is 5 and last one is 7.

Now you have 3 different places to put them into, there is lcd screen that shows number 735, now you have to put these pieces into their places, after doing so you will see number change to lets say 537 and have to change order of these pieces, and so on until you do all of the possible combination.

I wanted to do it in random so person doing it, cant remember the combination, but understad what he is doing.

Without randomness i would do it without problem but that randomness seems to me like more fun.

With that i was thinking how to do thing like this with "random" aspect, and the only think that came to my mind that it would need random combination of 1-6 numbers.

then i would need it to make that number 1 is 357, number 2 is 537, etc, and i have no idea how to use that code generator, how to make it to understand that number 1 is pin2(n2- pin3, n3- pin4, n4- pin5, n5- pin6, n6-pin7), how to make it so if combination is 3 5 2 4 1 6 then i would need to have pin4 high in state2, pin6 in state3, pin3 in state4, pin5 in state5, pin2 in state6 and pin7 in state7.

I hope that now people understand what i got on my mind because i feel like i cant explain what's in my mind and that worrisome

baronjah:
Now you have 3 different places to put them into, there is lcd screen that shows number 735, now you have to put these pieces into their places, after doing so you will see number change to lets say 537 and have to change order of these pieces, and so on until you do all of the possible combination.

I wanted to do it in random so person doing it, cant remember the combination, but understad what he is doing.

I'm still a bit confused.

Do you mean that when the person sees (for example) 735 on the screen he should type 7,3,5 in that order and when he does so the screen will then change to show 537 and the user must type 5,3,7 in that order. In other words there is no requirement for the user to guess the numbers or the order of the digits?

...R

Robin2:
I'm still a bit confused.

Do you mean that when the person sees (for example) 735 on the screen he should type 7,3,5 in that order and when he does so the screen will then change to show 537 and the user must type 5,3,7 in that order. In other words there is no requirement for the user to guess the numbers or the order of the digits?

...R

yea there is no need for user to guess the number, he need to know how to "input" these numbers, with 3 things that look the same(there will be place to put each thing inside and sound will play after x seconds(after 3, 5 and 7 seconds) with that he will know which is which and putting these things in another 3 places, he will input number 357 or 537 etc and then he will need to change places of these things to input another code) and i wanted to make order of these things random so he need to understand how to do it without guessing and remembering order of placing things in holes

baronjah:
that was interesting TED talk.

I guess i should explain my puzzle box in different way.

The idea is that you have 3 things that look the same, with help of other thing you know that one is 3, second is 5 and last one is 7.

Now you have 3 different places to put them into, there is lcd screen that shows number 735, now you have to put these pieces into their places, after doing so you will see number change to lets say 537 and have to change order of these pieces, and so on until you do all of the possible combination.

I wanted to do it in random so person doing it, cant remember the combination, but understad what he is doing.

Without randomness i would do it without problem but that randomness seems to me like more fun.

With that i was thinking how to do thing like this with "random" aspect, and the only think that came to my mind that it would need random combination of 1-6 numbers.

then i would need it to make that number 1 is 357, number 2 is 537, etc, and i have no idea how to use that code generator, how to make it to understand that number 1 is pin2(n2- pin3, n3- pin4, n4- pin5, n5- pin6, n6-pin7), how to make it so if combination is 3 5 2 4 1 6 then i would need to have pin4 high in state2, pin6 in state3, pin3 in state4, pin5 in state5, pin2 in state6 and pin7 in state7.

I hope that now people understand what i got on my mind because i feel like i cant explain what's in my mind and that worrisome

Thank you for that explanation, it's a bit clearer to me now!

Judging from this, I'd again say you have to take a step back. You're trying to make the whole picture work at once, but that will not fly unless you have the separate pieces clear.

So, forget about codes and combinations for now, we can come back to that later. Hook up your buttons and work on properly reading them. Then later you can focus on how to read the order in which they are pressed.

On a separate note, I think I understand the principle of the puzzle now, I think it's nice. One thought, is it really fun and necessary to do it 6 times?

baronjah:
with 3 things that look the same

I can't visualize that - either the concept of things that must be placed somewhere (where) or the idea that they look the same.

Can you post a picture or a diagram to illustrate what you have in mind.

...R
Simple Image Posting Guide