0
public static GetRandomFunc() {
    switch((int)(Math.random()*NUM_FUNCTIONS)  {
        case 0:
            functionA();
            break;
        case 1:
            functionB();
            break;
        case 2:
            functionC();
            break;
          //  ...
    }
}

I want to call GetRandomFunc() in main randomly until each function has been called once and then it ends. How do I make sure a function would be called once only, and not called again.

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
user872009
  • 428
  • 2
  • 4
  • 18

4 Answers4

4

It would be easier to store values in an collection, and draw them out randomly until the collection is empty. Or better yet, shuffle the collection and then walk over it sequentially.

The values in the collection could be integers, or they could be objects of different classes (with a common superclass or interface), which provide different implementations of a call() method.

For example:

import java.util.*;
import java.util.concurrent.*;

List<Runnable> functions = new ArrayList<Runnable>();
functions.add(new Runnable() {
  public void run() { /* do something */ }
});
functions.add(new Runnable() {
  public void run() { /* do something else */ }
});

Collections.shuffle(functions);
for(Runnable function : functions)
  function.run();

The other posts on this thread show other potential solutions, but all of them are more complex and error-prone than this one, and most of them would be very slow if the number of functions is large. (The one from @AndersLinden is an exception -- it would still be fast even if there are thousands of functions to call.)

Alex D
  • 29,755
  • 7
  • 80
  • 126
0

Bit fields to record whether a function has been called and an if statement to not call the function if it's bit is already set - keep looping until all of the bits are set.

(or as Alex D says, create a collection of numbers to use up front)

Either way the trick is to make sure you generate each number once and once only - if you screw this bit up you can end up in an infinite loop (e.g. waiting to get numbers 1, 2 and 3, but your random function is generating 0, 1 and 2)

John3136
  • 28,809
  • 4
  • 51
  • 69
0

You could create an array to keep track of which functions have already been used.

For example:

boolean[] usedFunctions = new boolean[NUM_FUNCTIONS];

public static GetRandomFunc() {
    switch((int) (Math.random() * NUM_FUNCTIONS) {
        case 0:
            if(!usedFunctions[0]) {
                functionA();
                usedFunctions[0] = true;
            }
            break;
        case 1:
            if(!usedFunctions[1]) {
                functionB();
                usedFunctions[1] = true;
            }
            break;
        // etc.
     }
}

Then all you need to do is repeatedly call GetRandomFunc() until all elements in usedFunctions are true.

Will Manson
  • 167
  • 1
  • 4
  • 12
  • Hi, it calls it only once. I tried calling it from main, but it only calls the first function, and then stops. – user872009 Aug 07 '12 at 07:10
0

You keep an array of integers that tells which indexes that are still not used. When you have used an integer, you fill it in the hole with the last index in the list and treat it as a list with one item shorter.

int indexes[] = new int[3];

for (int i = 0; i < 3; i++)
  indexes[i] = i;

for (int i = 0; i < 3; i++)
{
  int index = (int)(Math.random()*(3 - i));
  switch (indexes[index])
  {
    case 0:
      functionA();
      break;
    case 1:
      functionB();
      break;
    case 2:
      functionC();
      break;
  }

  indexes[index] = indexes[2 - i];
}
Anders Lindén
  • 6,839
  • 11
  • 56
  • 109