A random function that chooses every number from a "hat" before repeating
/* RandomHat Paul Badger 2007 - updated for Teensy compile 2017 choose one from a hat of n consecutive choices each time through loop Choose each number exactly once before reseting and choosing again */ #define randomHatStartNum 10 // starting number in hat #define randomHatEndNum 25 // ending number in hat - end has to be larger than start #define numberInHat (randomHatEndNum - randomHatStartNum) + 1 void setup() { Serial.begin(9600); Serial.println("start "); } void loop() { // randomHat test for (int i = 1; i <= numberInHat; i++) { int x = randomHat(); Serial.print(x); Serial.print(", "); delay(50); } Serial.println(" "); } int randomHat() { int thePick; //this is the return variable with the random number from the pool int theIndex; static int currentNumInHat = 0; static int randArray[numberInHat]; if (currentNumInHat == 0) { // hat is emply - all have been choosen - fill up array again for (int i = 0 ; i < numberInHat; i++) { // Put 1 TO numberInHat in array - starting at address 0. if (randomHatStartNum < randomHatEndNum) { randArray[i] = randomHatStartNum + i; } } currentNumInHat = abs(randomHatEndNum - randomHatStartNum) + 1; // reset current Number in Hat // Serial.print(" hat is empty "); // if something should happen when the hat is empty do it here } theIndex = random(currentNumInHat); //choose a random index from number in hat thePick = randArray[theIndex]; randArray[theIndex] = randArray[currentNumInHat - 1]; // copy the last element in the array into the the empty slot // // as the the draw is random this works fine, and is faster // // the previous version. - from a reader suggestion on this page currentNumInHat--; // decrement number in hat return thePick; }
added 2010-10-30.
A speed up of the reshuffling of the array at the end. Change
for (i = theIndex; i<= (currentNumInHat - 1); i++){ randArray[i] = randArray[i + 1]; // bump all the higher array contents down one, erasing the last number chosen }
in
randArray[theIndex] = randArray[currentNumInHat-1];
The idea is that the slot at theIndex becomes free and we just copy the last element from the array to that 'empty' slot. As the draw must be random this does not interfere.