A random function that chooses every number from a "hat" before repeating
/* RandomHat
Paul Badger 2007
choose one from a hat of n choices each time through loop
Choose each number exactly once before reseting and choosing again
*/
#define randomHatStartNum 0
#define randomHatEndNum 10
#define NumberInHat abs(randomHatEndNum - randomHatStartNum) + 1
int i, x;
void setup()
{
Serial.begin(9600);
Serial.println("start ");
}
void loop()
{ // randomHat test
for (i=1; i<=NumberInHat; i++){
x = randomHat();
Serial.print(x);
Serial.print(" ");
delay(100);
}
Serial.println(" ");
}
int randomHat(){
static int totalNumInHat = abs(randomHatEndNum - randomHatStartNum) + 1;
static int currentNumInHat = 0;
abs(randomHatEndNum - randomHatStartNum) + 1;
static int randArray[abs(randomHatEndNum - randomHatStartNum) + 1];
int i; //as long as they can be changed without harming other code
int thePick; //this is the return variable with the random number from the pool
int theIndex;
if (currentNumInHat == 0){ // hat is emply - all have been choosen - fill up array again
for (i = 0 ; i<=(totalNumInHat - 1); i++){ // Put 1 TO numberInHat in array - starting at address 0.
if (randomHatStartNum < randomHatEndNum){
randArray[i] = randomHatStartNum + i; }
else if (randomHatStartNum > randomHatEndNum){ // defensive programming in case startNum is greater than endNum
randArray[i] = randomHatEndNum + i; }
else{
return randomHatStartNum; } // startNum and endNum must be same number - return one - and bail out
}
currentNumInHat = abs(randomHatEndNum - randomHatStartNum) + 1; // reset current Number in Hat
//if something should happen when the hat is empty do it here
}
theIndex = random(currentNumInHat); //choose a random index
thePick = randArray[theIndex];
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
}
currentNumInHat--; // decrement counter
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.