CompSci.rocks
FRQcsapa

Scoreboard: 2024 FRQ 2

A step-by-step solution to the 2024 AP CSA FRQ 2 (Scoreboard), covering designing a class from scratch around an alternating-turn state machine in Java.

Two teams trading turns back and forth is the scenario behind this AP Computer Science A free-response question — you design an entire class from a plain-English description of the rules, with no starter code given at all.

What This FRQ Tests

  • AP CSA units: Unit 5 (Writing Classes)
  • Core skill: designing instance variables that track both accumulated state (scores) and a single piece of "which team's turn is it" state, from nothing but a rules description
  • Secondary skill: building a formatted String that reports several pieces of state at once
  • Official category: "Classes" — always FRQ 2 on the AP CSA exam

The Setup

  • No class skeleton is provided — the entire Scoreboard class, including its fields, is up to you to design.
  • Behavior is fully specified by the constructor and two methods:
    • Scoreboard(String team1Name, String team2Name) — team 1 always starts as the active team
    • void recordPlay(int points) — a play that scores points > 0 keeps the same team active and adds to its score; a play of exactly 0 ends that team's turn and switches which team is active
    • String getScore() — returns "<team1Score>-<team2Score>-<activeTeamName>"
  • The question includes a full worked execution sequence (reproduced below), and the finished class must return every value in it exactly.

Building the Scoreboard Class

Step-by-Step Approach

  1. Decide what state needs to persist between calls: both team names, both scores, and which team is currently active.
  2. In the constructor, store both names, initialize both scores to 0, and set team 1 as active.
  3. In recordPlay, branch on whether points is 0. If it's 0, flip which team is active. Otherwise, add points to whichever team's score is currently active — and leave the active team unchanged.
  4. In getScore, figure out the active team's name based on the stored active-team state, then concatenate the two scores and that name with hyphens in between.

The Code

public class Scoreboard
{
    private String name1;
    private String name2;
    private int score1;
    private int score2;
    private boolean team1Active;

    public Scoreboard(String team1Name, String team2Name)
    {
        name1 = team1Name;
        name2 = team2Name;
        score1 = 0;
        score2 = 0;
        team1Active = true;
    }

    public void recordPlay(int points)
    {
        if (points == 0)
        {
            team1Active = !team1Active;
        }
        else
        {
            if (team1Active)
            {
                score1 = score1 + points;
            }
            else
            {
                score2 = score2 + points;
            }
        }
    }

    public String getScore()
    {
        String activeName;

        if (team1Active)
        {
            activeName = name1;
        }
        else
        {
            activeName = name2;
        }

        return score1 + "-" + score2 + "-" + activeName;
    }
}

Why Each Piece Matters

  • A single boolean team1Active field, rather than a String naming the active team — since there are only ever two teams and they strictly alternate, a boolean fully captures "which one" without needing to store or compare names.
  • team1Active = !team1Active — flipping a boolean is the simplest way to express "switch to whichever team isn't currently active," and it works correctly regardless of which team was active beforehand.
  • The if (points == 0) check comes first, before anything about scoring — the entire method branches on this one condition, with scoring only happening in the else.
  • The active team never changes when points > 0 — the rule says the team "remains active" after a successful play, so nothing about team1Active is touched in that branch.

Tracing the Example

Using the question's own execution sequence, game = new Scoreboard("Red", "Blue"):

Call team1Active score1 score2 getScore()
(after construction) true 0 0 "0-0-Red"
recordPlay(1) true 1 0 "1-0-Red"
recordPlay(0) false 1 0 "1-0-Blue"
recordPlay(3) false 1 3 "1-3-Blue"
recordPlay(1) false 1 4
recordPlay(0) true 1 4 "1-4-Red"
recordPlay(0) false 1 4
recordPlay(4) false 1 8
recordPlay(0) true 1 8 "1-8-Red"

Every value matches the question's table exactly, including a brand-new Scoreboard object (match) created partway through the sequence returning "0-0-Lions" independently, without disturbing game's own state at all — confirming that each Scoreboard object tracks its own fields separately.

Common Mistakes to Avoid

  • Flipping team1Active on every call, not just when points == 0. A successful scoring play must leave the active team unchanged.
  • Adding points to the wrong team's score — always double check that points go to whichever team team1Active currently says is active, not a fixed team.
  • Building the returned String in the wrong order. The rule is specifically team 1's score, then team 2's score, then the active team's name — not the active team's score first.
  • Forgetting that a new Scoreboard object needs its own independent fields. Each object should track its own scores and active team, unaffected by any other Scoreboard object's state.

Key Takeaways

  • When a class needs to track "which of exactly two things is currently true," a single boolean is simpler and safer than storing a name or index to compare against later.
  • Toggling state with flag = !flag is the standard way to express "switch to the other one" without an if/else.
  • When no class skeleton is given, work backward from the method signatures and any worked example table — they tell you exactly what state the class needs to hold.

Related FRQs