Simulates flipping a coin repeatedly and continues until however many consecutive heads are tossed This program simulates flipping a coin repeatedly and continues until however many consecutive heads are tossed.  

I'm wondering if there are any issues when initializing a variable in a for loop the way I did. Also I assume assigning -1 to i was an appropriate move as well because after a loop cycle it will iterate (i++) causing i to become 1 if I had not, resulting in one less loop.

/*
 * File: ConsecutiveHeads.java
 * ---------------------------
 * This program simulates flipping a coin 
 * repeatedly and continues until however many
 * consecutive heads are tossed.
 */

/* Library packages */
import acm.program.*;
import acm.util.RandomGenerator;

public class ConsecutiveHeads extends ConsoleProgram {

    public void run() {
        int flips = 0;
        for (int i = 0; i &lt; CONSECUTIVE_HEADS; i++) {
            String coinSide = flipCoin();
            println(coinSide);
            flips++;
            if (coinSide.equals("Tails")) {
                i = -1;
            }
        }
        println("It took " + flips + " flips to "
                + "get " + CONSECUTIVE_HEADS + " consecutive heads.");
    }

    /* Returns true 50% of the time */
    private String flipCoin() {
        return rgen.nextBoolean() ? "Tails" : "Heads";
    }

    /* Create an instance variable for the random number generator */
    private RandomGenerator rgen = RandomGenerator.getInstance();

    /* Private constant */
    private static final int CONSECUTIVE_HEADS = 3;
}
Loop


  Also i assume assigning -1 to i was an appropriate move as well because after a loop cycle it will iterate (i++) causing i to become 1 if I had not, resulting in one less loop.


Well, that works, but I think it would be more clear to explicitly increment i on heads, and reset it otherwise:

for (int consecutiveHeads = 0; consecutiveHeads &lt; CONSECUTIVE_HEADS_THRESHOLD;) {
  ...
  if (coinSide.equals("Heads")) {
    consecutiveHeads++;
  } else {
    consecutiveHeads = 0;
  }
}


That could be a while loop as well, depending on your tastes.

Comments


/* Create an instance variable for the random number generator */



This is not really necessary. It's clearly an instance variable, and the names and types show that it is a RNG.


/* Private constant */



Again, this isn't really necessary. private final already shows that is is a private constant. Even if you these comments are more intended for organization, a common approach would be to group these variables in blocks at the top of the class, with implicit meaning.

They don't take away from anything, they're just not really necessary.


/* Returns true 50% of the time */
private String flipCoin() {



This is not accurate. It will never return true. It returns strings.

Matching strings

Matching against strings is somewhat fragile. If this was a larger codebase, you would probably implement an enum for the coin sides, although it's overkill for this example. Altogether, a slightly more genericized version might look something like this:

public class ConsecutiveHeads extends ConsoleProgram {

  // These traditionally go up top, not at the bottom of the class.
  private final RandomGenerator rgen = RandomGenerator.getInstance();
  private static final int DEFAULT_CONSECUTIVE_HEADS_THRESHOLD = 3;

  public void run() {
    run(DEFAULT_CONSECUTIVE_HEADS_THRESHOLD);
  }

  // Theshold is parameterized
  public void run(final int consecutiveHeadsThreshold) {
    int flips = 0;
    for (int consecutiveHeads = 0; consecutiveHeads &lt; consecutiveHeadsThreshold;) {
      CoinSide toss = flipCoin();
      flips++;
      println(toss.getName());

      if (CoinSide.HEADS.equals(toss)) {
        consecutiveHeads++;
      } else {
        consecutiveHeads = 0;
      }
    }
    System.out.printf("It took %d flips to get %d consecutive heads.", flips, consecutiveHeadsThreshold);
  }

  private CoinSide flipCoin() {
    return CoinSide.from(rgen.nextBoolean());
  }

  // Alternatively, in the limited scope of this example, you could
  // just define `true` to be heads and then not bother defining tails
  // at all.
  enum CoinSide {
    HEADS("Heads"), TAILS("Tails");

    private final String name;
    CoinSide(String name) { this.name = name; }
    public String getName() { return name; }

    public static CoinSide from(bool value) { return value ? HEADS : TAILS; }
  }
}