Simulates flipping a coin repeatedly and continues until however many consecutive heads are tossed
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; }
  }
}