CompSci.rocks
FRQcsapa

HiddenWord: 2015 FRQ 2

A step-by-step solution to the 2015 AP CSA FRQ 2 (HiddenWord), covering building a word-guessing game class that compares strings letter by letter in Java.

A word-guessing game with letter-by-letter feedback drives this AP Computer Science A free-response question — you build the entire class that compares a hidden word to a guess and produces a hint string, one character at a time.

What This FRQ Tests

  • AP CSA units: Unit 5 (Writing Classes)
  • Core skill: writing a complete class from a plain-English description, including its constructor and one method
  • Secondary skill: comparing characters position-by-position across two equal-length strings, and checking whether a character shows up somewhere else in a string
  • Official category: this year's FRQ 2 fits cleanly into the "Classes" category (Unit 5). Pre-2019 AP CSA exams didn't follow today's fixed FRQ-number-to-category order, but for 2015 this particular question happens to line up with what's now the modern FRQ-2 slot.

The Setup

  • No class skeleton is given at all — the entire HiddenWord class is up to you to design
  • The constructor takes the hidden word as a String (capital letters only)
  • One method: getHint(String guess), where guess is guaranteed to be the same length as the hidden word
  • The rule for each position in the returned hint:
    • Guess letter matches the hidden word's letter at that exact position → that letter itself
    • Guess letter appears somewhere in the hidden word, just not at that position → "+"
    • Guess letter doesn't appear in the hidden word at all → "*"

Building the HiddenWord Class

Step-by-Step Approach

  1. Store the hidden word in an instance variable — it's the only piece of state that needs to persist between calls to getHint.
  2. In getHint, build the hint one character position at a time, inside a loop.
  3. At each position, pull out the guess's letter and the hidden word's letter at that same index.
  4. If the two letters match, add that letter to the hint being built.
  5. If they don't match, check whether the guess's letter appears anywhere in the hidden word — if so, add "+".
  6. Otherwise, add "*".
  7. Return the finished hint after the loop completes.

The Code

public class HiddenWord
{
    private String word;

    public HiddenWord(String w)
    {
        word = w;
    }

    public String getHint(String guess)
    {
        String hint = "";

        for (int i = 0; i < word.length(); i++)
        {
            String guessLetter = guess.substring(i, i + 1);
            String wordLetter = word.substring(i, i + 1);

            if (guessLetter.equals(wordLetter))
            {
                hint = hint + guessLetter;
            }
            else if (word.indexOf(guessLetter) != -1)
            {
                hint = hint + "+";
            }
            else
            {
                hint = hint + "*";
            }
        }

        return hint;
    }
}

Why Each Piece Matters

  • word.substring(i, i + 1) pulls out a single-character String at position i — this is how the solution gets "the letter at position i" while sticking to a method that's on the AP CSA Quick Reference sheet. charAt would return that character more directly, but it isn't listed there (see the Notes section below for that version).
  • .equals(), never ==, for comparing the two single-character strings — two separately-built String objects with identical characters aren't guaranteed to be the same object in memory.
  • Order matters: the exact-position check happens first, and the indexOf check only runs when that first check has already failed. An exact match must never fall through and get reported as a "+" instead.
  • word.indexOf(guessLetter) != -1, reached only after the exact-match check already failed, doesn't need to separately confirm the letter is at a different position — if it had been at the same position, the first check would already have caught it.

Tracing the Example

Using the question's own setup, puzzle = new HiddenWord("HARPS"), here's puzzle.getHint("HEART") traced position by position:

Position Guess letter Word letter Same-position match? Appears elsewhere in word? Hint character
0 H H yes H
1 E A no no *
2 A R no yes (A is at index 1) +
3 R P no yes (R is at index 2) +
4 T S no no *

Final result: "H*++*" — matches the question's table exactly.

The same position-by-position logic produces the rest of the question's examples too: "+A+++" for "AAAAA", "H****" for "HELLO", "HAR*S" for "HARMS", and "HARPS" for "HARPS" itself (every letter matching its own position).

Common Mistakes to Avoid

  • Checking indexOf before checking for an exact match. Since indexOf would still find the letter even when it's at the exact same position, checking it first would report every correctly-placed letter as a "+" instead of the letter itself.
  • Comparing the single-character strings with == instead of .equals(). This is one of the most common AP CSA point losses anywhere String comparison shows up.
  • Building the hint as a char[] and forgetting to convert it back to a String — the method's return type is String, not char[].
  • Looping over guess.length() instead of word.length(). The two are guaranteed equal here, but tying the loop bound to the object's own stored state (word) is the more defensible habit.

Notes: A Simpler Way to Grab a Single Character

public String getHint(String guess)
{
    String hint = "";

    for (int i = 0; i < word.length(); i++)
    {
        char guessLetter = guess.charAt(i);
        char wordLetter = word.charAt(i);

        if (guessLetter == wordLetter)
        {
            hint = hint + guessLetter;
        }
        else if (word.indexOf(guessLetter) != -1)
        {
            hint = hint + "+";
        }
        else
        {
            hint = hint + "*";
        }
    }

    return hint;
}
  • charAt(i) returns the character at a position directly, instead of pulling out a one-character String with substring(i, i + 1).
  • charAt isn't listed on the AP CSA Quick Reference sheet, but that doesn't mean it's disallowed — AP CSA graders accept any correct Java, not just methods printed on the sheet. The real tradeoff is not being able to look its exact behavior up during the exam if you second-guess yourself, the way you could with substring.
  • Since char is a primitive type, == correctly compares two char values by content here — this is one of the few places in Java where == is genuinely the right choice, unlike comparing String objects.

Key Takeaways

  • When a rule has multiple fallback conditions, check the most specific case (an exact match) before falling back to a more general one (appears anywhere) — checking out of order silently changes the answer.
  • substring(i, i + 1) is the Quick-Reference-safe way to pull a single character out of a String when charAt isn't the method you want to rely on.
  • Building a String piece-by-piece inside a loop, then returning it once the loop finishes, is a pattern that shows up across many AP CSA FRQs well beyond this one.

Related FRQs