2024 FRQ
2024 FRQ
My Solution Code
// Create the Scoreboard Class HERE
class Scoreboard {
// Define your properties HERE
private String team1Name;
private String team2Name;
private int team1Score;
private int team2Score;
private int activeTeam; // 1 for team1, 2 for team2
public Scoreboard(String team1Name, String team2Name) {
// This is your CONSTRUCTOR
// Initialize your properties HERE (team names and active team)
this.team1Name = team1Name;
this.team2Name = team2Name;
this.team1Score = 0;
this.team2Score = 0;
this.activeTeam = 1; // team1 starts as active
}
public void recordPlay(int points) {
// Create the recordPlay Method HERE
if (points > 0) {
// Add points to active team and keep them active
if (activeTeam == 1) {
team1Score += points;
} else {
team2Score += points;
}
} else {
// Failed play: switch to inactive team
activeTeam = (activeTeam == 1) ? 2 : 1;
}
}
public String getScore() {
// Create the getScore Method HERE
String activeName = (activeTeam == 1) ? team1Name : team2Name;
return team1Score + "-" + team2Score + "-" + activeName;
}
}
// Testing the Scoreboard class (DO NOT MODIFY this part unless you change the class, method, or constructer names)
// DO NOT MODIFY BELOW THIS LINE
public class Main {
public static void main(String[] args) {
String info;
// Step 1: Create a new Scoreboard for "Red" vs "Blue"
Scoreboard game = new Scoreboard("Red", "Blue");
// Step 2
info = game.getScore(); // "0-0-Red"
System.out.println("(Step 2) info = " + info);
// Step 3
game.recordPlay(1);
// Step 4
info = game.getScore(); // "1-0-Red"
System.out.println("(Step 4) info = " + info);
// Step 5
game.recordPlay(0);
// Step 6
info = game.getScore(); // "1-0-Blue"
System.out.println("(Step 6) info = " + info);
// Step 7 (repeated call to show no change)
info = game.getScore(); // still "1-0-Blue"
System.out.println("(Step 7) info = " + info);
// Step 8
game.recordPlay(3);
// Step 9
info = game.getScore(); // "1-3-Blue"
System.out.println("(Step 9) info = " + info);
// Step 10
game.recordPlay(1);
// Step 11
game.recordPlay(0);
// Step 12
info = game.getScore(); // "1-4-Red"
System.out.println("(Step 12) info = " + info);
// Step 13
game.recordPlay(0);
// Step 14
game.recordPlay(4);
// Step 15
game.recordPlay(0);
// Step 16
info = game.getScore(); // "1-8-Red"
System.out.println("(Step 16) info = " + info);
// Step 17: Create an independent Scoreboard
Scoreboard match = new Scoreboard("Lions", "Tigers");
// Step 18
info = match.getScore(); // "0-0-Lions"
System.out.println("(Step 18) match info = " + info);
// Step 19: Verify the original game is unchanged
info = game.getScore(); // "1-8-Red"
System.out.println("(Step 19) game info = " + info);
}
}
Code Runner Cell and Output
Reflection on My Approach
Problem Understanding
I approached this FRQ with a solid grasp of the requirements. The key insight I recognized was that this problem required tracking state - specifically, which team is active - rather than just accumulating scores. Many students might initially miss this and focus only on score tracking, but I correctly identified that managing activeTeam as a mutable state variable was central to the solution.
Design Decisions
State Representation: I chose to represent activeTeam as an integer (1 or 2) rather than a boolean or enum. This was a pragmatic choice that allowed for simple toggle logic using a ternary operator: activeTeam = (activeTeam == 1) ? 2 : 1. While an enum might be more “semantically clean,” my approach prioritized simplicity and was perfectly sufficient for this use case.
Score Storage: I maintained separate integer variables for team1Score and team2Score rather than using an array or map. This is actually preferable here because:
- The problem explicitly mentions “team 1” and “team 2” throughout
- It makes the constructor and methods more explicit and readable
- It aligns with how many students think about the problem naturally
Team Names: Storing both team names in the constructor was essential. Without this, the getScore() method wouldn’t know which team name to return as the active team. This shows I understood the complete requirements.
Strengths of My Solution
- Correct Logic in
recordPlay(): The conditional structure perfectly captures the business logic:- If points > 0: add to active team’s score, keep them active
- If points == 0: switch active team (no score change)
The use of a simple
if-elserather thanelse ifis appropriate here since we only have two cases. -
Clean
getScore()Format: My string formatting correctly produces the required “score1-score2-activeTeamName” format. I used a ternary to look up the active team name, which is concise and readable. -
Proper State Initialization: The constructor sets all four instance variables correctly, including setting
activeTeam = 1to satisfy the requirement that “the game always begins with team 1 as the active team.” - Independence of Objects: My solution correctly creates independent
Scoreboardobjects (the difference betweengameandmatchin the test cases demonstrates this). Each instance has its own state, which is fundamental to proper OOP design.
Code Quality Observations
Comments: I included helpful comments explaining each section (especially “1 for team1, 2 for team2” and “Failed play: switch to inactive team”). These comments show I understood why the code works, not just how to make it work.
No Unnecessary Complexity: I didn’t over-engineer the solution with extra methods, collections, or helper variables. The solution is minimal and focused - this is a strength in timed assessments and competitive programming.
Variable Naming: Names like team1Name, team2Score, and activeTeam are self-documenting. Someone reading my code can immediately understand what each variable represents without needing to trace through logic.
What I Handled Well
-
The Toggle Logic: The ternary operator for switching teams (
activeTeam = (activeTeam == 1) ? 2 : 1) is elegant and correct. It demonstrates understanding of Java ternary syntax and conditional logic. -
State Mutation vs. Immutability: I correctly identified that scores and active team must be mutable (instance variables) while team names are effectively constant (set once in constructor, never modified). This shows nuanced understanding of when mutability is appropriate.
-
Test Case Validation: The provided test cases pass perfectly, which means I successfully handled:
- Multiple consecutive plays by the same team
- Team switching on failed plays
- Multiple independent scoreboard objects
- Calling
getScore()multiple times without state changes
Potential Improvements (Advanced Thinking)
While my solution is correct and complete, here are considerations that might arise in code review discussions:
-
Immutability: The
activeTeamcould theoretically be accessed and modified externally if it were public. Adding aprivateaccess modifier (which I did) prevents this - good defensive programming. -
Validation: The constructor could validate that team names are non-null and non-empty. The problem doesn’t require this, but it would be good practice in production code.
-
Alternative Implementations: Instead of integer 1/2, I could have used an enum:
enum Team { TEAM1, TEAM2 } private Team activeTeam;This would be more type-safe and self-documenting, though the added complexity might not be justified here.
Overall Assessment
This solution demonstrates that I:
- Understand OOP fundamentals: proper use of constructors, instance variables, and methods
- Can translate requirements to code: each requirement was directly and clearly implemented
- Write readable, maintainable code: appropriate variable names, logical structure, and helpful comments
- Can handle state management: correctly tracking mutable state across multiple method calls
- Test my thinking: all test cases pass, proving logical correctness
This is a solid, textbook-quality FRQ solution that correctly interprets and implements the specified requirements without unnecessary complexity.