Determine the winner of a coin flip game While I was writing this I had some thoughts and questions going through my head about if I was doing this in a good manner. For instance, is it good to use a StringTokenizer to loop through the words in the line I copied from the Scanner's input?


  Write a method named coinFlip that accepts as its parameter a Scanner for an input file. Assume that the input file data represents results of sets of coin flips that are either heads (H) or tails (T) in either upper or lower case, separated by at least one space. Your method should consider each line to be a separate set of coin flips and should output to the console the number of heads and the percentage of heads in that line, rounded to the nearest tenth. If this percentage is more than 50%, you should print a "You win" message.


public static void coinFlip(Scanner input) {
    
    int countHeads = 0;
    int countTails = 0;
    double count = 0.0;
    double ratio = 0.0;
    String line = "";
    
    while(input.hasNextLine()) {
        countHeads = 0;
        countTails = 0;

        line = input.nextLine();
        StringTokenizer lineTokens = new StringTokenizer(line);
        while (lineTokens.hasMoreTokens()) {
            String token = lineTokens.nextToken();
            if (token.toLowerCase().equals("h")) {
                countHeads++;
            } else {
                countTails++;
            }
        }

        count = countTails + countHeads;

        ratio = Math.abs(1 - (countTails/count)) * 100;

        System.out.printf(countHeads + " heads (%1.1f%%)\n", ratio);

        if (countHeads &gt; countTails) {
            System.out.println("You win!\n");
        }
        else {
            System.out.println();
        }
    }
}
The biggest simple improvement you could make would be to declare your variables in a more limited scope.  As you have written it, I cannot easily tell whether the statistics are cumulative, or each line is being treated as an independent problem.

count being a double is weird; it should be an int.

I suggest calling .toLowerCase() once per line instead of once per word.

It's probably worthwhile to do an extra simple check to ensure that every word that is not an "H" is a "T".

The calculation for ratio is more complicated than it needs to be.

You aren't using printf() effectively — the whole point of printf() is to take advantage of the format string rather than concatenation.

public static void coinFlip(Scanner input) {
    while (input.hasNextLine()) {
        int heads = 0, tails = 0;

        StringTokenizer tokens =
            new StringTokenizer(input.nextLine().toLowerCase());
        while (tokens.hasMoreTokens()) {
            String token = tokens.nextToken();
            if ("h".equals(token)) {
                heads++;
            } else if ("t".equals(token)) {
                tails++;
            }
        }

        double ratio = 100.0 * heads / (heads + tails);
        System.out.printf("%d heads (%1.1f%%)\n", heads, ratio);
        System.out.println((heads &gt; tails) ? "You win!\n" : "");
    }
}


One alternative to StringTokenizer would be to use Scanner.findInLine().

public static void coinFlip(Scanner input) {
    while (input.hasNextLine()) {
        int heads = 0, tails = 0;
        String token;
        while (null != (token = input.findInLine("\\b[HhTt]\\b"))) {
            switch (token) {
                case "H": case "h": heads++; break;
                case "T": case "t": tails++; break;
            }
        }

        double ratio = 100.0 * heads / (heads + tails);
        System.out.printf("%d heads (%1.1f%%)\n", heads, ratio);
        System.out.println((heads &gt; tails) ? "You win!\n" : "");
    }
}