Sunday, August 7, 2011

Program to Flip a Coin (until you get 3 "heads" in a row):

"Write a program that simpulates flipping a coin repeatedly and continues until three consecutive heads are tossed. At that point your program should display the total number of times the coin was flipped." (Roberts ch 6, problem 2).

What it looks like:



/*
/* File: FlipThreeHeads.java
 * ----------------------------
 * This program simulates flipping coin repeatedly until you get 3 heads in a row, at which point you
 * print how many flips it took to get those 3. It uses an instance of the RandomGenerator class and keeps count using a local variable 'count.'
 */

import acm.program.*;
import acm.util.*;
public class FlipThreeHeads extends ConsoleProgram{
 
    public void run() {
     
        // Placeholders X, Y and Z to store the most recent flip and the past 2 flips (when they happen):
        String flipX = flipCoin(); 
        println(flipX);
        String flipY = null;
        String flipZ = null;
        
        // Local variable to keep track of how many flips we've done so far:
        int count = 1;
  
       //"As long as X, Y and Z aren't equal to each other and aren't 'heads'..."
        while ((flipX != flipY) || (flipX != flipZ) || (flipZ != "heads")){
            count += 1;
            String nextCoin = flipCoin();
            println(nextCoin);
            //Shove down the values of the placeholders to make flipX the most recent result  
            flipZ = flipY;
            flipY = flipX;
            flipX = nextCoin;
        }
        println("It took " + count + " tries to get 3 consecutive heads.");  
    }
 
    private RandomGenerator rgen = RandomGenerator.getInstance();

    private String flipCoin() {
        boolean booleanResult = rgen.nextBoolean();
  
        String flipResult;
        if (booleanResult == true) {
            flipResult =  "heads";
        } else {
            flipResult = "tails";
        }
        return flipResult;
    }
}

What made this hard/interesting:

Naming things is hard! Because this program requires that you keep track of the 3 most recent flips so that you can compare them and see if there were 3 heads in a row, you have to create a lot of variables. However, I kept being tempted to use variable names like "flipCoin" and "nextFlip" since they all do similar things related to the actual coin flip. If there's a way to make this program more spartan and not use as many variables that would be great.

Here's how a run of the program works and each step needs its own variable or set of variables:

1) You establish 3 local variables "flipX," "flipY" and "flipZ." As we keep flipping our programmatic coin these will keep track of the 3 latest flips. We will build a shove-over mechanism so that with each new coin flip, we'll turn flipX into the latest result, turn flipY into the old value for flipX, and turn flipZ into the old value for flipY.

Also, you create flipX with an initial value by calling the flipCoin() method.

2) The flipCoin() method is a private method that we call that just simulates flipping a coin. It works by pulling a random boolean out of our RandomGenerator instance and translating the returned "true" or "false" into "heads" or "tails."

3) booleanResult is a local variable inside the flipCoin() method that stores the "true" or "false" that gets returned from calling nextBoolean(). flipResult is a local variable that takes the boolean and stores the "head" or "tail" translation.

4) nextCoin is part of our main method and always stores the most recent flip. We keep resetting it as we keep on flipping coins (and resetting flipX to equal it and going on with the shove-down mechanism described in step (1).

The "flipCoin" method was particularly hard to make up names for inside because there are 3 variables that mean essentially the same thing (those that turned out to be called "flipResult," "booleanResult" and "flipCoin." I kept on being tempted to name them "flipResult", but all the distinct variables are necessary in order to return the desired result.