Three faces coin flip

Hello everybody,
I need to simulate a coin flip, but with three possible outcomes, method1(), method2() and method3(). But if method1() is completed, then go to method2(), but if method2() is completed then go to method3() and so on…

Right now I came up with this working code, it does the job, but I want to ask you if it can be improved (some parts are written in pseudo-code, just to give you the idea):

void coin() {
  float coin = random(0.0, 1.0);

  if (coin < 0.3) {
    if (method1() != completed) {
      method1();
    } else {
      if (method3() != completed) {
        method3();
      } else { 
        if (method2() != completed) {
          method2();
        }
      }
    }
  } else if (coin >= 0.3 && coin < 0.6) {
    if (method2() != completed) {
      method2();
    } else {
      if (method1() != completed) {
        method1();
      } else { 
        if (method3() != completed) {
          method3();
        }
      }
    }
  } else {
    if (method3() != completed) {
      method3();
    } else {
      if (method2() != completed) {
        method2();
      } else {
        if (method1() != completed) {
          method1();
        }
      }
    }
  }
}

thank you so much :grin:

1 Like

Yes, you have an array of strings: 123, 231, 321.

You toss the coin, gives you 0,1,2 - use this an index (no ifs involved).

Then you have one of 3 Strings from the array. Make a function that evaluates / interpretes the String. This can be much shorter (or what you have now, but only once?). If method 1 is finished indexOfChar++;

I would do it like this:

method[] meths = new method[3];

void coin() {
  
  int coin = (int)random(0,4);
  int index = coin;
  
  while (meths[index].full == true && index <= 3) {
   
    index++;
    
  }
  
  meths[index].method();
  
}

You should make the method a class, but if you want each method to do something different then you should use this:

method[] meths = new method[3];

void coin() {
  
  int coin = (int)random(0,4);
  int index = coin;
  
  while (meths[index].full == true && index <= 3) {
   
    index++;
    
  }
  
  meths[index].num = index;
  meths[index].method();
  
}

and the class would be

class method {
  
 int num;
 boolean full;
 
 void method() {
   if (num == 1) {
     
     do stuff 1;
     
   } else if (num == 2) {
    
     do stuff 2;
     
   }else {
     
     do stuff 3;
     
  }
  
}

what I did was make coin an integer between 1 and 3.
And I made a class called method, then I made an array of that class.
The while loop will make the other method run if the other is full, It will break when the one is full or the index is greater than 3. If meths[3] is full then it will run 3.

Thanks.

2 Likes

I still need some free time to implement this solution. Do you think is better in terms of performances? :slightly_smiling_face:

For me your “and so on” is underspecified.

If I flip a 3, is the result method3?
Or is it method3, method1, method2?

If I flip 3, then 3, are the results method3, method3?
Or are they method3, method1?

Can I flip more than 3 times? Do the three options get used up, and if so then what?

Hey Jeremy, I’ll try to answer you in the best way possible.
As you can see from the code “and so on” means:
if you flip a 3 nothing happens because the ranges are from 0.0 to 1.0, but if we assume that if I flip 1 is for the first condition, 2 the second and 3 the third this is the code behaviour:

flip a 3 -> if method3 it’s not completed use method3, but if it’s complete then check if method1 is completed, if not use method1, but if it’s completed then check if method2 is completed, if it’s not use it.
flip a 3 again -> if method3 it’s not completed use method3, but if it’s complete then check if method1 is completed, if not use method1, but if it’s completed then check if method2 is completed, if it’s not use it.
flip a 1 -> if method1 it’s not completed use method1, but if it’s complete then check if method3 is completed, if not use method3, but if it’s completed then check if method2 is completed, if it’s not use it.

Yes, you flip the coin infinite times

Yes method1, method2, method3 can finish their purpose. In fact the general conditions if (method1() != completed), if (method2() != completed), if (method3() != completed) check if each method has completed its job.
Ex.: if in method1() I’m removing something from an ArrayList list1 then the condition could be written as if (list1.size() != 0) such as when method1() has removed all the items from list1 it shouldn’t be called anymore

Is it more clear now? :grin:

Got it. A circular checklist. Calling an index marks marks it off and returns it – or advanced to the next available, then marks that off and returns iit. If all are used, do nothing.

You can do a circular search on any index using a for-loop with modulo. Given that you want to “lookup else advance to the next”, popping items out of a list isn’t a good idea, as this will shift lookup indices.

Here is a very simple implementation of a circular checklist:

class CheckRing {
  boolean[] vals;
  CheckRing(int length) {
    this.vals = new boolean[length];
  }
  // Search in a loop from val[idx] to the next false val.
  // Mark true and return index.
  // If all vals are true, return -1.
  int next(int idx) {
    for (int i=0; i<vals.length; i++) {
      int id = (i+idx)%vals.length;
      if (!vals[id]) {
        vals[id] = true;
        return id;
      }
    }
    return -1;
  }
}

We could use a CheckRing plus code in draw() to call top-level sketch functions. Or we could add a CheckRing to an object and use it to choose object methods to call.

OR we could extend a CheckRing into a MethodRing, and write a group of methods right there.

class MethodRing extends CheckRing {
  MethodRing(int length) {
    super(length);
  }
  int next(int idx) {
    int id = super.next(idx);
    switch(id) {
    case 0: 
      method0(); 
      break;
    case 1: 
      method1(); 
      break;
    case 2: 
      method2(); 
      break;
    default: 
      println("..."); 
      break;
    }
    return id;
  }
  void method0() { 
    println("0!");
  }
  void method1() { 
    println("1!");
  }
  void method2() { 
    println("2!");
  }
}

We can test these classes with ring size = 3, and they work…

void setup() {
  CheckRing cr = new CheckRing(3);
  // test with 0, 2, 4, 6
  for (int i=0; i<=6; i+=2) {
    println(cr.next(i));
  }
  println();
  MethodRing mr = new MethodRing(3);
  // test with 2, 2, 2, 2
  for (int i=0; i<4; i++) {
    mr.next(2);
  }
}

0
2
1
-1

2!
0!
1!

This would also work with four items… or 40.

1 Like