Unit 2 - Selection and Iteration¶
Updated: 10/28/2026 AP Exam Weighting: 25–35%
AP Computer Science A — Assignment Rubric
Assignment Header
All submitted documents and .java files must include the header below. This mirrors the block comment required in Main.java and follows the standard used by university CS departments.
Name: [Your Full Name]
Partner: [Partner's Full Name, or "None"]
Course: AP Computer Science A
Instructor: [Instructor Name]
Assignment: [Assignment Number — Assignment Title]
Due Date: [Month Day, Year]
Example:
Name: Jordan Smith
Partner: Alex Rivera
Course: AP Computer Science A
Instructor: [Instructor Name]
Assignment: 2.03.1 — Guess Checker Pt 1
Due Date: October 19, 2026
This header must appear at the top of your
Main.javablock comment AND on your Test Cases document. Submissions missing the header will be penalized one point.
Submission Requirements
All assignments require the following unless otherwise stated:
All
.javasource file(s)Test Cases document showing inputs, expected output, actual output, and Pass/Fail result
Projects will have their own dedicated rubric and submission instructions.
5-Point Assignment Rubric
Points |
Grade |
Compilation & Output |
Documentation & Style |
Submission |
|---|---|---|---|---|
5 |
Full Credit |
Program compiles and runs without errors or warnings. Output matches expected results for all test cases. |
Block comment header fully completed. Meaningful variable names, camelCase convention, proper indentation. Inline and multi-line comments present throughout. |
All required |
4 |
Near Full Credit |
Program compiles and runs. Output is correct for most test cases with one minor error or omission. |
Block comment header complete. Comments mostly present. Minor style or formatting inconsistency. |
All required files submitted. Assignment header present. |
3 |
Partial Credit |
Program compiles but produces incorrect output for some test cases, or compiles with warnings. |
Limited comments. Block comment header partially completed. Variable names or formatting inconsistent. |
Most required files submitted. Test cases incomplete or partially documented. |
2 |
Minimal Credit |
Program has syntax or logic errors that cause significant incorrect output, or fails to fully compile. |
Little to no commenting. Block comment header missing or blank. Poor variable naming or formatting. |
A required |
1 |
Attempted |
Code submitted shows a clear attempt but does not compile or run. |
Minimal or no documentation present. |
At least one file submitted, but submission is largely incomplete. |
0 |
No Credit |
Nothing submitted, file is empty, or code is unrelated to the assignment. |
N/A |
N/A |
Academic Integrity Policy
Any submission that violates academic integrity will receive no credit and will be referred for disciplinary action in accordance with school policy.
The following are considered academic integrity violations in this course:
Submitting another student’s code as your own
Copying code from the internet without citation and modification
Allowing another student to copy your code
Sharing your source files with another student outside of an approved partner assignment
AI & External Source Use
AI tools may be used for idea generation, debugging assistance, and understanding small parts of code — not to generate complete solutions.
If you use any external source (websites, LLM/AI tools, friends), cite it in your code comments — indicate where you got help and whether any code sections came from that source.
Submitting AI-generated code as your own work — whether a whole solution or an unattributed snippet — is an academic integrity violation. Violations receive no credit and are referred for disciplinary action in accordance with school policy.
Approved Collaboration: Discussing concepts, approaches, and debugging strategies with classmates is encouraged. Writing or sharing actual code is not permitted unless the assignment is explicitly designated as a partner assignment.
Partner Assignments: Both partners must be listed in the assignment header. Both partners are equally responsible for the integrity of the submitted work.
Late Work Policy
Most work is done in class, so the late work policy is not applicable. For any assigned homework assignment, you have 1 week after the given due date to turn it in. Otherwise, you will receive a maximum of 50% for late work. With regards to Projects, you will have daily progress checks that will count for your overall grade. Failure to complete a daily progress check will lower your grade.
Grading Notes
A program that does not compile cannot earn higher than a 2.
A missing test cases document cannot earn higher than a 4.
A missing block comment header deducts 1 point from the earned score.
A missing assignment header deducts 1 point from the earned score.
Style and documentation are evaluated holistically — occasional lapses do not automatically lower a grade, but a consistent pattern does.
#############################################################################
📋 Unit 2 Standards Alignment
Standard |
Description |
|---|---|
ICT 1.0 |
Academics — apply academic standards across content areas |
ICT 2.0 |
Communications — communicate clearly in written and electronic formats |
ICT 4.1 |
Use electronic reference materials to gather information |
ICT 5.4 |
Interpret information and draw conclusions to make informed decisions |
ICT 5.8 |
Create and use algorithms to solve problems |
ICT 5.9 |
Deconstruct large problems into smaller components |
ICT 7.5 |
Apply high-quality techniques to product design and development |
ICT 10.1 |
Interpret and explain ICT-specific terminology |
C4.4 |
Identify and apply data types and encoding |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures, procedures, and variables |
C4.11 |
Document development work using comments |
C5.4 |
Design a solution to a problem |
C5.5 |
Implement a solution |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 2 |
Communicate clearly, effectively, and with reason |
CRP 4 |
Apply technology to enhance productivity |
CRP 5 |
Utilize critical thinking to make sense of problems |
CRP 7 |
Act as a responsible and contributing citizen and employee |
You’ve Already Started Unit 2
Several Unit 2 ideas showed up in Unit 1 before they had a name. This unit gives them names, rules, and exam-level precision.
Unit 2 Topic |
Where You Already Saw It |
What’s New in Unit 2 |
|---|---|---|
|
1.02.1 Allowance — |
Else-if chains, nesting, ordering traps, short-circuiting |
|
1.07a String Pool, 1.15 aliasing, 1.17 wrapper pitfalls |
|
Ternary |
1.14.4 Bike Shop — |
How it works and when to use it |
|
1.07.2 Magic 8-Ball “keep asking” loop |
Writing loops from scratch, tracing, counting iterations |
|
Cake |
Writing |
Find max, average |
1.17.1 — |
Divisibility, digit extraction, frequency counts |
College Board Note: Unit 2 is the heaviest unit on the AP exam (25–35%), and FRQ 1 (Methods and Control Structures) is built almost entirely from it. On FRQ 1 you will be given a class and asked to write the body of a method that uses conditionals and loops. Every section in this unit includes a Write the Method exercise in that style.
Oracle Exam Note: Sections marked — Oracle Foundations 1Z0-811 (
switch, the ternary operator, operator precedence,do-while,break/continue, and the Date/Time API) are tested on Oracle but are not part of the AP Java subset. You are allowed to use them on the AP exam, but no AP question will require them.
2.01 Algorithms with Selection and Repetition¶
📌 Standards — 2.01
Standard |
Description |
|---|---|
ICT 5.8 |
Create and use algorithms and solve problems |
ICT 5.9 |
Deconstruct large problems into components |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
C5.4 |
Design a solution to a problem |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Identify sequencing, selection, and repetition in an algorithm.
Represent an algorithm with a flowchart and with pseudocode.
Trace an algorithm by hand to predict its result.
Three Building Blocks
An algorithm is a finite, step-by-step process for solving a problem. Every algorithm, from a vending machine to a search engine, is built from only three structures:
Structure |
Meaning |
Java Tools |
|---|---|---|
Sequencing |
Steps run one after another, in order |
Every program you wrote in Unit 1 |
Selection |
Choose a path based on a condition |
|
Repetition (iteration) |
Repeat steps while a condition holds |
|
Every selection and every repetition is controlled by a Boolean expression, a question with a true or false answer. That’s why 2.02 starts there.
Flowchart Symbols
You’ll need these for the Choose Your Own Adventure project.
Shape |
Name |
Use |
|---|---|---|
Oval |
Terminator |
Start / End |
Parallelogram |
Input / Output |
|
Rectangle |
Process |
Calculations, assignments |
Diamond |
Decision |
A Boolean question — exactly two exits, labeled true and false |
Arrow |
Flow line |
Shows which step comes next |
A loop in a flowchart is simply an arrow that travels back up to an earlier decision diamond.
From English to Pseudocode to Java
English: “A ride lets you on if you’re at least 48 inches tall. Otherwise it tells you to try the kiddie coaster.”
INPUT height
IF height >= 48
DISPLAY "Enjoy the ride!"
ELSE
DISPLAY "Try the kiddie coaster."
int height = input.nextInt();
if (height >= 48)
{
System.out.println("Enjoy the ride!");
}
else
{
System.out.println("Try the kiddie coaster.");
}
College Board Note: AP multiple-choice questions frequently describe an algorithm in English and ask which code segment correctly implements it. Read the English slowly. Words like at least (
>=), more than (>), no more than (<=), and unless (negation) decide the answer.
Exercise 2.01.A — Name the Structure¶
Here is a “school morning” algorithm. Label each step as sequencing, selection, or repetition by answering the three questions below.
Wake up.
If it’s raining, grab an umbrella.
Hit snooze until you’ve snoozed 3 times.
Eat breakfast.
If the bus has left, ask for a ride; otherwise, walk to the stop.
Exercise 2.01.B — English to Pseudocode¶
“A movie theater charges \(8 for children under 13, \)14 for adults, and $9 for seniors 65 and older.”
Sketch your own pseudocode on paper first, then check it against the choices below.
Check for Understanding¶
#############################################################################
2.02 Boolean Expressions¶
📌 Standards — 2.02
Standard |
Description |
|---|---|
ICT 5.4 |
Interpret information and draw conclusions to make informed decisions |
ICT 5.8 |
Create and use algorithms and solve problems |
C4.4 |
Identify and apply data types and encoding |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Use relational operators to compute the value of a Boolean expression.
Store the result of a comparison in a
booleanvariable.Explain the difference between
=and==.I will be able to write a program that utilizes a Boolean expression.
George Boole formulated the basic rules of Boolean algebra back in 1847. A Boolean expression evaluates to exactly one of two values: true or false.
Relational Operators (all on the AP exam)
Relational Operator |
Description |
Boolean Value |
|---|---|---|
|
a less than b |
|
|
a less than or equal to b |
|
|
a greater than b |
|
|
a greater than or equal to b |
|
|
a equals b* |
|
|
a does not equal b |
|
* For primitives (int, double, char, boolean) == compares values. For objects it compares references (addresses). You already know to use .equals() for Strings and wrapper objects; 2.06 extends that to objects of your own classes.
Boolean Variables Store Answers
A comparison produces a value, so you can store it, just as you did in 1.02.1 Allowance:
int temperature = 95;
boolean isHot = temperature > 90; // true
boolean isFreezing = temperature <= 32; // false
System.out.println(isHot); // true
Naming tip: start boolean names with is, has, or can (isHot, hasKey, canVote) so conditions read like English: if (hasKey).
Rules for What Can Be Compared
int a = 7;
double b = 7.0;
char c = 'A';
System.out.println(a == b); // true — int is widened to double, then compared
System.out.println(c < 'B'); // true — chars compare by Unicode value ('A' = 65, 'B' = 66)
System.out.println(c + 1); // 66 — char arithmetic produces an int
// System.out.println("cat" < "dog"); // COMPILE ERROR — < is not defined for Strings
// System.out.println(true > false); // COMPILE ERROR — booleans only use == and !=
To order Strings, use compareTo (from 1.15): "cat".compareTo("dog") returns a negative number because “cat” comes first alphabetically. You’ll use this in 2.10.
College Board Note: Comparing
doublevalues with==is risky because of rounding.0.1 + 0.2 == 0.3isfalse! When exactness matters, check whether the values are close enough:Math.abs(x - y) < 0.0001.
= vs. ==
Operator |
Name |
Meaning |
|---|---|---|
|
Assignment |
Store the right side into the variable on the left |
|
Equality |
Ask whether two values are the same |
int score = 10;
// if (score = 10) { } // COMPILE ERROR — (score = 10) is an int, not a boolean
boolean done = false;
if (done = true) // COMPILES — assigns true to done, so the condition is ALWAYS true
{
System.out.println("This always prints!");
}
Oracle Exam Note: The
if (done = true)trap is a classic. With anint, the mistake won’t compile. With aboolean, it compiles and silently changes the variable. Best practice: writeif (done)andif (!done)instead of comparing a boolean totrueorfalse.
Logical Operators — A Preview
You used && in 1.02.1. Here are all three; 2.05 covers them in depth.
Operator |
Name |
|
|---|---|---|
|
AND |
both sides are true |
|
OR |
at least one side is true |
|
NOT |
the expression it’s applied to is false |
Exercise 2.02.A — Evaluate It¶
Given int x = 8; int y = 3; double z = 8.0; char ch = 'm';, evaluate each expression. Each println prints the value of one Boolean expression.
Exercise 2.02.B — Write the Method¶
The Ride class from your Unit 1 project needs a method that answers a yes/no question: isTallEnough. Write your own version first (no if statement needed; return the comparison itself), then choose every body below that works.
public class Ride
{
private String name;
private int minHeight; // in inches
public Ride(String name, int minHeight)
{
this.name = name;
this.minHeight = minHeight;
}
/** Returns true if a guest of the given height (inches) may ride. */
public boolean isTallEnough(int guestHeight)
{
/* your code here */
}
}
Activity 2.02.1 — Truth Table¶
Fill in the truth table for a && (b || c):
Activity 2.02.2 — Field Trip Eligibility Check¶
Overview
The CTE department is planning a field trip, and the office needs a quick report on each student. Your program reads a student’s information and prints a true/false report, one Boolean expression per line. You won’t make any decisions with if yet (that’s 2.03). The goal is to write correct Boolean expressions and store them in well-named boolean variables.
By the end of this activity you will be able to:
Write Boolean expressions with all six relational operators
Store the result of a comparison in a
booleanvariableCompare
charvalues and test whether twodoublevalues are “close enough”Explain how integer division can make a Boolean expression wrong
Report Rules
Report Line |
|
|---|---|
Upperclassman |
grade level is 11 or higher |
GPA requirement |
GPA is at least |
Attendance |
absences are |
Permission slip |
the answer is |
Perfect GPA |
GPA is 4.0, tested with |
Bus A |
the student’s name starts with a letter from |
Service average |
service hours ÷ events attended is 3.5 or more |
To Do
Add the required block comment header
Use
Scannerto read: name (full line), grade level, GPA, absences, total service hours, service events attended, and permission slip (yes/no)Declare
finalconstantsMIN_GPAandMAX_ABSENCESCreate seven
booleanvariables, one for each report line. Name them withis,has, ormeets(for example,meetsGpa).Use at least four different relational operators across your expressions
For Bus A, compare the first character of the name (
name.charAt(0)) with'M'. Assume names start with a capital letter.For Service average, first write it without a cast and test with 14 hours and 4 events. Record the result in a comment, then fix it with a
(double)cast and explain in the comment why the first version was wrong.Print the report with
printfso thetrue/falsevalues line up (%bprints a boolean)Do not use
if,&&, or||in this activity
Sample Output (two separate runs)
Student name: Maya Lopez
Grade level (9-12): 11
GPA: 3.4
Absences this semester: 2
Total service hours: 14
Service events attended: 4
Permission slip returned? (yes/no): YES
=== FIELD TRIP CHECK: MAYA LOPEZ ===
Upperclassman (11-12): true
GPA at least 2.0: true
Absences 5 or fewer: true
Permission slip returned: true
Perfect 4.0 GPA: false
Rides Bus A (names A-M): true
Avg 3.5+ hours per event: true
Student name: Theo
Grade level (9-12): 9
GPA: 4.0
Absences this semester: 7
Total service hours: 9
Service events attended: 4
Permission slip returned? (yes/no): no
=== FIELD TRIP CHECK: THEO ===
Upperclassman (11-12): false
GPA at least 2.0: true
Absences 5 or fewer: false
Permission slip returned: false
Perfect 4.0 GPA: true
Rides Bus A (names A-M): false
Avg 3.5+ hours per event: false
Think About It (comment at the bottom)
Without the cast, 14 ÷ 4 gave the wrong answer for Service average. What value did Java actually compare to 3.5?
Why can’t you write
name < "M"to decide the bus?A student is eligible only when all of the first four lines are true. What operator will let you combine them (coming in 2.05)?
Submission
FieldTrip.javawith block comment headerTest Cases document: at least three students, including one exactly at each limit (grade 11, GPA 2.0, 5 absences) and one whose name starts with
MorN
Grading: AP CSA 5-point Assignment Rubric.
Check Your Understanding 2.02¶
Check for Understanding¶
#############################################################################
2.03 if Statements¶
📌 Standards — 2.03
Standard |
Description |
|---|---|
ICT 5.8 |
Create and use algorithms and solve problems |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Write one-way (
if) and two-way (if/else) selection statements.Predict which statements run for a given input.
Identify the empty-statement and missing-brace traps.
I will be able to write a program that uses if/else statements.
One-Way Selection: if
The body runs only when the condition is true. Either way, the program continues after the closing brace.
if (condition)
{
// runs only when condition is true
}
// always runs
int gold = 120;
if (gold >= 100)
{
System.out.println("You can buy the sword.");
}
System.out.println("You leave the shop.");
Output:
You can buy the sword.
You leave the shop.
Two-Way Selection: if/else
Exactly one of the two blocks runs, never both and never neither.
if (gold >= 100)
{
System.out.println("You can buy the sword.");
}
else
{
System.out.println("Not enough gold.");
}
Braces Matter
Without braces, only the first statement after the if belongs to it. Indentation means nothing to Java.
int hp = 50;
if (hp <= 0)
System.out.println("Game over.");
System.out.println("Respawning..."); // NOT part of the if — always prints!
Output:
Respawning...
Best practice in this course: always use braces, even for one statement.
The Empty-Statement Trap
int lives = 0;
if (lives > 0); // ← this semicolon IS the entire if body (an empty statement)
{
System.out.println("Keep playing!"); // a plain block — ALWAYS runs
}
Oracle Exam Note: Oracle loves both traps above: misleading indentation and a stray semicolon after
if (...). Both compile without errors, so you have to catch them by reading carefully.
Variables Declared Inside a Block Stay Inside
A variable declared inside { } only exists inside that block (its scope).
if (gold >= 100)
{
String item = "sword";
}
// System.out.println(item); // COMPILE ERROR — item does not exist here
Fix: declare the variable before the if, then assign it inside.
Oracle Exam Note: Expect “Does this code compile?” questions that hinge on a variable used outside the block where it was declared.
Exercise 2.03.A — Predict the Output¶
For each segment, predict the output before running it. Watch the braces (and the lack of them).
Exercise 2.03.B — Write the Method¶
The bakery from Assignment 1.12.1 now gives 10% off orders over $50.00. Write your own finalTotal first, then choose every body below that works.
public class BakeryOrder
{
private String customer;
private double subtotal;
public BakeryOrder(String customer, double subtotal)
{
this.customer = customer;
this.subtotal = subtotal;
}
/** Returns the subtotal, reduced by 10% when the subtotal is more than 50.00. */
public double finalTotal()
{
/* your code here */
}
}
Activity 2.03.1 — Guess Checker Pt 1¶
Overview
You’re building a code-breaking game. The computer picks a secret 4-digit code with no repeated digits, and the player tries to crack it. You will grow this program across three activities: hits now (2.03), near hits in 2.04, and compound conditions plus multiple guesses in 2.05. You submit it once, at the end of Pt 3.
By the end of this activity you will be able to:
Use
ifstatements to compare matching positions of two codesUse a counter variable with
++to tally resultsRead code that someone else wrote and add to it without breaking it
What’s Provided (read it; don’t change it)
Method |
What It Does |
|---|---|
|
Creates a random 4-digit code from 1000–9999 with no duplicate digits |
|
Prompts until the player types a valid guess, then returns it as a |
|
Returns |
These helper methods contain a loop and an array, which you’ll learn in 2.07 and Unit 4. You only need to call them, the same way you called
Mathmethods in Unit 1 without seeing inside them.
To Do
Add the required block comment header
Declare an
int hitscounter and set it to0Write four
ifstatements that each compare one guess digit to the secret digit in the same position (g1withr1,g2withr2, …)Each time a digit matches, add one to
hitsAfter the four
ifs, printNumber of hits:followed by the countLeave the line that prints the secret code turned on. It lets you and your teacher test the program.
Starter Code — GuessChecker.java
import java.util.Scanner;
public class GuessChecker
{
// PROVIDED: one Scanner for the whole program
private static Scanner sc = new Scanner(System.in);
public static void main(String[] args)
{
// Generate the secret code
String targetStr = makeCode();
System.out.println(targetStr); // LEAVE THIS LINE ON for testing and grading
// Break the secret code into four digits
int r1 = Integer.parseInt(targetStr.substring(0, 1));
int r2 = Integer.parseInt(targetStr.substring(1, 2));
int r3 = Integer.parseInt(targetStr.substring(2, 3));
int r4 = Integer.parseInt(targetStr.substring(3, 4));
// Get the player's guess
String guess = getGuess();
// Break the guess into four digits
int g1 = Integer.parseInt(guess.substring(0, 1));
int g2 = Integer.parseInt(guess.substring(1, 2));
int g3 = Integer.parseInt(guess.substring(2, 3));
int g4 = Integer.parseInt(guess.substring(3, 4));
/* your code here */
}
// ===================== PROVIDED — DO NOT MODIFY =====================
// Returns true if num repeats any digit
public static boolean hasDupes(int num)
{
boolean[] digs = new boolean[10];
while (num > 0)
{
if (digs[num % 10])
{
return true;
}
digs[num % 10] = true;
num /= 10;
}
return false;
}
// Creates a random 4-digit code (1000-9999) with no duplicate digits
public static String makeCode()
{
int target = (int) (Math.random() * 9000 + 1000);
while (hasDupes(target))
{
target = (int) (Math.random() * 9000 + 1000);
}
return target + "";
}
// Prompts until the player enters a valid 4-digit guess with no duplicates
public static String getGuess()
{
boolean validGuess = false;
int userGuess = 0;
while (!validGuess)
{
System.out.print("Guess a 4-digit number from 1000 to 9999 with no duplicate digits: ");
userGuess = sc.nextInt();
if (!(hasDupes(userGuess) || userGuess < 1000 || userGuess > 9999))
{
validGuess = true;
}
}
return userGuess + "";
}
}
Sample Output (two separate runs)
3768
Guess a 4-digit number from 1000 to 9999 with no duplicate digits: 7658
Number of hits: 1
3768
Guess a 4-digit number from 1000 to 9999 with no duplicate digits: 3658
Number of hits: 2
Your secret code will be different every run. Use the printed code to plan a guess that should produce 0, 1, 2, and 4 hits, and check each one.
Think About It (answer in a comment at the bottom of your program)
Why does
makeCode()multiply by9000and then add1000? (Hint: 1.11Math.random().)getGuess()returns aString, not anint. Why is aStringconvenient for pulling out one digit at a time?
Submission: None yet. Keep this file; you’ll build on it in 2.04.
Check for Understanding¶
#############################################################################
2.04 Nested if Statements¶
📌 Standards — 2.04
Standard |
Description |
|---|---|
ICT 5.8 |
Create and use algorithms and solve problems |
ICT 5.9 |
Deconstruct large problems into components |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Write multiway selection with
if / else if / else.Order conditions so every branch is reachable.
Trace nested
ifstatements, including the “dangling else.”
Multiway Selection: else if
Java checks the conditions from top to bottom and runs the first branch whose condition is true. Every other branch is skipped, even if its condition is also true.
if (score >= 90)
{
grade = "A";
}
else if (score >= 80)
{
grade = "B";
}
else if (score >= 70)
{
grade = "C";
}
else
{
grade = "F";
}
When score is 95, score >= 80 is also true, but it is never checked. The chain stopped at "A".
Order Matters
// BUGGY — what grade does 95 get?
if (score >= 70)
{
grade = "C";
}
else if (score >= 80)
{
grade = "B"; // unreachable for any score >= 80!
}
else if (score >= 90)
{
grade = "A"; // unreachable!
}
A 95 gets a "C". With “at least” (>=) ranges, test the largest threshold first. With “less than” (<) ranges, test the smallest first.
else if vs. Separate ifs
// Separate ifs: EVERY condition is checked
int points = 95;
if (points >= 90) { System.out.print("A "); }
if (points >= 80) { System.out.print("B "); }
if (points >= 70) { System.out.print("C "); }
// prints: A B C
Use separate ifs when several things can be true at once (bonus badges). Use else if when exactly one outcome should happen (a letter grade).
Nested if: A Decision Inside a Decision
if (hasTicket)
{
if (age >= 18)
{
System.out.println("Welcome to the late show.");
}
else
{
System.out.println("Matinee only.");
}
}
else
{
System.out.println("Please buy a ticket.");
}
The inner question (age) is only asked when the outer answer (ticket) is true.
The Dangling else
An else always pairs with the nearest unmatched if, no matter how it’s indented.
int x = 5;
int y = 10;
if (x > 10)
if (y > 5)
System.out.println("A");
else // indented under the outer if, but belongs to the INNER if
System.out.println("B");
Nothing prints. x > 10 is false, so the entire inner if/else is skipped. Braces remove all doubt.
Oracle Exam Note: “Dangling else” questions appear on both exams. Cover the indentation with your finger and pair each
elsewith the closestifabove it that doesn’t already have one.
Exercise 2.04.A — Trace the Chain¶
Trace the else if chain for three different temperatures. Remember: Java runs the first branch whose condition is true.
Exercise 2.04.B — Write the Method¶
Write ticketPrice for the Guest class from your Unit 1 Theme Park project.
Guest |
Price |
|---|---|
Age under 3 |
0 (free) |
Age 3–12 |
45 |
Age 13–64 |
80 |
Age 65+ |
50 |
Members get $10 off any non-free ticket. Use a nested if for the member discount.
public class Guest
{
private String name;
private int age;
private boolean isMember;
public Guest(String name, int age, boolean isMember)
{
this.name = name;
this.age = age;
this.isMember = isMember;
}
/** Returns this guest's ticket price in whole dollars. */
public int ticketPrice()
{
/* your code here */
}
}
Activity 2.04.1 — Guess Checker Pt 2¶
Overview
Add near hits to your Guess Checker: digits the player guessed correctly but placed in the wrong position. Because the secret code never repeats a digit, each guess digit is either a hit, a near hit, or neither, and you can test those possibilities with an if / else if chain.
By the end of this activity you will be able to:
Write an
if / else ifchain where the order of the checks mattersMaintain two separate counters in the same program
Document changes to existing code with dated comments
To Do
Declare an
int nearHitscounter set to0Replace each of your four hit checks with an
if / else ifchain for that digit:first, check for a hit (same position)
then use
else ifto check the digit against each of the other three secret positions, adding one tonearHitson a match
Do not use
&&or||yet. That’s Pt 3.Print both counters at the end
Add a comment with today’s date wherever you changed or added code
Here is the pattern for the first digit. Write the other three yourself.
if (g1 == r1)
{
hits++;
}
else if (g1 == r2)
{
nearHits++;
}
else if (g1 == r3)
{
nearHits++;
}
else if (g1 == r4)
{
nearHits++;
}
Sample Output
9782
Guess a 4-digit number from 1000 to 9999 with no duplicate digits: 9728
Number of hits: 2
Number of near hits: 2
9782
Guess a 4-digit number from 1000 to 9999 with no duplicate digits: 7928
Number of hits: 0
Number of near hits: 4
Think About It (comment at the bottom)
Why must the hit check come first in each chain?
Why is an
else ifchain safe here only because the secret code has no duplicate digits?
Submission: None. Keep building; you’ll submit after Pt 3.
Activity 2.04.2 — Activity Director¶
Overview
You’re the Activities Director at a resort. Every morning the program checks the temperature and tells guests what to do. Some temperatures also trigger a second message, which tests whether you know the difference between an else if chain (exactly one result) and a separate if (an extra, independent check).
By the end of this activity you will be able to:
Write an
if / else if / elsechain with ranges in the correct orderDecide when a check belongs in the chain and when it needs its own
ifGenerate a random integer in a range (1.11
Math.random())Test a program at its boundary values
Activity Table
Temperature |
Message |
|---|---|
80 and above |
|
60–79 |
|
40–59 |
|
39 and below |
|
And separately: if the temperature is above 95 or below 20, also print Visit our shops!
Temperatures are whole numbers, so the ranges are written with whole numbers. There’s no gap between 59 and 60 to fall through.
To Do
Add the required block comment header
Generate a random
inttemperature from 10 to 101, inclusive. Add a comment showing how you chose the numbers in your formula.Print
Temperature:followed by the valueWrite a static method
suggestActivity(int temp)that returns the activityStringusing anif / else if / elsechain. Call it frommainand print the result.After printing the activity, print
Visit our shops!when the temperature is above 95 or below 20. You haven’t learned||yet (2.05), so use anifwith anelse if. This check must not be part of the activity chain.Test every boundary listed in Test Cases below
Starter Code — ActivityDirector.java
public class ActivityDirector
{
public static void main(String[] args)
{
// TODO: random temperature from 10 to 101 (inclusive)
int temp = 0;
System.out.println("Temperature: " + temp);
// TODO: print the result of suggestActivity(temp)
// TODO: shop message (above 95 or below 20)
}
/** Returns the suggested activity for the given temperature. */
public static String suggestActivity(int temp)
{
/* your code here */
}
}
Sample Output (three separate runs)
Temperature: 72
Play tennis!
Temperature: 100
Go swimming!
Visit our shops!
Temperature: 20
Go skiing!
Test Cases
A random temperature makes testing hard because you can’t choose the value. For testing, temporarily replace the random line with a fixed value (for example, int temp = 95;), run it, record the result, and repeat. Put the random line back before you submit. Test every boundary, the values right at the edge of each range:
// example below
/*
TEST CASE 1:
Temperature: 100
Go swimming!
Visit our shops!
TEST CASE 2:
Temperature: 20
Go skiing!
*/
Temperature |
Expected Output |
|---|---|
101 |
Go swimming! · Visit our shops! |
96 |
Go swimming! · Visit our shops! |
95 |
Go swimming! |
80 |
Go swimming! |
79 |
Play tennis! |
60 |
Play tennis! |
59 |
Play golf! |
40 |
Play golf! |
39 |
Go skiing! |
20 |
Go skiing! |
19 |
Go skiing! · Visit our shops! |
10 |
Go skiing! · Visit our shops! |
Think About It (comment at the bottom)
Why can’t
Visit our shops!be anotherelse ifat the bottom of the activity chain?Your chain probably tests
temp >= 80first. What would go wrong iftemp >= 40came first?Preview of 2.05: rewrite your shop check as one
ifusing||.
Submission
ActivityDirector.javawith block comment header (random line restored)Test Cases document covering all twelve boundary values
Grading: AP CSA 5-point Assignment Rubric.
Check for Understanding¶
#############################################################################
2.04a Switch Statements and the Ternary Operator — Oracle Foundations 1Z0-811¶
📌 Standards — 2.04a
Standard |
Description |
|---|---|
ICT 5.8 |
Create and use algorithms and solve problems |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Oracle Exam Note:
switchand the ternary operator are tested on Oracle 1Z0-811. They are not in the AP Java subset. You may use them on AP free-response questions, but no AP question requires them.
Write a
switchstatement withcase,break, anddefault.Predict output when
breakis missing (fall-through).Identify which types a
switchcan and cannot use.Use the ternary operator for a simple conditional assignment.
The switch Statement
A switch compares one value against a list of constant cases. It’s a cleaner alternative to a long else if chain that keeps testing the same variable with ==.
int day = 3;
switch (day)
{
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
default:
System.out.println("Other day");
}
How It Runs
Java evaluates the expression in
switch (...)once.It jumps to the matching
case(or todefaultif nothing matches).It runs statements downward until it hits a
breakor the end of theswitch.
Step 3 is what makes fall-through happen.
Fall-Through: Missing break
int level = 2;
switch (level)
{
case 1:
System.out.println("Easy");
case 2:
System.out.println("Medium");
case 3:
System.out.println("Hard");
break;
default:
System.out.println("Unknown");
}
Output:
Medium
Hard
Java jumped to case 2, printed “Medium,” then kept going into case 3 because there was no break.
Fall-through is sometimes useful on purpose, to group cases:
int month = 4;
switch (month)
{
case 4:
case 6:
case 9:
case 11:
System.out.println("30 days");
break;
case 2:
System.out.println("28 or 29 days");
break;
default:
System.out.println("31 days");
}
switch Rules Oracle Tests
Rule |
Example |
|---|---|
Allowed types: |
|
Not allowed: |
|
Case labels must be constants (literals or |
|
Case labels must be unique |
two |
Case label type must match the switch type |
|
|
If |
|
|
Oracle Exam Note: Newer versions of Java (14+) add an arrow form,
case 1 -> ..., with no fall-through. Both exams use the classic form shown here.
The Ternary Operator ? :
The ternary operator is a one-line if/else that produces a value.
// condition ? valueIfTrue : valueIfFalse
int age = 17;
String status = (age >= 18) ? "adult" : "minor"; // "minor"
int a = 10, b = 20;
int max = (a > b) ? a : b; // 20
Remember this line from 1.14.4 Bike Shop?
String gearWord = (gears == 1) ? " gear" : " gears";
Now you can read it: if gears is 1, use " gear"; otherwise use " gears".
Ternary Rules
It is an expression (it produces a value), so it must be used: assigned, printed, or returned.
(x > 0) ? "pos" : "neg";on a line by itself is a compile error.Both result values must fit the target type:
int n = (flag) ? 5 : "five";does not compile.Ternaries can be nested, but readability drops fast. Prefer
if/elsefor anything beyond a simple choice.
int n = -4;
String sign = (n > 0) ? "positive" : (n < 0) ? "negative" : "zero"; // "negative"
Exercise 2.04a.A — Trace the Switch¶
Predict what each segment prints. Watch for missing break statements.
Exercise 2.04a.B — Convert It¶
Part 1. Rewrite this chain using a switch on choice:
if (choice == 1)
{
System.out.println("Attack");
}
else if (choice == 2)
{
System.out.println("Defend");
}
else if (choice == 3)
{
System.out.println("Run");
}
else
{
System.out.println("Invalid");
}
Part 2. Rewrite this if/else as a single ternary assignment:
String label;
if (hp > 0)
{
label = "alive";
}
else
{
label = "defeated";
}
Activity 2.04a.1 — Text-Based Calculator with Mode Selection¶
Overview
Build a calculator that asks the user which mode to run and routes them there with a switch. Inside each mode, use ternary operators for quick decisions. This activity pulls in Scanner, Math methods, and printf from Unit 1.
By the end of this activity you will be able to:
Use a
switchon aStringto route program flowNest a
switchon acharinside anotherswitchUse the ternary operator to choose between two values
Guard against invalid input with
default
To Do
Add the required block comment header
Ask the user to choose a mode:
basic,scientific, orstats. Convert the input with.trim().toLowerCase()so" Basic "still works.Use a
switchon the modeString:basic— read twodoublevalues and an operator (+,-,*,/). Use a nestedswitchon the operatorchar(input.next().charAt(0)). For division, use a ternary to printundefinedwhen the divisor is0. Use a second ternary to report whether the result ispositiveornegative(treat0as positive).scientific— read onedouble. Print its square (Math.pow), its absolute value (Math.abs), and its square root. Use a ternary so a negative number printsnot a real numberinstead ofNaN.stats— read threeintvalues. Find the largest using two ternaries (noMath.max). Print the average to two decimal places withprintf.default— printUnknown mode:followed by what the user typed.
Every
caseends withbreak(unless you can explain an intentional fall-through in a comment)Test every mode, plus at least one invalid mode, in your Test Cases document
Sample Output (four separate runs)
Choose a mode (basic, scientific, stats): basic
Enter first number: 12
Enter second number: 0
Enter operator (+ - * /): /
Result: undefined
Choose a mode (basic, scientific, stats): Basic
Enter first number: 7.5
Enter second number: 10
Enter operator (+ - * /): -
Result: -2.5 (negative)
Choose a mode (basic, scientific, stats): scientific
Enter a number: -16
Square: 256.0
Absolute value: 16.0
Square root: not a real number
Choose a mode (basic, scientific, stats): stats
Enter three whole numbers: 84 97 90
Largest: 97
Average: 90.33
Hints
input.next().charAt(0)reads the next word and keeps its first character.A ternary must produce one type. Use
String.format("%.3f", Math.sqrt(x))so both choices areStrings.Find the max of three in two steps:
int max = (a > b) ? a : b;then comparecwithmax.
Submission
Calculator.javawith block comment headerTest Cases document: at least five runs (each mode, one invalid mode, and divide by zero)
Grading: AP CSA 5-point Assignment Rubric.
Check for Understanding¶
#############################################################################
2.05 Compound Boolean Expressions¶
📌 Standards — 2.05
Standard |
Description |
|---|---|
ICT 5.4 |
Interpret information and draw conclusions to make informed decisions |
ICT 5.8 |
Create and use algorithms and solve problems |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Combine conditions with
&&,||, and!.Explain and use short-circuit evaluation to prevent errors.
Write range checks correctly.
Logical Operators
|
|
|
|
|
|---|---|---|---|---|
T |
T |
T |
T |
F |
T |
F |
F |
T |
F |
F |
T |
F |
T |
T |
F |
F |
F |
F |
T |
&&is true only when both sides are true.||is true when at least one side is true. (It’s inclusive: both true counts.)!flips the value.
// Range: between 18 and 65, inclusive
if (age >= 18 && age <= 65)
{
System.out.println("Working age");
}
// Out of range: invalid score
if (score < 0 || score > 100)
{
System.out.println("Invalid score");
}
// Negation
if (!hasKey)
{
System.out.println("The door is locked.");
}
Compound vs. Nested
These two segments are equivalent:
if (hasTicket)
{
if (age >= 18)
{
System.out.println("Welcome to the late show.");
}
}
if (hasTicket && age >= 18)
{
System.out.println("Welcome to the late show.");
}
Use && when both conditions lead to the same single action. Use nesting when the outer condition has its own else or other work to do.
Short-Circuit Evaluation
Java evaluates left to right and stops as soon as it knows the answer:
false && anythingisfalse, so the right side is never evaluated.true || anythingistrue, so the right side is never evaluated.
This isn’t just a speed trick. It’s how you write guards that prevent crashes:
int count = 0;
int total = 50;
// SAFE — when count is 0, the left side is false and the division never happens
if (count != 0 && total / count > 10)
{
System.out.println("High average");
}
// CRASH — the division runs first: ArithmeticException: / by zero
// if (total / count > 10 && count != 0) { ... }
String nickname = null;
// SAFE — when nickname is null, the length check is skipped
if (nickname != null && nickname.length() > 0)
{
System.out.println("Hi, " + nickname);
}
// CRASH — NullPointerException (recall 1.14: calling a method on null)
// if (nickname.length() > 0 && nickname != null) { ... }
College Board Note: Short-circuit evaluation is tested on almost every AP exam. Questions show a guard like
x != 0 && y / x > 2and ask whether an exception can occur. Order is everything: the guard goes on the left.
Oracle Exam Note: Java also has
&and|, which work on booleans but do not short-circuit; both sides always run. Oracle may showif (x != 0 & 10 / x > 1)and ask what happens whenxis 0. Answer: anArithmeticException.
Common Mistakes
// if (0 < x < 10) // COMPILE ERROR — (0 < x) is a boolean; boolean < 10 is meaningless
if (0 < x && x < 10) // correct
// if (choice == 1 || 2) // COMPILE ERROR — 2 is not a boolean
if (choice == 1 || choice == 2) // correct
if (x > 10 && x < 5) // compiles, but can NEVER be true
if (x > 5 || x < 10) // compiles, but is ALWAYS true
Exercise 2.05.A — Evaluate and Short-Circuit¶
Given int a = 4; int b = 0; String s = null;, decide whether each expression is true, false, or throws an exception. Ask yourself each time: does the right side actually run?
Exercise 2.05.B — Write the Method¶
Write two methods for the Car class from your Unit 1 Car Dealership project.
public class Car
{
private String make;
private int year;
private int mileage;
private double price;
public Car(String make, int year, int mileage, double price)
{
this.make = make;
this.year = year;
this.mileage = mileage;
this.price = price;
}
/** A car is "featured" if it is (2020 or newer AND under 30,000 miles)
* OR priced below 15000.00. */
public boolean isFeatured()
{
/* your code here */
}
/** Returns true if searchMake is not null and matches this car's make,
* ignoring case. Must never throw a NullPointerException. */
public boolean matchesMake(String searchMake)
{
/* your code here */
}
}
Activity 2.05.1 — Thunder Mountain Ride Gate¶
Overview
Your Unit 1 theme park needs a gate program for its newest roller coaster. A rider’s height, age, and answers decide whether they ride. The rules combine conditions with && (ranges), || (invalid input), and ! (a missing requirement), and one rule needs parentheses to group a compound condition correctly.
By the end of this activity you will be able to:
Write range checks with
&&Reject invalid input with
||Use
!with a boolean variableUse parentheses to group
&&and||in the same condition
Ride Rules (check them in this order)
# |
Rule |
Message |
|---|---|---|
1 |
Height under 30 or over 96 inches, or age under 1 or over 110 |
|
2 |
Has not watched the safety video |
|
3 |
Height 48–76 inches (inclusive) and age 8 or older |
|
4 |
Height 44–47 inches and riding with an adult |
|
5 |
Height over 76 inches |
|
6 |
Anyone else |
|
Fast Pass: after the gate decision, an admitted rider who is under 10 years old or under 48 inches also gets Fast Pass granted: use the short line!
To Do
Add the required block comment header
Read height (
int), age (int), riding with an adult (yes/no), and watched the safety video (yes/no). Store both yes/no answers asbooleanvariables using.equalsIgnoreCase("yes").Write the six rules as one
if / else if / elsechain, in the order shownRule 1 must be a single condition using
||Rule 2 must use
!with your safety-video booleanRules 3 and 4 must each be a single condition using
&&Declare
boolean admitted = false;before the chain and set it totruein the two “Welcome aboard” branchesWrite the Fast Pass check as one
ifthat usesadmitted,&&,||, and parenthesesTest every rule, plus the boundary heights 44, 47, 48, 76, and 77
Sample Output (three separate runs)
=== THUNDER MOUNTAIN RIDE GATE ===
Rider height (inches): 52
Rider age: 9
Riding with an adult? (yes/no): no
Watched the safety video? (yes/no): yes
Welcome aboard! Enjoy Thunder Mountain.
Fast Pass granted: use the short line!
=== THUNDER MOUNTAIN RIDE GATE ===
Rider height (inches): 46
Rider age: 7
Riding with an adult? (yes/no): no
Watched the safety video? (yes/no): yes
Sorry, you do not meet the ride requirements yet.
=== THUNDER MOUNTAIN RIDE GATE ===
Rider height (inches): 52
Rider age: 12
Riding with an adult? (yes/no): no
Watched the safety video? (yes/no): no
Please watch the safety video first.
Think About It (comment at the bottom)
Remove the parentheses from your Fast Pass condition:
admitted && age < 10 || height < 48. Find an input where the result changes, and explain why. (Hint:&&is evaluated before||.)Why must Rule 1 come first in the chain?
Rule 3 uses
height >= 48 && height <= 76. Write the opposite of that range as a single condition.
Submission
RideGate.javawith block comment headerTest Cases document: every rule triggered at least once, a Fast Pass rider, and the five boundary heights
Grading: AP CSA 5-point Assignment Rubric.
Activity 2.05.2 — Smart Checkout: Short-Circuit Guards¶
Overview
A store’s checkout program has two hidden dangers: a coupon lookup that returns null for bad codes, and a loyalty calculation that can divide by zero. You’ll crash the program on purpose to see both errors, then fix it with short-circuit guards: compound conditions where the left side protects the right side. This builds on the NullPointerException you met in 1.17.1 High Score Tracker.
By the end of this activity you will be able to:
Explain short-circuit evaluation for
&&and||Order a compound condition so it can never throw an exception
Guard against unboxing a
nullInteger(1.17)Guard against integer division by zero
Store Rules
Rule |
Details |
|---|---|
Coupon |
|
Big saver |
A valid coupon of 15% or more prints |
VIP |
Average loyalty points per visit ( |
To Do
Add the required block comment header
Read the subtotal (
double), coupon code (String), store visits (int), and loyalty points (int)Crash it on purpose (do this first). Write these unguarded versions, run them, and screenshot each crash:
if (percent < 5 || percent == null)with the codeBOGUS→NullPointerExceptionboolean vip = points / visits >= 50 && visits != 0;with 0 visits →ArithmeticException
Fix it. Reorder each condition so the safety check is on the left:
Guard 1 (
||): no discount when the coupon isnullor under 5%; otherwise apply itGuard 2 (
&&): print the Big saver message only when the coupon is notnulland at least 15%Guard 3 (
&&): VIP only when visits is not 0 and the average is at least 50
Above each guard, add a comment naming the exception it prevents and why the order works
Print the receipt with
printf(two decimal places)
Starter Code — SmartCheckout.java
import java.util.Scanner;
public class SmartCheckout
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.println("=== SMART CHECKOUT ===");
// TODO: read subtotal, coupon code, visits, and points
Integer percent = couponPercent(code); // WARNING: may be null!
// TODO: Guard 1, Guard 2, Guard 3, and the receipt
}
// ===================== PROVIDED — DO NOT MODIFY =====================
// Returns the percent off for a valid code, or null if the code is not valid
public static Integer couponPercent(String code)
{
if (code.equalsIgnoreCase("SAVE10"))
{
return 10;
}
else if (code.equalsIgnoreCase("TEACHER"))
{
return 15;
}
else if (code.equalsIgnoreCase("PENNY"))
{
return 1;
}
return null;
}
}
Sample Output (three separate runs)
=== SMART CHECKOUT ===
Subtotal: $80.00
Coupon code (or NONE): SAVE10
Store visits this year: 4
Loyalty points earned: 260
Coupon applied: 10% off
VIP shopper: extra $5.00 off!
Subtotal: $ 80.00
Discount: -$ 13.00
Total: $ 67.00
=== SMART CHECKOUT ===
Subtotal: $80.00
Coupon code (or NONE): teacher
Store visits this year: 0
Loyalty points earned: 0
Coupon applied: 15% off
Big saver! That's one of our best coupons.
Subtotal: $ 80.00
Discount: -$ 12.00
Total: $ 68.00
=== SMART CHECKOUT ===
Subtotal: $25.50
Coupon code (or NONE): NONE
Store visits this year: 3
Loyalty points earned: 149
No coupon discount applied.
Subtotal: $ 25.50
Discount: -$ 0.00
Total: $ 25.50
Think About It (comment at the bottom)
In the third run, 149 points over 3 visits is not VIP. What does
149 / 3evaluate to in Java, and why?Guard 1 and the “apply the coupon” logic are opposites. Use De Morgan’s Laws (2.06 preview) to write the condition for “the coupon is accepted.”
Try
10.0 / 0in a quick test. It doesn’t crash; what does it print? Why is integer division different?
Submission
SmartCheckout.javawith block comment header and guard commentsScreenshots of both crashes from the crash-it-on-purpose step
Test Cases document: a valid coupon, a
PENNYcoupon, an invalid code, 0 visits, and a VIP shopper
Grading: AP CSA 5-point Assignment Rubric. Pay particular attention to:
Every guard has the safety check on the left
Each guard comment names the exception it prevents
Activity 2.05.3 — Guess Checker Pt 3¶
Overview
Finish your Guess Checker. You’ll simplify the near-hit chains with compound Boolean expressions, give the player three guesses, and end with a win or lose message. This is the version you submit.
By the end of this activity you will be able to:
Replace an
else ifchain with a single condition using||Write a compound condition with
&&that controls when a game keeps goingUse a ternary to fix singular/plural output
Write test cases that prove each part of a program works
What’s New in the Starter
Repeating the guess three times requires a loop, which you’ll study in 2.07. The loop is provided below. Your job is to write the condition that decides whether the game keeps going, the same kind of Boolean expression you’ve been writing all unit.
To Do
Rewrite each digit’s near-hit check as one
else ifusing||. For example,g1becomes:else if (g1 == r2 || g1 == r3 || g1 == r4)Inside the loop, reset
hitsandnearHitsto0at the start of every guessWrite the loop condition: keep going while the player has guesses left AND has not cracked the code
After each guess, subtract one from
guessesLeftand print the hits, near hits, and guesses remainingUse a ternary so the output says
1 guessbut2 guesses/0 guessesAfter the loop, use an
if/elseto printYou cracked the code!orOut of guesses! The code was ____.Test at least four situations (see Submission) and record them in your Test Cases document
Starter Code — the new main method (helper methods are unchanged from Pt 1)
public static void main(String[] args)
{
String targetStr = makeCode();
System.out.println(targetStr); // LEAVE THIS LINE ON for testing and grading
int r1 = Integer.parseInt(targetStr.substring(0, 1));
int r2 = Integer.parseInt(targetStr.substring(1, 2));
int r3 = Integer.parseInt(targetStr.substring(2, 3));
int r4 = Integer.parseInt(targetStr.substring(3, 4));
final int MAX_GUESSES = 3;
int guessesLeft = MAX_GUESSES;
int hits = 0;
int nearHits = 0;
// PROVIDED LOOP (2.07): repeats its body as long as the condition is true
while ( /* TODO: guesses left AND code not cracked */ )
{
String guess = getGuess();
int g1 = Integer.parseInt(guess.substring(0, 1));
int g2 = Integer.parseInt(guess.substring(1, 2));
int g3 = Integer.parseInt(guess.substring(2, 3));
int g4 = Integer.parseInt(guess.substring(3, 4));
/* TODO: reset the counters */
/* TODO: four if / else-if checks using || */
/* TODO: update guessesLeft and print the results (use a ternary for guess/guesses) */
System.out.println();
}
/* TODO: win or lose message */
}
Sample Output
9782
Guess a 4-digit number from 1000 to 9999 with no duplicate digits: 9728
Number of hits: 2
Number of near hits: 2
You have 2 guesses remaining.
Guess a 4-digit number from 1000 to 9999 with no duplicate digits: 7928
Number of hits: 0
Number of near hits: 4
You have 1 guess remaining.
Guess a 4-digit number from 1000 to 9999 with no duplicate digits: 9782
Number of hits: 4
Number of near hits: 0
You have 0 guesses remaining.
You cracked the code!
Cracking it early ends the game right away:
5163
Guess a 4-digit number from 1000 to 9999 with no duplicate digits: 5163
Number of hits: 4
Number of near hits: 0
You have 2 guesses remaining.
You cracked the code!
Think About It (comment at the bottom)
Your loop condition uses
&&. Using De Morgan’s thinking (coming in 2.06), the game stops when what is true?Why must
hitsbe declared before the loop instead of inside it?
Submission
GuessChecker.javawith block comment header and dated change comments from Pt 2Test Cases document with at least these four runs (use the printed code to plan your guesses):
win on the first guess
win on the third guess
lose after three guesses
an invalid guess (a repeated digit or a 5-digit number) that gets re-prompted
Screenshot of one complete run
Grading: AP CSA 5-point Assignment Rubric. Pay particular attention to:
Near-hit checks use
||(oneelse ifper digit, not three)The loop condition correctly combines both stopping reasons with
&&Singular/plural output uses a ternary
Check for Understanding¶
#############################################################################
2.05a Operator Precedence — Oracle Foundations 1Z0-811¶
📌 Standards — 2.05a
Standard |
Description |
|---|---|
ICT 5.4 |
Interpret information and draw conclusions to make informed decisions |
ICT 10.1 |
Interpret and explain ICT-specific terminology |
C4.6 |
Use proper programming language syntax |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Oracle Exam Note: Oracle 1Z0-811 includes “use operator precedence” in its objectives and tests it with dense one-line expressions. AP questions add parentheses to avoid precedence puzzles, but the same evaluation rules still apply.
Evaluate expressions that mix arithmetic, relational, and logical operators.
Trace pre- and post-increment inside a condition.
Use parentheses to make the intended order obvious.
Precedence Table (highest at the top)
Level |
Operators |
Notes |
|---|---|---|
1 |
|
Postfix: use the value, then change it |
2 |
|
Prefix and unary: change first, then use. Includes casts |
3 |
|
Left to right |
4 |
|
Left to right (also String concatenation) |
5 |
|
Relational |
6 |
|
Equality |
7 |
|
AND binds tighter than OR |
8 |
|
|
9 |
|
Ternary |
10 |
|
Assignment happens last, right to left |
Memory aid: unary → math → compare → equal → AND → OR → ternary → assign.
Worked Examples
System.out.println(true || false && false);
&& goes first: false && false is false. Then true || false is true. (Reading strictly left to right would give false, which is the trap.)
System.out.println(5 + 3 * 2 > 10 && !(4 % 2 == 1));
3 * 2→6, and4 % 2→05 + 6→1111 > 10→true, and0 == 1→false!(false)→truetrue && true→true
Increments Inside Conditions
int x = 5;
boolean b = x++ > 5 || x > 5;
System.out.println(b + " " + x); // true 6
x++ > 5 compares the old value (5 > 5 is false), then x becomes 6. The right side, x > 5, sees 6, so b is true.
int y = 3;
boolean c = y > 5 && ++y > 3;
System.out.println(c + " " + y); // false 3
y > 5 is false, so && short-circuits and ++y never runs. y stays 3.
Oracle Exam Note: Short-circuiting combined with
++is a favorite Oracle trap. Always ask: did the right side actually execute?
Exercise 2.05a.A — Evaluate It¶
Evaluate each expression, given int a = 2, b = 5;. Use the precedence table: unary → math → compare → equal → AND → OR.
Check for Understanding¶
#############################################################################
2.06 Comparing Boolean Expressions¶
📌 Standards — 2.06
Standard |
Description |
|---|---|
ICT 5.4 |
Interpret information and draw conclusions to make informed decisions |
ICT 5.8 |
Create and use algorithms and solve problems |
ICT 10.1 |
Interpret and explain ICT-specific terminology |
C4.6 |
Use proper programming language syntax |
C4.7 |
Use various data structures including objects |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Determine whether two Boolean expressions are equivalent using a truth table.
Apply De Morgan’s Laws, including correctly negating relational operators.
Compare object references with
==,!=, andnull.Explain when
==and.equals()give different answers, including for your own classes.
Part 1 — Equivalent Expressions¶
Two Boolean expressions are equivalent if they produce the same value for every possible input. A truth table proves it by checking every row.
Are !(a && b) and !a || !b equivalent?
a |
b |
a && b |
!(a && b) |
!a |
!b |
!a || !b |
|---|---|---|---|---|---|---|
T |
T |
T |
F |
F |
F |
F |
T |
F |
F |
T |
F |
T |
T |
F |
T |
F |
T |
T |
F |
T |
F |
F |
F |
T |
T |
T |
T |
The two bold columns match in every row, so the expressions are equivalent.
De Morgan’s Laws
!(a && b) ≡ !a || !b // NOT (A AND B) is (NOT A) OR (NOT B)
!(a || b) ≡ !a && !b // NOT (A OR B) is (NOT A) AND (NOT B)
To push a ! inside parentheses: negate each piece and flip && ↔ ||.
Negating Relational Operators
This is where most mistakes happen. The opposite of “greater than” is not “less than.”
Expression |
Negation |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Worked Example
!(age >= 13 && age <= 19)
Negate each piece:
age >= 13→age < 13;age <= 19→age > 19Flip
&&to||Result:
age < 13 || age > 19, “not a teenager,” which matches the 1.02.1 Allowance logic
College Board Note: AP questions give an expression like
!(x > 5 || y != 3)and ask which choice is equivalent. Two choices usually look almost the same: one saysx < 5(wrong) and one saysx <= 5(right). Negate the operators carefully.
Part 2 — Comparing Objects¶
You learned in 1.07a and 1.15 that object variables store references (addresses), and that two variables can be aliases for the same object. Here’s the full set of rules.
Comparison |
What It Asks |
|---|---|
|
Do these variables point to the same object? |
|
Do they point to different objects? |
|
Does this variable point to no object at all? |
|
Do these objects have the same content? (Only if the class defines what “same content” means) |
Aliases vs. Equal Content
public class Locker
{
private int number;
public Locker(int number)
{
this.number = number;
}
}
Locker a = new Locker(214);
Locker b = new Locker(214);
Locker c = a; // alias: c and a point to the SAME object
System.out.println(a == b); // false — two different objects
System.out.println(a == c); // true — same object
System.out.println(a.equals(b)); // false — surprise!
Why is a.equals(b) false when both lockers are #214? Locker never defined its own equals method, so it uses the default one inherited from Object, and the default equals just does ==. String and Integer give “content” answers because their classes override equals. You’ll write your own equals in Unit 5.
Exam Note (AP + Oracle): For a class that doesn’t override
equals,.equals()behaves exactly like==. Both exams test this with a small custom class.
Checking for null
Calling a method on null throws a NullPointerException (recall 1.14). Compare to null with == or != before calling methods, and use short-circuiting (2.05) to keep it to one line:
String weapon = null; // the player hasn't picked one up yet
if (weapon != null && weapon.equals("sword"))
{
System.out.println("You swing the sword!");
}
else
{
System.out.println("You have no sword.");
}
Never write
weapon.equals(null)to check for null. Ifweaponis null, that line crashes. Always useweapon == null.
Exercise 2.06.A — Apply De Morgan’s Laws¶
Write an equivalent expression with no ! operator for each one. Negate each piece and flip && ↔ ||.
!(x > 10 && y < 5)!(score < 0 || score > 100)!(a == b || c != d)!(!done && count >= 3)
Exercise 2.06.B — Prove It with a Truth Table¶
Is a || (b && !a) equivalent to a || b? Build the truth table to prove your answer.
Exercise 2.06.C — Write the Method¶
The Unit 1 Guest class tracks which ride a guest is currently on (null if none). Write isOnRide. It must never throw an exception.
public class Guest
{
private String name;
private String currentRide; // null when the guest is not on a ride
public Guest(String name)
{
this.name = name;
currentRide = null;
}
public void board(String rideName)
{
currentRide = rideName;
}
/** Returns true if this guest is currently on the ride named rideName. */
public boolean isOnRide(String rideName)
{
/* your code here */
}
}
Activity 2.06.1 — Two Ways to Say No: De Morgan Checker¶
Overview
Every condition with a ! in front of parentheses can be rewritten without the ! using De Morgan’s Laws. But how do you know your rewrite is right? You test it. In this activity you write each condition two ways as methods, and a provided test harness runs both versions on the same inputs and reports MATCH or MISMATCH. Every method is one line long, the same shape as an AP free-response method.
By the end of this activity you will be able to:
Apply De Morgan’s Laws to
&&and||conditionsNegate relational operators correctly (
>=becomes<, not<=)Test whether two Boolean expressions are equivalent, including at the boundaries
Write methods that return a
boolean
The Four Scenarios
# |
Method Pair |
Original (write it exactly like this) |
|---|---|---|
1 |
|
School stays open when it is not the case that snow is 6+ inches or the temperature is below -10: |
2 |
|
A password is rejected when it is not the case that it has 8+ characters and a digit: |
3 |
|
The game is over when it is not the case that lives remain and time remains: |
4 |
|
A score is out of range when it is not the case that it is from 0 to 100: |
To Do
Add the required block comment header
Write all eight methods. Each
...Originalmethod returns the condition in the table, exactly as written.Each
...Rewritemethod returns the De Morgan equivalent with no!in front of parentheses (!hasDigiton a single variable is fine)Run the program. Every line in Scenarios 1–4 must say MATCH. If you see MISMATCH, fix your rewrite. Don’t change the tests.
Study the provided Common Mistake section. It’s supposed to show MISMATCH. Explain why in a comment.
In a comment at the bottom, write the full truth table for Scenario 2 (all four combinations of
length >= 8andhasDigit)
Starter Code — TwoWaysToSayNo.java
public class TwoWaysToSayNo
{
public static void main(String[] args)
{
System.out.println("=== SCENARIO 1: School stays open ===");
check("snow=2, temp=20", schoolOpenOriginal(2, 20), schoolOpenRewrite(2, 20));
check("snow=8, temp=20", schoolOpenOriginal(8, 20), schoolOpenRewrite(8, 20));
check("snow=2, temp=-15", schoolOpenOriginal(2, -15), schoolOpenRewrite(2, -15));
check("snow=6, temp=-10", schoolOpenOriginal(6, -10), schoolOpenRewrite(6, -10));
System.out.println("=== SCENARIO 2: Password rejected ===");
check("length=10, digit=true", rejectedOriginal(10, true), rejectedRewrite(10, true));
check("length=10, digit=false", rejectedOriginal(10, false), rejectedRewrite(10, false));
check("length=5, digit=true", rejectedOriginal(5, true), rejectedRewrite(5, true));
check("length=8, digit=true", rejectedOriginal(8, true), rejectedRewrite(8, true));
System.out.println("=== SCENARIO 3: Game over ===");
check("lives=3, time=30", gameOverOriginal(3, 30), gameOverRewrite(3, 30));
check("lives=0, time=30", gameOverOriginal(0, 30), gameOverRewrite(0, 30));
check("lives=3, time=0", gameOverOriginal(3, 0), gameOverRewrite(3, 0));
check("lives=0, time=0", gameOverOriginal(0, 0), gameOverRewrite(0, 0));
System.out.println("=== SCENARIO 4: Score out of range ===");
check("score=50", outOfRangeOriginal(50), outOfRangeRewrite(50));
check("score=0", outOfRangeOriginal(0), outOfRangeRewrite(0));
check("score=100", outOfRangeOriginal(100), outOfRangeRewrite(100));
check("score=101", outOfRangeOriginal(101), outOfRangeRewrite(101));
System.out.println("=== THE COMMON MISTAKE (provided) ===");
check("score=0", outOfRangeOriginal(0), outOfRangeBuggy(0));
check("score=100", outOfRangeOriginal(100), outOfRangeBuggy(100));
}
// PROVIDED — prints one test row and whether the two versions agree
public static void check(String inputs, boolean original, boolean rewrite)
{
String result = (original == rewrite) ? "MATCH" : "MISMATCH";
System.out.printf(" %-24s original=%-6b rewrite=%-6b %s%n", inputs, original, rewrite, result);
}
// TODO: write the eight methods, for example:
// public static boolean schoolOpenOriginal(int snow, int temp) { return /* ... */; }
// public static boolean schoolOpenRewrite(int snow, int temp) { return /* ... */; }
// PROVIDED — a common mistake: negating >= as > and <= as <
public static boolean outOfRangeBuggy(int score)
{
return score <= 0 || score >= 100;
}
}
Sample Output (when all eight methods are correct)
=== SCENARIO 1: School stays open ===
snow=2, temp=20 original=true rewrite=true MATCH
snow=8, temp=20 original=false rewrite=false MATCH
snow=2, temp=-15 original=false rewrite=false MATCH
snow=6, temp=-10 original=false rewrite=false MATCH
=== SCENARIO 2: Password rejected ===
length=10, digit=true original=false rewrite=false MATCH
length=10, digit=false original=true rewrite=true MATCH
length=5, digit=true original=true rewrite=true MATCH
length=8, digit=true original=false rewrite=false MATCH
=== SCENARIO 3: Game over ===
lives=3, time=30 original=false rewrite=false MATCH
lives=0, time=30 original=true rewrite=true MATCH
lives=3, time=0 original=true rewrite=true MATCH
lives=0, time=0 original=true rewrite=true MATCH
=== SCENARIO 4: Score out of range ===
score=50 original=false rewrite=false MATCH
score=0 original=false rewrite=false MATCH
score=100 original=false rewrite=false MATCH
score=101 original=true rewrite=true MATCH
=== THE COMMON MISTAKE (provided) ===
score=0 original=false rewrite=true MISMATCH
score=100 original=false rewrite=true MISMATCH
Think About It (comment at the bottom)
The Common Mistake only fails at 0 and 100. Why do the boundary values catch the bug when 50 and 101 don’t?
Which test in Scenario 1 would catch someone who wrote
temp > -10instead oftemp >= -10?Write one more scenario of your own: an English rule, the
!( ... )original, and its rewrite. Add twocheckcalls that test it, including a boundary.
Submission
TwoWaysToSayNo.javawith block comment header, all methods, the Scenario 2 truth table, and your own scenarioScreenshot of the output showing every Scenario 1–4 line as MATCH
Grading: AP CSA 5-point Assignment Rubric. Pay particular attention to:
No
!in front of parentheses in any...RewritemethodRelational operators are negated correctly
Your own scenario includes a boundary test
Activity 2.06.2 — Body Mass Index (BMI)¶
Overview
Body Mass Index (BMI) is a person’s weight divided by the square of their height. Health professionals use it as a quick screening number for weight categories. It does not diagnose anyone’s health. You’ll write a BMI calculator with two methods, validate the input using De Morgan’s Laws, and practice choosing between units with String comparison.
Use sample values. For testing, use the sample numbers below or made-up values. You do not need to enter your own measurements.
By the end of this activity you will be able to:
Write a method that calls another method you wrote (1.10)
Classify a
doublevalue into ranges with anif / else if / elsechainWrite an input-validation condition two equivalent ways using De Morgan’s Laws
Compare user input Strings with
.equalsIgnoreCase()
Weight Classes (CDC)
BMI |
Weight Class |
|---|---|
below 18.5 |
underweight |
18.5 up to (not including) 25.0 |
normal |
25.0 up to (not including) 30.0 |
overweight |
30.0 and above |
obese |
Watch the boundaries: a BMI of exactly 25.0 is overweight, not normal.
Formulas
Units |
Formula |
|---|---|
Pounds and inches |
BMI = (weight ÷ height²) × 703 |
Kilograms and meters |
BMI = weight ÷ height². If height is in centimeters, divide by 100 first |
Source: cdc.gov/healthyweight
To Do
Add the required block comment header
Use
Scannerto read the height (inches) and weight (pounds) asdoublevaluesWrite
public static double bmi(double height, double weight)that returns the BMI (imperial formula)Write
public static String weightClass(double height, double weight)that callsbmiand returns the weight class as aStringValidate the input. Height and weight must both be greater than 0.
Write the “invalid” condition with
!around a compound condition:!(height > 0 && weight > 0)In a comment directly above it, write the De Morgan equivalent with no
!If the input is invalid, print an error message and do not calculate
Print the BMI to one decimal place with
printfand print the weight classTest values on both sides of every weight-class boundary, plus both invalid cases
Extra Credit — Metric or Imperial
Ask
metric (m) or imperial (i)?and compare the answer with.equalsIgnoreCase()soMandmboth workFor metric, read centimeters and kilograms. Either convert to inches and pounds before calling your methods (1 in = 2.54 cm, 1 kg = 2.20462 lb) or add metric versions of the methods.
Sample Output
Would you like to use metric (m) or imperial (i) units? i
Height (in inches): 70.0
Weight (in pounds): 194.25
BMI = 27.9
Weight class: overweight
Would you like to use metric (m) or imperial (i) units? M
Height (in centimeters): 177.8
Weight (in kilograms): 88.1
BMI = 27.9
Weight class: overweight
Would you like to use metric (m) or imperial (i) units? i
Height (in inches): 0
Weight (in pounds): 150
Height and weight must both be greater than 0.
Think About It (comment at the bottom)
Why should
weightClasscallbmiinstead of repeating the formula?Your chain uses
value < 25.0for the normal range. What changes if you writevalue <= 25.0, and which BMI would be misclassified?Write the valid-input condition (the opposite of your invalid check) without using
!.
Submission
BMI.javawith block comment headerTest Cases document: at least one value in each weight class, values just below and just above 18.5, 25.0, and 30.0, and both invalid cases (zero and negative)
Grading: AP CSA 5-point Assignment Rubric. Pay particular attention to:
weightClasscallsbmi(no duplicated formula)The validation condition and its De Morgan equivalent are both correct
Boundary values land in the correct weight class
Activity 2.06.3 — Library Return Desk: Comparing Objects¶
Overview
The school library tracks books as objects. When a student returns a book, the desk has to decide: is this the book they checked out? That question turns out to be trickier than it looks. Two Book objects can have identical titles and authors and still be different objects. You’ll predict and test how == and .equals() behave, then write your own method that compares two books by their content.
By the end of this activity you will be able to:
Explain the difference between an alias and an equal-content object
Predict the result of
==,!=, and.equals()on objects of a class you wroteExplain why
.equals()acts like==when a class doesn’t override itWrite a content-comparison method with a
nullguard
To Do
Part A — Predict, then Run
Before running anything, write your predictions for the four Part A lines in a comment at the top of
ReturnDesk.javaRun the program and record which predictions were right. For any you missed, explain why in your comment.
Part B — Write sameBook
In
Book.java, writepublic boolean sameBook(Book other). It returnstruewhenotheris notnulland the titles match and the authors match, ignoring capitalization.Use short-circuiting (2.05) so
sameBook(null)returnsfalseinstead of crashingDo not use
==to compare the Strings
Part C — The Return Desk
In
ReturnDesk.java, writepublic static void processReturn(Book onRecord, Book returned)using anif / else if / elsechain:onRecordisnull→No book on record. [returned] goes to the lost-and-found cart.the books match (
sameBook) →Thank you! [returned] has been checked in.otherwise →
Mismatch: expected [onRecord] but received [returned].
The
nullcheck must come first. Explain why in a comment.
Starter Code — Book.java
public class Book
{
private String title;
private String author;
public Book(String title, String author)
{
this.title = title;
this.author = author;
}
public String getTitle() { return title; }
public String getAuthor() { return author; }
// TODO Part B: returns true if other is not null and has the same
// title and author (ignoring case)
public boolean sameBook(Book other)
{
/* your code here */
}
@Override
public String toString()
{
return "\"" + title + "\" by " + author;
}
}
Starter Code — ReturnDesk.java
public class ReturnDesk
{
public static void main(String[] args)
{
Book checkedOut = new Book("Hatchet", "Gary Paulsen");
Book shelfCopy = new Book("Hatchet", "Gary Paulsen");
Book myCopy = checkedOut; // alias
Book returned = new Book("hatchet", "GARY PAULSEN");
Book nothing = null; // nothing checked out yet
// PART A: write your predictions in a comment BEFORE running
System.out.println("=== PART A: == vs. equals ===");
System.out.println("checkedOut == myCopy: " + (checkedOut == myCopy));
System.out.println("checkedOut == shelfCopy: " + (checkedOut == shelfCopy));
System.out.println("checkedOut.equals(shelfCopy): " + checkedOut.equals(shelfCopy));
System.out.println("checkedOut.getTitle().equals(shelfCopy.getTitle()): "
+ checkedOut.getTitle().equals(shelfCopy.getTitle()));
System.out.println();
System.out.println("=== PART B: sameBook ===");
System.out.println("checkedOut.sameBook(shelfCopy): " + checkedOut.sameBook(shelfCopy));
System.out.println("checkedOut.sameBook(returned): " + checkedOut.sameBook(returned));
System.out.println("checkedOut.sameBook(nothing): " + checkedOut.sameBook(nothing));
System.out.println();
System.out.println("=== PART C: Return desk ===");
processReturn(checkedOut, returned);
processReturn(checkedOut, new Book("Holes", "Louis Sachar"));
processReturn(nothing, returned);
}
// TODO Part C
public static void processReturn(Book onRecord, Book returned)
{
/* your code here */
}
}
Sample Output
=== PART A: == vs. equals ===
checkedOut == myCopy: true
checkedOut == shelfCopy: false
checkedOut.equals(shelfCopy): false
checkedOut.getTitle().equals(shelfCopy.getTitle()): true
=== PART B: sameBook ===
checkedOut.sameBook(shelfCopy): true
checkedOut.sameBook(returned): true
checkedOut.sameBook(nothing): false
=== PART C: Return desk ===
Thank you! "hatchet" by GARY PAULSEN has been checked in.
Mismatch: expected "Hatchet" by Gary Paulsen but received "Holes" by Louis Sachar.
No book on record. "hatchet" by GARY PAULSEN goes to the lost-and-found cart.
Think About It (comment at the bottom)
checkedOut.equals(shelfCopy)isfalse, butcheckedOut.getTitle().equals(shelfCopy.getTitle())istrue. Explain the difference in one or two sentences.What would happen if
processReturncheckedonRecord.sameBook(returned)before checking fornull?In Unit 5 you’ll learn to override
equalsitself. Based onsameBook, what do you think the body of aBookequalsmethod will need to compare?
Submission
Book.javaandReturnDesk.javawith block comment headersYour Part A predictions and corrections, plus Think About It answers, in comments
Screenshot of the output
Grading: AP CSA 5-point Assignment Rubric. Pay particular attention to:
sameBookguards againstnullwith the check on the leftStrings are compared with
.equalsIgnoreCase(), never==The
nullcase is handled first inprocessReturn
Check for Understanding¶
#############################################################################
Unit 2 Mid-Unit Project — Choose Your Own Adventure¶
📌 Standards — Mid-Unit Project
Standard |
Description |
|---|---|
ICT 2.0 |
Communications — communicate clearly in written and electronic formats |
ICT 5.4 |
Interpret information and draw conclusions to make informed decisions |
ICT 5.8 |
Create and use algorithms and solve problems |
ICT 5.9 |
Deconstruct large problems into smaller components |
ICT 7.5 |
Apply high-quality techniques to product design and development |
C4.6 |
Use proper programming language syntax |
C4.7 |
Use various data structures including objects |
C4.8 |
Use OOP concepts: properties, methods, and inheritance |
C4.9 |
Create programs using control structures, procedures, and variables |
C4.11 |
Document development work using comments |
C5.4 |
Design a solution to a problem |
C5.5 |
Implement a solution |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 2 |
Communicate clearly, effectively, and with reason |
CRP 5 |
Utilize critical thinking to make sense of problems |
CRP 7 |
Act as a responsible and contributing citizen and employee |
Apply every selection concept from 2.01–2.06 in one cohesive program.
Combine Unit 2 decision logic with a Unit 1 class (constructors,
toString, instance methods).Plan with a flowchart and timeline before coding, then test every path.
I will demonstrate mastery of selection by building an interactive story game.
Overview
You are a game developer building a text-based Choose Your Own Adventure game. The player reads a scene, makes a choice, and the story branches. Earlier choices change what happens later, a random event keeps every playthrough unpredictable, and the story ends in one of at least three different endings.
Your story, your theme: escape a haunted school, survive a zombie mall, solve a mystery in a data center, explore a shipwreck. Keep it school-appropriate.
No loops required. Your game is a single playthrough from start to an ending. (Loops arrive in 2.07; then you could add “Play again?”)
Required Files: Main.java, Player.java (minimum)
Submission: All .java files, flowchart, timeline, and Test Cases, combined into one PDF, plus your .java files
Part 1 — Plan First¶
Digital flowchart of your story using correct symbols (2.01): oval start/end, parallelogram input/output, rectangle process, diamond decision with true/false labels. Every ending in your code must appear in the flowchart.
Digital timeline chart showing your plan: story outline, flowchart,
Player.java,Main.javascenes, testing, final PDF.
Part 2 — Player.java¶
Your Player class stores the player’s state. Complete the starter below. You may rename fields to fit your theme (hp → sanity, gold → credits), but every required method must exist and be used in Main.
/*
* Name: [Your Full Name]
* Partner: None
* Course: AP Computer Science A
* Instructor: [Instructor Name]
* Assignment: Unit 2 Mid-Unit Project — Choose Your Own Adventure
* Due Date: [Month Day, Year]
*/
public class Player
{
private String name;
private int health;
private int gold;
private String item; // null until the player picks something up
// Constructor: sets name, starts health at 100, gold at a value you choose, item at null
public Player(String name)
{
/* your code here */
}
// ----- Accessors -----
public String getName() { return name; }
public int getHealth() { return health; }
public int getGold() { return gold; }
public String getItem() { return item; }
// ----- void methods: change the player's state -----
// Subtracts damage from health. Health must never drop below 0 (use an if).
public void takeDamage(int damage)
{
/* your code here */
}
// Stores the item the player picked up.
public void pickUp(String newItem)
{
/* your code here */
}
// Subtracts cost from gold ONLY if the player can afford it.
public void spend(int cost)
{
/* your code here */
}
// ----- non-void methods: answer questions (FRQ style) -----
// Returns true if health is greater than 0.
public boolean isAlive()
{
/* your code here */
}
// Returns true if the player has at least cost gold.
public boolean canAfford(int cost)
{
/* your code here */
}
// Returns true if the player is holding an item that matches itemName (ignore case).
// Must NOT throw an exception when item is null.
public boolean hasItem(String itemName)
{
/* your code here */
}
// Returns a status String such as: "Ava | Health: 85 | Gold: 20 | Item: flashlight"
// Shows "none" when item is null (a ternary works well here).
@Override
public String toString()
{
/* your code here */
}
}
Part 3 — Main.java¶
Build your story in Main.java. Your game must:
Ask for the player’s name with
Scannerand create aPlayer.Have at least four decision points, each driven by user input.
Use both
Stringinput (normalized with.trim().toLowerCase()) andintinput (a numbered menu).Include at least three
if / else if / elsechains, and at least oneifnested inside anotherif.Include at least one decision that depends on an earlier choice (for example, the locked door only opens if the player picked up the key two scenes ago).
Use a
switchfor one numbered menu and a ternary somewhere meaningful (2.04a).Use
&&,||, and!each at least once in conditions that affect the story.Include a short-circuit guard (2.05): a compound condition where the left side protects the right side from an error. Add a comment explaining it.
Include a condition written with
!( ... )and, in a comment directly above it, its De Morgan equivalent (2.06).Compare Strings only with
.equals()/.equalsIgnoreCase(), never==.Compare an object reference to
nullbefore using it (for example, checkinggetItem()).Use
Math.random()(orRandom) for at least one random event that changes the path, such as a 30% chance of a trap:if (Math.random() < 0.30).Print the player’s status using
toString()at least twice, and the final summary line withprintforString.format.Reach at least three distinct endings.
Sample Output (an example story, “Server Room Escape.” Yours will be different.)
=== SERVER ROOM ESCAPE ===
Enter your name: Ava
Ava | Health: 100 | Gold: 25 | Item: none
The lights flicker. A toolbox sits by the door. Do you open it? (yes/no): yes
You find a flashlight!
Ava | Health: 100 | Gold: 25 | Item: flashlight
Two hallways:
1. The humming hallway
2. The dark hallway
3. Wait for help
Choose 1, 2, or 3: 2
Good thing you have a flashlight. You spot a loose floor panel and step around it.
A vending machine sells an access card for 20 gold. Buy it? (yes/no): yes
You bought the access card. 5 gold left.
A sparking cable whips across the hall!
You dodge it.
The exit door has a card reader...
Card accepted. You walk out into the sunlight.
*** ENDING 1 of 3: THE CLEAN ESCAPE ***
Final status -> Ava | Health: 100 | Gold: 5
Because of the random event, the “sparking cable” scene might hit the player on another run. Your Test Cases document needs to show both outcomes.
Part 4 — Test Cases¶
At least one test case per ending (minimum three), showing the inputs typed at every decision
At least one test of the random event going each way
At least one test of an earlier choice changing a later scene
Each test lists: inputs, expected output, actual output, Pass/Fail
Quality screenshots of at least three complete playthroughs
Unit 2 Mid-Unit Project Rubric¶
Each concept below is worth 1 point. Credit is awarded when the concept is used correctly and meaningfully, not simply present in the code. Partial credit is not awarded per concept.
# |
Category |
Concept |
What to Demonstrate |
Pts |
|---|---|---|---|---|
1 |
2.01 Algorithms |
Flowchart |
Digital flowchart with correct symbols; every decision diamond has labeled true/false exits; all endings shown |
1 |
2 |
2.01 Algorithms |
Timeline |
Digital timeline chart covering planning, coding, and testing |
1 |
3 |
2.02 Boolean Expressions |
Relational operators |
Uses at least three different relational operators ( |
1 |
4 |
2.02 Boolean Expressions |
boolean variable |
Stores the result of a comparison in a |
1 |
5 |
2.03 if Statements |
if/else |
At least one |
1 |
6 |
2.03 if Statements |
Braces and scope |
All |
1 |
7 |
2.04 Nested if |
Multiway selection |
At least three |
1 |
8 |
2.04 Nested if |
Nested if |
At least one |
1 |
9 |
2.04 Nested if |
Condition order |
Range-based conditions are ordered so every branch is reachable |
1 |
10 |
2.04a Switch (Oracle) |
switch |
Uses a |
1 |
11 |
2.04a Ternary (Oracle) |
Ternary operator |
Uses |
1 |
12 |
2.05 Compound Boolean |
&& |
Uses |
1 |
13 |
2.05 Compound Boolean |
|| |
Uses |
1 |
14 |
2.05 Compound Boolean |
! |
Uses |
1 |
15 |
2.05 Compound Boolean |
Short-circuit guard |
A compound condition where the left side prevents an error on the right, with a comment explaining it |
1 |
16 |
2.06 Comparing Boolean |
De Morgan’s Law |
A |
1 |
17 |
2.06 Comparing Objects |
String comparison |
All String comparisons use |
1 |
18 |
2.06 Comparing Objects |
null check |
Compares an object reference to |
1 |
19 |
Story Logic |
Earlier choice matters |
At least one decision combines the current choice with a choice made earlier |
1 |
20 |
Story Logic |
Random event |
Uses |
1 |
21 |
Story Logic |
Three endings |
At least three distinct endings, each reachable |
1 |
22 |
Unit 1 — OOP |
Player class |
|
1 |
23 |
Unit 1 — OOP |
toString() |
Overrides |
1 |
24 |
Unit 1 — Instance Methods |
void methods |
|
1 |
25 |
Unit 1 — Instance Methods |
non-void methods |
|
1 |
26 |
Unit 1 — Scanner |
Input types |
Reads both |
1 |
27 |
Unit 1 — String Methods |
Input normalization |
Uses |
1 |
28 |
Unit 1 — Formatting |
printf / String.format |
Final summary uses |
1 |
29 |
Documentation |
Headers and comments |
Required block comment header in both files, all fields completed; meaningful comments throughout |
1 |
30 |
Submission |
Test Cases |
Test cases cover every ending, both random outcomes, and an earlier-choice path (inputs, expected, actual, Pass/Fail) |
1 |
31 |
Submission |
Files and PDF |
Single PDF (flowchart, timeline, screenshots, code) plus all |
1 |
32 |
Submission |
Compiles & runs |
Program compiles without errors and every path runs without crashing |
1 |
TOTAL |
32 |
Grading Notes:
Code must compile and run to receive credit for most concept points.
A concept used only in a comment, or in code that can never execute, does not earn its point.
The block comment header must have all fields completed, not left as placeholders.
De Morgan point: the commented equivalent must be logically correct, including the negated relational operators.
Short-circuit point: the comment must name what error the left side prevents.
nullcheck point: the program must check before use. ANullPointerExceptionon any tested path loses this point and point 32.
#############################################################################
2.06a The Date/Time API — Oracle Foundations 1Z0-811¶
📌 Standards — 2.06a
Standard |
Description |
|---|---|
ICT 4.1 |
Use electronic reference materials to gather information |
ICT 5.8 |
Create and use algorithms and solve problems |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 4 |
Apply technology to enhance productivity |
CRP 5 |
Utilize critical thinking to make sense of problems |
Oracle Exam Note: Creating and manipulating calendar data with the
java.timeclasses is tested on Oracle 1Z0-811. It is not on the AP exam. This section comes before loops because every activity from 2.07 on prints a run stamp built with these classes.
Create
LocalDate,LocalTime, andLocalDateTimeobjects withnow()andof().Explain why
java.timeobjects are immutable, and reassign the result ofplusmethods.Measure the gap between two dates or times with
PeriodandDuration.Format dates with
DateTimeFormatter.
The Core Classes (all in java.time, so they need an import. Recall 1.01a: only java.lang is automatic)
Class |
Holds |
Create One |
|---|---|---|
|
a date, no time |
|
|
a time, no date |
|
|
both |
|
|
a gap in years, months, days |
|
|
a gap in hours, minutes, seconds, nanoseconds |
|
|
a display pattern |
|
These classes have no public constructors.
new LocalDate()does not compile; you use the static methodsnow()andof(...), the same way you usedMathmethods in 1.11.
Immutability: The Big Trap
java.time objects can never change, just like String (1.15). Methods like plusDays return a new object.
LocalDate day = LocalDate.of(2026, 10, 11);
day.plusDays(7); // creates a new date... and throws it away
System.out.println(day); // 2026-10-11 (unchanged!)
day = day.plusDays(7); // reassign to keep the new date
System.out.println(day); // 2026-10-18
Comparing and Measuring
LocalDate today = LocalDate.of(2026, 10, 11);
LocalDate trip = LocalDate.of(2027, 3, 14);
System.out.println(trip.isAfter(today)); // true
System.out.println(trip.isBefore(today)); // false
System.out.println(trip.equals(today)); // false
Period gap = Period.between(today, trip);
System.out.println(gap.getMonths() + " months, " + gap.getDays() + " days"); // 5 months, 3 days
Formatting
Pattern Letter |
Meaning |
Example |
|---|---|---|
|
year |
2026 / 26 |
|
month |
10 / Oct / October |
|
day of month |
11 |
|
day of week |
Sunday |
|
hour (24-hour / 12-hour) |
14 / 02 |
|
minutes |
30 |
|
AM/PM |
PM |
LocalDateTime when = LocalDateTime.of(2026, 10, 11, 14, 30);
System.out.println(when.format(DateTimeFormatter.ofPattern("MM/dd/yy"))); // 10/11/26
System.out.println(when.format(DateTimeFormatter.ofPattern("EEEE, MMMM dd"))); // Sunday, October 11
Oracle Exam Note: Watch for these traps:
MMis month andmmis minutes.Months run 1–12 (the old
Calendarclass used 0–11).
LocalDate.of(2026, 2, 30)compiles but throws aDateTimeExceptionat run time.A
LocalDatehas no time, so callinggetHour()on one does not compile.
The Run Stamp (used in every activity from here to the end of Unit 2)
From now on, every program starts by printing a run stamp, the date and time it ran. It takes three lines and two imports:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
// first lines of main:
DateTimeFormatter stamp = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a");
System.out.println("Run: " + LocalDateTime.now().format(stamp));
Run: 10/11/2026 01:03 PM
When an activity says “print the run stamp (2.06a)”, this is what it means.
Check for Understanding¶
Activity 2.06a.1 — Birthday Countdown¶
Overview
How long until your next birthday? Java can work it out, but there’s a catch: if your birthday already happened this year, the next one is next year. That takes an if statement, isBefore, and a reassignment, because LocalDate is immutable.
To Do
Add the required block comment header
Read a birthday month and day with
ScannerGet today’s date with
LocalDate.now()and build this year’s birthday withLocalDate.of(today.getYear(), month, day)If that birthday is before today, move it to next year with
plusYears(1). Remember to reassign.If the birthday is today, print
Happy birthday! It's today!Otherwise, use
Period.between(today, birthday)and print:
Your birthday is in X months and Y days!
Use ternaries so the output says
1 month/1 dayinstead of1 months/1 daysAlso print the total number of days to go with
ChronoUnit.DAYS.between(today, birthday)(importjava.time.temporal.ChronoUnit)
Sample Output (run on October 11, 2026. Your dates will differ.)
Birthday month (1-12): 3
Birthday day: 14
Today: 2026-10-11
Next birthday: 2027-03-14
Your birthday is in 5 months and 3 days!
Total days to go: 154
Birthday month (1-12): 10
Birthday day: 12
Today: 2026-10-11
Next birthday: 2026-10-12
Your birthday is in 0 months and 1 day!
Total days to go: 1
Extension: a February 29 birthday crashes your program in most years. Find out why, then handle it (for example, celebrate on February 28 in non-leap years; LocalDate has an isLeapYear() method).
Submission: BirthdayCountdown.java. No test cases needed.
Grading: AP CSA 5-point Assignment Rubric.
Activity 2.06a.2 — Date Formatting Challenge¶
Overview
The same moment in time can be written many ways. You’ll format the current date and time several ways with DateTimeFormatter, prove that java.time objects are immutable, and catch the most common pattern mistake.
To Do
Add the required block comment header
Create
LocalDateTime now = LocalDateTime.now();Print it in three required formats:
ISO:
DateTimeFormatter.ISO_LOCAL_DATE_TIMEShort:
MM/dd/yyLong:
EEEE, MMMM dd, yyyy HH:mm
Print a fourth format of your own design using at least one pattern letter not used above (for example,
h:mm a 'on' MMM d). Text in single quotes prints literally.Immutability: call
now.plusWeeks(1);without saving it and printnowagain (it won’t change). Then savenow.plusWeeks(1)in a new variable and print that.The trap: print
nowwith the patternmm/dd/yy, then explain the result in a comment
Need help? Oracle’s DateTimeFormatter pattern reference
Sample Output (run at 12:46 PM on October 11, 2026. Yours will show the current date and time.)
ISO format: 2026-10-11T12:46:05.733207985
Short format: 10/11/26
Long format: Sunday, October 11, 2026 12:46
My format: 12:46 PM on Oct 11
After now.plusWeeks(1) (not saved): 10/11/26
One week from now: 10/18/26
Using mm/dd/yy by mistake: 46/11/26
Submission: DateFormats.java. No test cases needed.
Grading: AP CSA 5-point Assignment Rubric.
#############################################################################
2.07 while Loops¶
📌 Standards — 2.07
Standard |
Description |
|---|---|
ICT 5.8 |
Create and use algorithms and solve problems |
ICT 5.9 |
Deconstruct large problems into components |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Write
whileloops that repeat code while a condition is true.Trace a loop with a trace table and predict its output.
Identify loops that run zero times, run forever, or run one time too many or too few.
I will be able to write a program that uses while loops.
Anatomy of a while Loop
You already filled in a while loop in 1.07.2 Magic 8-Ball. Every working while loop has three parts:
int count = 1; // 1. INITIALIZE — set up the loop variable
while (count <= 5) // 2. CONDITION — checked BEFORE every pass
{
System.out.print(count + " ");
count++; // 3. UPDATE — move toward making the condition false
}
System.out.println("Done");
// Output: 1 2 3 4 5 Done
How it runs:
Check the condition. If it’s
false, skip the loop entirely.If it’s
true, run the body once.Go back to step 1.
Trace Tables
A trace table records the variables and the condition on every pass. It’s the most reliable way to answer AP loop questions.
int n = 13;
int steps = 0;
while (n > 1)
{
n = n / 2;
steps++;
}
System.out.println(steps);
Pass |
|
|
|
|---|---|---|---|
1 |
13 > 1 ✅ |
6 |
1 |
2 |
6 > 1 ✅ |
3 |
2 |
3 |
3 > 1 ✅ |
1 |
3 |
— |
1 > 1 ❌ |
stop |
Output: 3
Three Ways Loops Go Wrong
// 1. ZERO ITERATIONS — the condition is false from the start
int x = 10;
while (x < 5)
{
System.out.println("never prints");
}
// 2. INFINITE LOOP — the update is missing (or moves the wrong way)
int y = 1;
while (y <= 5)
{
System.out.println(y); // y never changes: prints 1 forever
}
// 3. OFF BY ONE — runs one time too many or too few
int z = 0;
while (z <= 5) // runs 6 times (0-5) when 5 were intended
{
z++;
}
If your program seems frozen, it’s probably an infinite loop. Stop it, then check the update.
When to Use while
Use while when you don’t know in advance how many times the loop will run:
Sentinel loop: keep going until a special value appears (
"q",-1,"no")Validation loop: keep asking until the input is acceptable
Until a condition is met: keep doubling until the amount passes a target
// Sentinel loop: add numbers until the user types 0
int total = 0;
int num = input.nextInt();
while (num != 0)
{
total += num;
num = input.nextInt(); // read the NEXT value at the end of the body
}
College Board Note: A
returnstatement inside a loop ends the whole method immediately, not just the loop. AP questions use this in search methods: return as soon as you find what you’re looking for, and return the “not found” value after the loop.
/** Returns the first multiple of 7 that is greater than start. */
public static int nextMultipleOf7(int start)
{
int n = start + 1;
while (true)
{
if (n % 7 == 0)
{
return n; // exits the method (and the loop) right away
}
n++;
}
}
Exercise 2.07.A — Trace Table¶
Build a trace table on paper (one row per pass, with columns for the condition, a, and b), then answer the questions.
Exercise 2.07.B — How Many Times?¶
For each loop, decide how many times the body runs, or whether it’s infinite.
Exercise 2.07.C — Write the Method¶
The theme park’s Ride class needs to estimate the wait. Each ride cycle takes cycleMinutes and carries up to seatsPerCycle guests. Write minutesToClear using a while loop (no division).
public class Ride
{
private int seatsPerCycle;
private int cycleMinutes;
public Ride(int seatsPerCycle, int cycleMinutes)
{
this.seatsPerCycle = seatsPerCycle;
this.cycleMinutes = cycleMinutes;
}
/** Returns the minutes needed to give every guest in line a ride.
* Precondition: lineLength >= 0 */
public int minutesToClear(int lineLength)
{
/* your code here */
}
}
For example, with 24 seats and a 4-minute cycle, a line of 50 takes 3 cycles: 12 minutes.
Activity 2.07.1 — Unknown Number of Loops¶
Overview
Some questions can only be answered by repeating a step until something happens: “How many days until…?” or “How many steps until…?” You can’t know the count in advance, which makes these perfect while loops.
By the end of this activity you will be able to:
Write a
whileloop whose number of passes isn’t known in advanceUse a counter to report how many passes happened
Use selection (
if/else) inside a loopTrace a loop with a trace table
Part A — The Doubling Penny
You get one penny on day 1, and the amount doubles every day. On what day does it first reach a target amount?
Part B — The Collatz Sequence
Start with any positive whole number and repeat:
if it’s even, divide it by 2
if it’s odd, multiply by 3 and add 1
Mathematicians believe every starting number eventually reaches 1, but no one has proven it. Count the steps.
To Do
Add the required block comment header and print the run stamp (2.06a) first
Part A: read a target in dollars. Start at
0.01on day 1 and use awhileloop to double the amount until it reaches or passes the target. Print the day and the amount withprintfusing a comma separator (%,.2f).Part B: read a starting number and use a
whileloop that runs until the number is 1, usingif/elsefor the even and odd rules. Build the path as a String (6 -> 3 -> 10 ...) and count the steps.On paper (or in a comment), make a trace table for Part B starting at 6
Test Part B with at least three starting numbers, including 1 and 27
Sample Output
Run: 10/11/2026 01:15 PM
Target amount in dollars: 1000000
A doubling penny passes $1,000,000.00 on day 28 with $1,342,177.28.
Starting number for Collatz: 6
6 -> 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
Reached 1 in 8 steps.
Try 27. It takes 111 steps and climbs as high as 9232 before falling back to 1.
Think About It (comment at the bottom)
What does your Collatz loop do when the starting number is 1? Is that correct?
Part A’s loop condition is
amount < target. What changes if you writeamount <= target?What would happen in Part B if a user entered 0? Add a validation loop that prevents it.
Submission
UnknownLoops.javawith block comment headerYour Part B trace table for 6
Test Cases document: Part A with targets 1, 100, and 1000000; Part B with 1, 6, 7, and 27
Grading: AP CSA 5-point Assignment Rubric.
Activity 2.07.2 — Factors, Digits, and Sums¶
Overview
Three while-loop algorithms, each a different loop pattern:
Is a Factor? repeats until a value runs out (repeated subtraction)
Extract Digits peels off one digit per pass (a 2.09 standard algorithm)
Sum and Average keeps reading until a sentinel value appears
By the end of this activity you will be able to:
Replace division with a repeated-subtraction loop
Use
% 10and/ 10to take apart an integer digit by digitWrite a sentinel-controlled input loop
Guard against bad input that would cause an infinite loop or a divide-by-zero
To Do
Add the required block comment header and print the run stamp (2.06a) first
Program 1 — Is a Factor? Write
public static boolean isFactor(int number, int divisor)that decides whetherdivisordividesnumberevenly without using%or/. Hint: keep subtracting the divisor; what’s left at the end tells you the answer.In
main, reject a divisor of 0 or less before callingisFactor. In a comment, explain why a divisor of 0 would make your loop run forever.
Program 2 — Extract Digits. Write
public static void extractDigits(int num)that prints each digit on its own line, last digit first, using awhileloop with% 10and/ 10. Make sureextractDigits(0)prints0.Program 3 — Sum and Average. Read entries with
next()until the user typesqorQ. Convert each number withInteger.parseInt(1.17), then print the sum and the average as adouble. If the user typesqright away, printNo numbers were entered.instead of dividing by zero.
Sample Output
Run: 10/11/2026 01:15 PM
Enter the number:
104
Enter the divisor:
13
13 is a factor of 104
Enter a positive integer:
54321
1
2
3
4
5
Enter a number, or the letter 'q' to end the sequence:
25
Enter a number, or the letter 'q' to end the sequence:
78
Enter a number, or the letter 'q' to end the sequence:
16
Enter a number, or the letter 'q' to end the sequence:
14
Enter a number, or the letter 'q' to end the sequence:
q
The sum is: 133
The average is: 33.25
Enter the number:
52
Enter the divisor:
3
3 is not a factor of 52
Think About It (comment at the bottom)
How many times does the
isFactorloop run forisFactor(104, 13)? ForisFactor(1000000, 1)? What does that tell you about this algorithm compared to using%?How would you print the digits first to last instead (5, 4, 3, 2, 1 for 54321)? What makes that harder?
Why does Program 3 read the first entry before the loop and the next entry at the bottom of the loop?
Submission
WhileAlgorithms.javawith block comment headerTest Cases document: a factor and a non-factor, divisor 0, number 0;
extractDigitsof 54321, 7, and 0; Sum and Average with several numbers and withqfirst
Grading: AP CSA 5-point Assignment Rubric.
Check for Understanding¶
#############################################################################
2.07a do-while Loops, break, and continue — Oracle Foundations 1Z0-811¶
📌 Standards — 2.07a
Standard |
Description |
|---|---|
ICT 5.8 |
Create and use algorithms and solve problems |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Oracle Exam Note:
do-while,break, andcontinueare tested on Oracle 1Z0-811. None of them are part of the AP Java subset. You may use them on AP free-response questions, but no AP question requires them.
Write a
do-whileloop and explain when its body runs.Use a
do-whileloop for input validation.Trace loops that use
breakandcontinue.
The do-while Loop
A do-while checks its condition after the body, so the body always runs at least once.
do
{
// body: always runs at least once
} while (condition); // ← note the semicolon
Scanner input = new Scanner(System.in);
int number;
do
{
System.out.print("Enter a positive number: ");
number = input.nextInt();
} while (number <= 0); // checked AFTER the body
System.out.println("You entered " + number);
That’s the classic use: validation. You have to ask at least once before there’s anything to check.
while vs. do-while
int i = 10;
while (i < 5) // false right away: body runs 0 times
{
System.out.println("while: " + i);
}
int j = 10;
do
{
System.out.println("do-while: " + j); // runs once, prints "do-while: 10"
} while (j < 5);
Oracle Exam Note: Two traps to watch for: forgetting the semicolon after
while (condition)is a compile error in ado-while, and a variable declared inside thedo { }block can’t be used in thewhile (...)condition, because it’s out of scope.
break and continue
breakexits the loop immediately. Code after the loop runs next.continueskips the rest of this pass and goes straight to the next condition check.
// break: stop at the first multiple of 7
int n = 50;
while (n < 100)
{
if (n % 7 == 0)
{
System.out.println("Found " + n); // Found 56
break;
}
n++;
}
// continue: print 1-10 but skip multiples of 3
int k = 0;
while (k < 10)
{
k++; // update BEFORE continue
if (k % 3 == 0)
{
continue;
}
System.out.print(k + " "); // 1 2 4 5 7 8 10
}
Oracle Exam Note: In a
whileloop, ifcontinuecomes before the update, the update is skipped and the loop can run forever. (In aforloop,continuestill runs the update in the header.) When loops are nested (2.11),breakexits only the innermost loop.
Writing Loops Without break or continue
Anything break and continue do, a condition and an if can do. This is the style AP expects:
// Instead of break: put the stopping reason in the condition
boolean found = false;
int m = 50;
while (m < 100 && !found)
{
if (m % 7 == 0)
{
found = true;
}
else
{
m++;
}
}
Activity 2.07a.1 — Guessing Game¶
Overview
The computer picks a secret number from 1 to 100, and the player guesses until they get it. A guessing game is the classic do-while situation: the player must guess at least once before there’s anything to check. You’ll give “hot/cold” hints, count the guesses, and use the Date/Time API to report how long the player took.
By the end of this activity you will be able to:
Use a
do-whileloop when the body must run at least onceCombine a loop with an
if / else if / elsechain for feedbackMeasure elapsed time with
LocalDateTimeandDuration(2.06a)Use a seeded
Randomso a random program can be tested
Hint Table
Distance from the secret |
Hint |
|---|---|
0 |
|
1–3 |
|
4–10 |
|
11–25 |
|
more than 25 |
|
Every wrong guess also says Go higher. or Go lower.
To Do
Add the required block comment header
Print the run stamp (2.06a) first. Save the
LocalDateTimein a variable namedstart, because you’ll need it again at the end.Declare
private static final boolean TEST_MODEand aSEED. In test mode, createnew Random(SEED)and print the secret number so you can test.Use a
do-whileloop that repeats while the guess is not the secretInside the loop:
a guess below 1 or above 100 prints
Out of range! Pick 1 to 100.and does not count as a tryotherwise count the try, compute the distance with
Math.abs, and print the hint and direction
After the loop, use
Duration.between(start, LocalDateTime.now())to print the number of seconds taken, along with the number of tries. Use a ternary so 1 try isn’t printed as “1 tries”.Set
TEST_MODEtofalsebefore you submit
Sample Output (test mode, seed 4. Your run stamp and the number of seconds will differ.)
Run: 10/11/2026 01:03 PM
I'm thinking of a number from 1 to 100.
[TEST MODE] secret = 63
Your guess: 150
Out of range! Pick 1 to 100.
Your guess: 50
Cool. Go higher.
Your guess: 75
Cool. Go lower.
Your guess: 61
Burning hot! Go higher.
Your guess: 63
Correct!
Congratulations! You found 63 in 4 tries and 12 seconds.
Think About It (comment at the bottom)
Why is a
do-whilea better fit here than awhileloop? What would you have to do before awhileloop to make it work?Write your loop’s condition, then use De Morgan’s thinking to state exactly when the loop stops.
What’s the greatest number of guesses a perfect strategy needs to find any number from 1 to 100? (Hint: each guess can cut the range in half.)
Submission
GuessingGame.javawith block comment header (TEST_MODEset tofalse)Test Cases document (made in test mode): a win on the first guess, an out-of-range guess, and each hint level at least once
Grading: AP CSA 5-point Assignment Rubric.
Activity 2.07a.2 — Age/Name¶
Overview
do-while is the standard tool for input validation: ask, check, and ask again until the answer is acceptable. You’ll validate a name and an age, then use the Date/Time API to estimate the user’s birth year.
By the end of this activity you will be able to:
Write a
do-whileloop that re-prompts until input is validWrite validation conditions using String length and a numeric range
Use
LocalDate.now().getYear()in a calculation (2.06a)
To Do
Add the required block comment header and print the run stamp (2.06a) first
Write a
do-whilethat asks for the user’s first name until it is at least 4 characters long (ignore extra spaces with.trim()). Print an error message when it’s too short.Write a second
do-whilethat asks for the user’s age until it is between 18 and 65, inclusive (nextInt()). Print an error message when it’s out of range.Print
[name] is [age] years old.Use
LocalDate.now().getYear()to print the two possible birth years (it depends on whether their birthday has happened yet this year)Use made-up ages for testing. You don’t need your own.
Sample Output
Run: 10/11/2026 01:03 PM
What is your first name?
Kai
Your name needs to be at least 4 characters long.
What is your first name?
Kaiden
What is your current age?
70
Age must be between 18 and 65.
What is your current age?
50
Kaiden is 50 years old.
Kaiden was born in 1976 or 1975.
Think About It (comment at the bottom)
The age condition is
age < 18 || age > 65. Write the valid-age condition, then show how De Morgan’s Laws connect the two.Why do you only know the birth year to within one year?
What happens if the user types
fiftyinstead of50? (Try it. You’ll learn to handle this with exceptions in Unit 3.)
Submission
AgeName.javawith block comment headerTest Cases document: a name that is exactly 3 characters, then exactly 4; ages 17, 18, 65, and 66
Grading: AP CSA 5-point Assignment Rubric.
Activity 2.07a.3 — char — Oracle¶
Overview
Oracle expects you to work comfortably with the char type: comparing characters, converting case, and using them in a switch. You’ll validate that the user typed exactly one letter, then classify it as a vowel or consonant with a switch that uses intentional fall-through (2.04a).
Oracle Exam Note: A
charis stored as a number (its Unicode value), so'a' < 'b'works and'a' + 1is98. Aswitchcan usecharcases, and grouping several cases with nobreakbetween them is a common Oracle pattern.
By the end of this activity you will be able to:
Get a
charfrom aStringwithcharAt(0)and convert its caseTest whether a
charis a letter with a range checkUse a
do-whileto validate inputGroup
switchcases with fall-through
To Do
Add the required block comment header and print the run stamp (2.06a) first
Use a
do-whileto read a line until the user types exactly one character that is a letter. PrintPlease type exactly one character.orThat character is not a letter.as appropriate.Convert the letter to lowercase with
Character.toLowerCase(...)before testing itCheck “is a letter” with a range:
ch >= 'a' && ch <= 'z'Use a
switchon thechar: group'a','e','i','o', and'u'with fall-through to printis a vowel., and usedefaultforis a consonant.Print the letter exactly as the user typed it (so
E is a vowel.keeps the capital)
Starter Code
import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
System.out.println("Enter a letter");
String str = sc.nextLine();
}
}
Sample Output
Run: 10/11/2026 01:03 PM
Enter a letter
bat
Please type exactly one character.
Enter a letter
7
That character is not a letter.
Enter a letter
b
b is a consonant.
Think About It (comment at the bottom)
What does
System.out.println('a' + 1);print, and why isn’t itb?Your
switchcases for the vowels have nobreakbetween them. Explain why that’s correct here.Should
ybe a vowel? How would you change yourswitchif your teacher said yes?
Submission
Main.javawith block comment headerTest Cases document: a vowel, a consonant, an uppercase vowel, a digit, an empty line, and a multi-character entry
Grading: AP CSA 5-point Assignment Rubric.
Activity 2.07a.4 — Break & Continue — Oracle¶
Overview
break exits a loop immediately. continue skips the rest of the current iteration and jumps to the next one. Both are tested on Oracle 1Z0-811 but are not in the AP Java subset, so in Part C you’ll prove that every program can be written without them.
By the end of this activity you will be able to:
Use
continueto skip certain iterationsUse
breakto stop a loop early, and check afterward why it stoppedExplain the infinite-loop trap when
continueskips awhileloop’s updateRewrite a loop without
breakorcontinue
To Do
Add the required block comment header and print the run stamp (2.06a) first
Part A — continue: read
n, then use awhileloop to add the numbers from 1 ton, usingcontinueto skip multiples of 3. Print each number added and the final sum.Increment your counter at the top of the loop body. In a comment, explain what would happen if the increment were at the bottom, after the
continue.
Part B — break: build a vault that allows up to 4 attempts to enter the code
4721. Use awhileloop andbreakout as soon as the code is right. After the loop, printVault unlocked after X tries!orLOCKED OUT.Use abooleanto remember which happened.Part C — no break, no continue: rewrite Part A as a second
whileloop with anifinstead ofcontinue, and print its sum. In a comment, write thewhilecondition that would let Part B work withoutbreak.
Sample Output
Run: 10/11/2026 01:03 PM
Add the numbers from 1 to: 10
Added: 1 2 4 5 7 8 10
Sum without multiples of 3: 37
=== VAULT ===
Enter code (4 left): 1111
Wrong code.
Enter code (3 left): 4721
Vault unlocked after 2 tries!
Part C sum (no continue): 37
Think About It (comment at the bottom)
After the vault loop ends, why can’t you tell whether the user succeeded just from
tries?Which version of Part A do you find easier to read, the one with
continueor the one without? Why?Predict the output, then check it:
int i = 0;
while (i < 5)
{
i++;
if (i == 2) continue;
if (i == 4) break;
System.out.print(i + " ");
}
Submission
BreakContinue.javawith block comment headerTest Cases document: Part A with
n= 1, 3, and 10; Part B unlocked on try 1, unlocked on try 4, and locked out
Grading: AP CSA 5-point Assignment Rubric.
Check for Understanding¶
#############################################################################
2.08 for Loops¶
📌 Standards — 2.08
Standard |
Description |
|---|---|
ICT 5.8 |
Create and use algorithms and solve problems |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Write
forloops for counter-controlled repetition.Determine exactly how many times a
forloop runs.Rewrite a
forloop as an equivalentwhileloop, and back.
One Line, Three Parts
A for loop puts all three parts of a counting loop in its header:
// initialize condition update
for (int i = 0; i < 5; i++)
{
System.out.print(i + " "); // 0 1 2 3 4
}
Order of execution:
Initialize runs once, before anything else.
Check the condition. If it’s
false, the loop ends.Run the body.
Run the update, then go back to step 2.
Every for Loop Is a while Loop
for (int i = 1; i <= 3; i++)
{
System.out.println(i);
}
int i = 1;
while (i <= 3)
{
System.out.println(i);
i++;
}
Same output. The difference is where the parts live, and the scope of i.
Counting Patterns
Goal |
Header |
Runs |
|---|---|---|
0 up to n − 1 |
|
|
1 up to n |
|
|
n down to 1 |
|
|
Even numbers 0–20 |
|
11 times |
Each index of a String |
|
|
Counting iterations: for for (int i = a; i < b; i++) the loop runs b - a times. With <=, it’s b - a + 1.
IMPORTANT: off-by-one error¶
The most common loop mistake is running one time too many or too few:
// WRONG: runs 6 times (0-5) when you want 5 iterations
for (int i = 0; i <= 5; i++) { ... }
// CORRECT: runs 5 times (0-4)
for (int i = 0; i < 5; i++) { ... }
Check the first value and the last value the loop variable takes. That’s where off-by-one errors hide.
Loop Variable Scope
A variable declared in the for header exists only inside the loop:
for (int i = 0; i < 3; i++)
{
System.out.println(i);
}
// System.out.println(i); // COMPILE ERROR — i is out of scope
If you need the value afterward, declare the variable before the loop.
Oracle Exam Note: Oracle tests scope with
forheaders, and also these legal-but-unusual forms: several variables in one header (for (int i = 0, j = 10; i < j; i++, j--)), and empty parts (for (;;)is an infinite loop).
Best practice: Don’t change the loop variable inside the body of a
forloop. It compiles, but it makes the number of iterations hard to predict. Exam questions sometimes do it on purpose to test your tracing.
Exercise 2.08.A — Count the Iterations¶
How many times does each loop body run?
Exercise 2.08.B — while ↔ for¶
Rewrite each loop in the other form. Each pair must print the same output.
Part 1. Rewrite this while loop as a for loop:
int n = 100;
while (n > 1)
{
System.out.print(n + " ");
n = n / 2;
}
Part 2. Rewrite this for loop as a while loop:
for (int t = 10; t >= 0; t -= 5)
{
System.out.print(t + " ");
}
Exercise 2.08.C — Write the Method¶
Remember the private repeat helper inside the Cake class from 1.14.3? Now you can write it yourself.
/** Returns text repeated times times, joined together.
* repeat("ab", 3) returns "ababab"; repeat("x", 0) returns "".
* Precondition: times >= 0 */
public static String repeat(String text, int times)
{
/* your code here */
}
Activity 2.08.1 — Launch Sequence: for Loop Basics¶
Overview
Mission Control (remember 1.10.1?) needs a launch sequence program. Each stage of the launch is a different kind of for loop: counting up by a step, adding up a total, counting matches, and counting down. Choosing the right start, condition, and update for each loop is the whole skill.
By the end of this activity you will be able to:
Write
forloops that count up, count down, and count by stepsUse an accumulator to add up values inside a loop
Use an
ifinside a loop to count values that meet a conditionAvoid off-by-one errors by testing the first and last values
To Do
Add the required block comment header and print the run stamp (2.06a) first
Part A — Fuel Loading: one
forloop printsFuel at 0%throughFuel at 100%in steps of 20. The update must befuel += 20, notfuel++.Part B — Systems Check: read
nand use aforloop to add 1 + 2 + … + n. Print the total.Part C — Signal Scan: read
kand use aforloop from 1 to 100 with anifinside that counts how many numbers are multiples ofk(2.09 preview)Part D — Countdown: read a starting number and count down to 1 on one line, then print
LIFTOFF!Above each loop, add a comment stating exactly how many times the loop body runs (use the sample inputs)
Sample Output
=== MISSION CONTROL: LAUNCH SEQUENCE ===
-- Fuel Loading --
Fuel at 0%
Fuel at 20%
Fuel at 40%
Fuel at 60%
Fuel at 80%
Fuel at 100%
Number of systems to check: 5
-- Systems Check --
Check codes 1 through 5 add up to 15
Signal frequency to scan for: 7
-- Signal Scan --
Signals on multiples of 7 from 1 to 100: 14
Countdown from: 10
-- Countdown --
10... 9... 8... 7... 6... 5... 4... 3... 2... 1... LIFTOFF!
Think About It (comment at the bottom)
Part A runs 6 times, not 5. Why?
Part C could loop through only the multiples of
kinstead of all 100 numbers. Write that loop header. How many times does it run whenkis 7?What happens in Part D if you write the condition as
t > 1? Ast >= 0?
Submission
LaunchSequence.javawith block comment header and loop-count commentsTest Cases document: Part B with
n= 1 andn= 100; Part C withk= 1, 7, and 100; Part D starting from 1 and from 10
Grading: AP CSA 5-point Assignment Rubric.
Activity 2.08.2 — Factorial X¶
Overview
Two classic for-loop programs: an accumulator that multiplies (factorial) and a counter that prints a table (multiples). Factorial values grow so fast that they also test what you learned about data type ranges in 1.05.
By the end of this activity you will be able to:
Use a
forloop to multiply values into a running productChoose a data type large enough for the result
Validate input before running a loop
Use the loop variable inside the loop body to build output
Background
The factorial of n, written n!, multiplies n by every positive integer below it:
4! = 4 × 3 × 2 × 1 = 24
0! = 1 (defined that way)
To Do
Program 1 — Factorial.java
Add the required block comment header and print the run stamp (2.06a) first
Read a number. If it is less than 0 or greater than 19, print
Invalid input! Please enter a number between 0 and 19.and do not calculate.Otherwise, use a
forloop to compute the factorial and printFactorial of n is: resultStore the product in a
long. Starting the product at1makes0!come out right automatically.In a comment, explain what goes wrong if the product is an
int(try13!to find out)
Program 2 — TimesTable.java
Add the required block comment header and print the run stamp (2.06a) first
Read an integer and how many multiples to display
Use a
forloop to print each line in the form4 * 3 = 12
Sample Output — Program 1 (four separate runs)
Enter a number (0-19): 5
Factorial of 5 is: 120
Enter a number (0-19): 10
Factorial of 10 is: 3628800
Enter a number (0-19): 25
Invalid input! Please enter a number between 0 and 19.
Enter a number (0-19): -3
Invalid input! Please enter a number between 0 and 19.
Sample Output — Program 2
Enter an integer:
4
Enter the number of multiples:
10
4 * 1 = 4
4 * 2 = 8
4 * 3 = 12
4 * 4 = 16
4 * 5 = 20
4 * 6 = 24
4 * 7 = 28
4 * 8 = 32
4 * 9 = 36
4 * 10 = 40
Think About It (comment at the bottom of Factorial.java)
What is
19!? Find out how large alongcan be (Long.MAX_VALUE). Is20!still safe? What about21!?Your loop can start at
i = 2instead ofi = 1. Why doesn’t that change the answer?How many times does the loop body run for
n = 10? Write the count in terms ofn.
Submission
Factorial.javaandTimesTable.javawith block comment headersTest Cases document: factorial of 0, 1, 5, 19, -1, and 20; times table with 0 multiples and with a negative number
Grading: AP CSA 5-point Assignment Rubric.
Activity 2.08.3 — Allowance Savings Plan¶
Overview
Back in 1.02.1 you decided who gets an allowance. Now you’ll plan how to save it. Your program prints a week-by-week savings table, adds a parent “match” bonus every fourth week, and reports when (or whether) a savings goal is reached. In Part B, you’ll prove that a while loop and a for loop can do the same job.
By the end of this activity you will be able to:
Use a
forloop to build a formatted table, one row per iterationUse
%inside a loop to act on every nth iterationRecord the first iteration where a condition becomes true
Rewrite a
whileloop as an equivalentforloop
Rules
Each week, the saver deposits a chosen percent of their weekly allowance.
Every 4th week (weeks 4, 8, 12, …), parents add a $5.00 bonus.
The program reports the first week the balance reaches the goal, or how far short it is.
To Do
Part A — Savings Table
Add the required block comment header and print the run stamp (2.06a) first
Read the weekly allowance (
double), percent to save (int), number of weeks (int), and savings goal (double)Declare
final double BONUS = 5.00;Use a
forloop from week 1 to the last week. Each iteration computes the deposit, uses a ternary withweek % 4 == 0for the bonus, updates the balance, and prints one aligned row withprintf.Before the loop, declare
int goalWeek = -1;(meaning “not reached yet”). Inside the loop, record the week only the first time the balance reaches the goal. (Hint: two conditions joined with&&.)After the loop, print the goal message or how much is still needed
Part B — while to for
Copy this
whileloop into your program, then write aforloop that prints exactly the same output:
int count = 3;
while (count <= 30)
{
System.out.print(count + " ");
count += 3;
}
Sample Output
Weekly allowance: $20
Percent to save each week: 25
Number of weeks: 8
Savings goal: $30
Week Deposit Bonus Balance
1 5.00 0.00 5.00
2 5.00 0.00 10.00
3 5.00 0.00 15.00
4 5.00 5.00 25.00
5 5.00 0.00 30.00
6 5.00 0.00 35.00
7 5.00 0.00 40.00
8 5.00 5.00 50.00
Goal of $30.00 reached in week 5!
while version: 3 6 9 12 15 18 21 24 27 30
for version: 3 6 9 12 15 18 21 24 27 30
When the goal isn’t reached (allowance \(10, 10%, 6 weeks, goal \)50), the last line of Part A is:
Goal not reached. You are $39.00 short.
Think About It (comment at the bottom)
Why does
goalWeekneed the extra checkgoalWeek == -1? What would it hold at the end without it?In Part B, where did each of the three parts of the
whileloop (start, condition, update) go in yourforheader?Why is
-1a safe “not reached” value for a week number?
Submission
SavingsPlan.javawith block comment headerTest Cases document: goal reached early, goal reached exactly on a bonus week, goal never reached, and 0 weeks
Grading: AP CSA 5-point Assignment Rubric.
#############################################################################
Check for Understanding¶
#############################################################################
2.08a Comparing Loops — Oracle Foundations 1Z0-811¶
📌 Standards — 2.08a
Standard |
Description |
|---|---|
ICT 5.4 |
Interpret information and draw conclusions to make informed decisions |
ICT 5.8 |
Create and use algorithms and solve problems |
ICT 10.1 |
Interpret and explain ICT-specific terminology |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Oracle Exam Note: “Compare and contrast the
for,while, anddo-whileloops” is a direct objective on Oracle 1Z0-811. You’ve now seen all three individually (2.07, 2.07a, 2.08). This section puts them side by side.
Explain when each loop checks its condition.
Choose the best loop for a situation and justify the choice.
Convert between loop types without changing the behavior.
All three loops repeat code. They differ in when the condition is checked and when you’d choose one over another.
|
|
|
|
|---|---|---|---|
Condition checked |
Before each iteration |
After each iteration |
Before each iteration |
Guarantees at least 1 run? |
No |
Yes |
No |
Best used when… |
The number of iterations is unknown and depends on a condition |
The body must run at least once (menus, input validation) |
The number of iterations is known or counter-based |
Counter handled where? |
Declared and updated separately |
Declared and updated separately |
Declared, checked, and updated in the header |
Semicolon after the condition? |
No |
Yes: |
No |
// while — condition checked FIRST; may run zero times
int i = 10;
while (i < 5)
{
System.out.println(i); // never runs; i starts at 10
}
// do-while — condition checked LAST; runs at least once
int j = 10;
do
{
System.out.println(j); // runs once, prints 10
} while (j < 5);
// for — best when you know exactly how many times to repeat
for (int k = 0; k < 5; k++)
{
System.out.println(k); // runs exactly 5 times
}
Oracle Exam Note: A common trap: given a
do-whilewhose condition is false from the start, students assume the body never runs. Ado-whilealways runs its body at least once, no matter what the condition is.
Activity 2.08a.1 — Which Loop?¶
For each scenario, name the best loop (for, while, or do-while) and explain why in one sentence.
Printing the numbers 1 through 20.
Repeatedly asking the user for a password until they enter the correct one.
Reading lines from a file until there are no more lines to read.
Displaying a menu at least once, then repeating it if the user enters an invalid choice.
Doubling a savings balance until it passes $1,000.
Processing every character of a String.
Sample Answers
for— the count (20) is known in advance.do-while— the user must be asked at least once before there’s anything to check. (Awhilewith a first prompt before the loop also works.)while— the number of lines is unknown, and the file might be empty (zero iterations).do-while— the menu must display at least once.while— the number of doublings isn’t known in advance.for— the length of the String gives the exact count:for (int i = 0; i < str.length(); i++).
################################################################
Activity 2.08a.2 — Convert Program: for to do-while¶
Overview
This activity goes with the loop comparison in 2.08a. Any for loop can be rewritten as a do-while, but there’s a catch. A for loop can run zero times, while a do-while always runs at least once. You’ll convert two programs and discover what goes wrong when the loop shouldn’t run at all.
By the end of this activity you will be able to:
Rewrite a
forloop as ado-whileloopIdentify inputs where a
do-whileruns when it shouldn’tGuard a
do-whilewith anifUse a
do-whilefor input validation
The Original Programs
// Program A: counts how many times "aaa" appears (overlaps count)
String pattern = "aaa";
int howMany = 0;
for (int i = 0; i < input.length() - pattern.length() + 1; i++)
{
String currSeq = input.substring(i, i + pattern.length());
if (currSeq.equals(pattern))
{
howMany++;
}
}
System.out.println("There were " + howMany + " substrings matching " + pattern);
// Program B: prints the input backward
String output = "";
for (int i = input.length(); i > 0; i--)
{
output += input.substring(i - 1, i);
}
System.out.println(output);
To Do
Add the required block comment header and print the run stamp (2.06a) first
Put both programs in one file, one after the other, using one
ScannerConvert: rewrite each
forloop as ado-while. Move the start before the loop, the update to the end of the body, and the condition intowhile (...).Break it on purpose: run Program B with an empty input (just press Enter). Screenshot the
StringIndexOutOfBoundsException, and explain in a comment why theforversion didn’t crash.Fix it: wrap each
do-whilein anifthat only lets it run when it should. Program B needs at least one character; Program A needs at least as many characters as the pattern.Validate: Program A’s prompt asks for at least 3 characters, but nothing enforces it. Add a
do-whilethat re-prompts until the input is long enough.
Sample Output
Run: 10/11/2026 01:03 PM
Enter a String with at least 3 characters:
ab
Enter a String with at least 3 characters:
baaaaab
There were 3 substrings matching aaa
Enter a String:
stressed
desserts
Think About It (comment at the bottom)
"baaaaab"contains five a’s in a row. Why does Program A count 3 matches?After adding the input-validation loop in Program A, is the
ifguard still needed? Explain.Which loop type would you choose for each program, and why?
Submission
ConvertPrograms.javawith block comment headerScreenshot of the Program B crash before your fix
No Test Cases document needed.
Grading: AP CSA 5-point Assignment Rubric.
#############
2.09 Implementing Selection and Iteration Algorithms¶
📌 Standards — 2.09
Standard |
Description |
|---|---|
ICT 5.8 |
Create and use algorithms and solve problems |
ICT 5.9 |
Deconstruct large problems into components |
ICT 7.5 |
Apply high-quality techniques to product design and development |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Recognize and write the standard algorithms that combine loops and conditionals.
Choose a correct starting value for sums, counts, minimums, and maximums.
Combine standard algorithms to solve a new problem.
College Board Note: The AP CED lists these as standard algorithms you should be able to write and recognize: determining whether an integer is evenly divisible by another, extracting digits, counting how often a condition is met, finding a minimum or maximum, and computing a sum or average. FRQ 1 almost always asks for one or more of them.
The Standard Algorithms
You’ve already used several of these. Here they are side by side.
1. Divisibility — x % d == 0 means d divides x evenly (2.09.1 Smallest Divisible).
int count = 0;
for (int x = 1; x <= 100; x++)
{
if (x % 6 == 0)
{
count++; // how many numbers from 1-100 are divisible by 6? 16
}
}
2. Digit extraction — % 10 gives the last digit, and / 10 removes it (2.07.2).
int num = 3074;
while (num > 0)
{
int digit = num % 10; // 4, then 7, then 0, then 3
num = num / 10;
}
3. Frequency count — count how many values meet a condition (Sevens face counts, the Signal Scan in 2.08.1).
int evens = 0;
for (int i = 1; i <= 10; i++)
{
int roll = (int) (Math.random() * 6) + 1;
if (roll % 2 == 0)
{
evens++;
}
}
4. Minimum / maximum — keep a “best so far” and replace it when a better value appears (1.17.1 High Score Tracker).
int max = Integer.MIN_VALUE; // start at the WORST possible value
int count = 0;
int value = input.nextInt();
while (value != -1)
{
if (value > max)
{
max = value;
}
count++;
value = input.nextInt();
}
5. Sum and average — add with an accumulator, count the values, and divide as a double, but only if the count isn’t 0.
double average = (count > 0) ? (double) sum / count : 0.0;
Starting Values Matter
Algorithm |
Start at |
Why |
|---|---|---|
Sum |
|
Adding 0 changes nothing |
Product |
|
Multiplying by 1 changes nothing (2.08.2 Factorial) |
Count |
|
Nothing counted yet |
Maximum |
|
Any real value replaces it |
Minimum |
|
Any real value replaces it |
Starting a maximum at
0is a classic bug: if every value is negative, the “maximum” comes out as 0, a value that was never entered.
Exercise 2.09.A — Trace It¶
Trace the digits from last to first.
Exercise 2.09.B — Write the Method¶
This is a classic FRQ 1 style method. Write countEvenDigits.
/** Returns the number of even digits in num.
* countEvenDigits(24681) returns 4; countEvenDigits(135) returns 0.
* Precondition: num > 0 */
public static int countEvenDigits(int num)
{
/* your code here */
}
Exercise 2.09.C — Write the Method¶
Write isPrime. A prime number is greater than 1 and has no divisors other than 1 and itself.
/** Returns true if n is prime. isPrime(13) is true; isPrime(1) and isPrime(15) are false. */
public static boolean isPrime(int n)
{
/* your code here */
}
Activity 2.09.1 — Smallest Divisible Number¶
Overview
What is the smallest positive number that every whole number from 1 to 10 divides evenly? There’s no formula to plug into, but a computer can search for it: try a number, test it, and move to the next one until a number passes every test. This is one of the standard algorithms on the AP exam, testing divisibility with % inside a loop.
By the end of this activity you will be able to:
Use
%to test whether one number divides another evenlyWrite a search loop that stops when a compound condition is satisfied
Rewrite a loop condition with De Morgan’s Laws (2.06)
Measure how much work an algorithm does by counting iterations (2.12)
Background
“Evenly divides” means no remainder. x % d == 0 is true exactly when d divides x evenly.
System.out.println(12 % 4 == 0); // true — 12 / 4 = 3, remainder 0
System.out.println(12 % 5 == 0); // false — 12 / 5 = 2, remainder 2
A number is divisible by all of 1–10 when every test is true, so the tests are joined with &&:
num % 2 == 0 && num % 3 == 0 && num % 4 == 0 && ... && num % 10 == 0
Why is
num % 1 == 0missing? Every whole number is divisible by 1, so that test is alwaystrueand adds nothing.
The search algorithm in plain English:
num ← 1
WHILE num is NOT divisible by all of 2-10
num ← num + 1
DISPLAY num
To Do
Part A — Brute Force
Add the required block comment header and print the run stamp (2.06a) first
Start
numat1and use awhileloop that keeps going whilenumis not divisible by all of 2–10. Write it as!( ... && ... ).Count how many numbers you checked with a
checkscounterPrint the answer and the count
Part B — Work Smarter
The answer must be divisible by 10, so only multiples of 10 can possibly work. Start a new search at
10and add10each time.Multiples of 10 already pass the tests for 1, 2, 5, and 10, so only check the divisors that are left
Rewrite the loop condition without
!using De Morgan’s Laws: “keep going while any test fails” (||with!=)Count the checks again and print both counts
Part C — Think About It (comment at the bottom)
Part B checks far fewer numbers than Part A. About how many times fewer, and why?
If a number is divisible by 8 and 9, which other divisors from 2–10 are automatically covered?
Using De Morgan’s Laws, show that
!(a == 0 && b == 0)is the same asa != 0 || b != 0.
Starter Code — SmallestDivisible.java
public class SmallestDivisible
{
public static void main(String[] args)
{
// ---------- Part A: brute force ----------
int num = 1;
int checks = 1;
// TODO: while num is NOT divisible by every number from 2 to 10
// (write the condition as !( ... && ... ) )
// num++ and checks++
System.out.println("Part A: smallest number divisible by 1-10 is " + num);
System.out.println("Numbers checked: " + checks);
// ---------- Part B: only multiples of 10 ----------
int candidate = 10;
int checksB = 1;
// TODO: while ANY remaining test fails (use || and !=, no !)
// candidate += 10 and checksB++
System.out.println("Part B: " + candidate + " after checking " + checksB + " numbers");
}
}
Sample Output
Part A: smallest number divisible by 1-10 is 2520
Numbers checked: 2520
Part B: 2520 after checking 252 numbers
Extension
Find the smallest number divisible by every number from 1 to
nfor anynthe user enters. Writing out every test is no longer possible, so use a nested loop: an innerforloop checks divisors 2 throughnand sets abooleanflag tofalseif any divisor fails. Check: forn = 20the answer is232792560.
Submission
SmallestDivisible.javawith block comment headerScreenshot of the output and your Part C answers
Grading: AP CSA 5-point Assignment Rubric. Pay particular attention to:
Part A uses
!( ... && ... ); Part B uses the correct De Morgan form with||and!=The check counters are correct (no off-by-one)
Check for Understanding¶
#############################################################################
2.10 Implementing String Algorithms¶
📌 Standards — 2.10
Standard |
Description |
|---|---|
ICT 5.8 |
Create and use algorithms and solve problems |
ICT 5.9 |
Deconstruct large problems into components |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Traverse a String one character at a time with a loop.
Find, count, and replace substrings.
Build a new String in a loop, including a reversed String.
Avoid
StringIndexOutOfBoundsExceptionat the end of a String.
College Board Note: The AP CED’s standard String algorithms are: finding whether a String contains a substring with a given property, counting substrings that meet a criterion, and creating a new String with the characters reversed. The AP Java Quick Reference gives you
length,substring,indexOf,equals, andcompareTo, but notcharAt. AP solutions pull one character at a time withstr.substring(i, i + 1).
The Traversal Pattern
String word = "banana";
for (int i = 0; i < word.length(); i++)
{
String letter = word.substring(i, i + 1); // one character, as a String
System.out.print(letter + " "); // b a n a n a
}
Indexes run from 0 to length() - 1, so the condition is i < word.length(). substring(i, i + 1) is safe at the last index, because the end index may equal length().
Counting Matches (frequency count on a String)
String text = "Mississippi";
int sCount = 0;
for (int i = 0; i < text.length(); i++)
{
if (text.substring(i, i + 1).equals("s"))
{
sCount++; // 4
}
}
Checking a Set of Characters with indexOf
"aeiou".indexOf(letter) returns -1 when letter isn’t in the set, so one call replaces five comparisons:
if ("aeiouAEIOU".indexOf(letter) >= 0) // letter is a vowel
Searching for a Longer Substring
When the target is longer than one character, stop early so substring doesn’t run past the end:
String dna = "GATTACATTA";
String target = "TTA";
int found = 0;
for (int i = 0; i <= dna.length() - target.length(); i++)
{
if (dna.substring(i, i + target.length()).equals(target))
{
found++; // 2 (at index 2 and index 7)
}
}
Exam Note (AP + Oracle): Running
substring(i, i + 3)all the way toi < dna.length()throws aStringIndexOutOfBoundsExceptionnear the end. The last legal start index for a target of lengthtislength() - t.
Building a New String: Reverse
String original = "stressed";
String reversed = "";
for (int i = original.length() - 1; i >= 0; i--)
{
reversed += original.substring(i, i + 1);
}
System.out.println(reversed); // desserts
Compare this with 1.16.2 Palindrome Checker, where StringBuilder.reverse() did the work for you. Now you know what’s inside.
Replacing as You Build
// Replace every space with an underscore
String phrase = "AP CS A rocks";
String result = "";
for (int i = 0; i < phrase.length(); i++)
{
String ch = phrase.substring(i, i + 1);
result += ch.equals(" ") ? "_" : ch;
}
System.out.println(result); // AP_CS_A_rocks
Exercise 2.10.A — Predict the Output¶
Trace which indexes the loop visits, and notice where each letter is added.
Exercise 2.10.B — Write the Method¶
/** Returns the number of times target appears in str. Overlapping matches count.
* countOccurrences("banana", "ana") returns 2; countOccurrences("aaaa", "aa") returns 3.
* Precondition: target.length() > 0 */
public static int countOccurrences(String str, String target)
{
/* your code here */
}
Exercise 2.10.C — Write the Method¶
/** Returns true if str contains at least one digit character (0-9).
* hasDigit("R2D2") is true; hasDigit("Java") is false. */
public static boolean hasDigit(String str)
{
/* your code here */
}
Activity 2.10.1 — EveryOther, Vowels, dbpq¶
Overview
Three String algorithms, each built the same way: traverse the String one character at a time and build a new String. Write each one as a method that returns the new String, the same shape as an AP free-response method.
College Board Note: The AP Java Quick Reference lists
substring,indexOf,length,equals, andcompareTo, but notcharAt. Get comfortable pulling one character as a String withstr.substring(i, i + 1). That’s what AP solutions use.
By the end of this activity you will be able to:
Traverse a String with a loop and
substring(i, i + 1)Build a result String by concatenating inside a loop
Test whether a character belongs to a set using
indexOfHandle edge cases: an empty String and a one-character String
The Three Methods
1. everyOther(String str) keeps the characters at indexes 0, 2, 4, …
Input |
Output |
|---|---|
|
|
|
|
|
|
|
|
|
|
2. removeVowels(String str) removes upper- and lowercase vowels
Input |
Output |
|---|---|
|
|
|
|
|
|
|
|
|
|
3. scrambleDBPQ(String str) replaces every lowercase d, b, p, or q with a randomly chosen d, b, p, or q. Every other character stays the same.
Input |
One possible output |
|---|---|
|
|
|
|
|
|
To Do
Add the required block comment header and print the run stamp (2.06a) first
Write all three methods as
public static Stringmethods that return the new StringUse
substring(i, i + 1)to get each characterremoveVowels: test each character with"aeiouAEIOU".indexOf(letter)scrambleDBPQ: test each character with"dbpq".indexOf(letter), then pick a random index 0–3 and take that letter from"dbpq"Use a
Randomwith a test-modeSEED(see 2.07a.1) so your scramble output can be repeated for testingIn
main, call each method on every input in its table and print the results, then let the user type their own text and run all three methods on it
Sample Output (test mode, seed 10. Scrambled results depend on your seed.)
Run: 10/11/2026 01:04 PM
=== Program 1: everyOther ===
"abcdefg" -> "aceg"
"HelloWorld" -> "Hlool"
"" -> ""
"A" -> "A"
"123456" -> "135"
=== Program 2: removeVowels ===
"Hello World" -> "Hll Wrld"
"AEIOUaeiou" -> ""
"Programming" -> "Prgrmmng"
"ChatGPT" -> "ChtGPT"
"Beautiful Day" -> "Btfl Dy"
=== Program 3: scrambleDBPQ (test mode, seed 10) ===
"badquip" -> "pabbuib"
"ddbbpq" -> "dpdbqb"
"hello" -> "hello"
Your own text: Bob dipped a pear
everyOther: "Bbdpe er"
removeVowels: "Bb dppd pr"
scrambleDBPQ: "Bob piqqep a bear"
Think About It (comment at the bottom)
Why doesn’t
everyOther("")crash, even though the loop callssubstring?In
scrambleDBPQ("Bob dipped a pear"), the capitalBwasn’t replaced. Why? How would you include capitals?everyOthercan be written by steppingi += 2, or by steppingi++with anif. How many times does each version’s loop run for a String of length 10?
Submission
StringAlgorithms.javawith block comment headerTest Cases document: every row of all three tables (scramble results with your seed), plus one input of your own
Grading: AP CSA 5-point Assignment Rubric.
Activity 2.10.2 — wordCount and vowelCount¶
Overview
Count the words and vowels in a phrase. The starting hint, words = spaces + 1, works for neat input. In Part B you’ll find inputs that break it and write a version that doesn’t break.
By the end of this activity you will be able to:
Count characters that meet a condition while traversing a String (2.09 frequency count)
Find the inputs that break a simple algorithm
Track state across loop iterations with a
booleanvariable
To Do
Add the required block comment header and print the run stamp (2.06a) first
Write
public static int wordCount(String phrase)that counts spaces and returns spaces + 1Write
public static int vowelCount(String phrase)that counts upper- and lowercase vowelsUse
substring(i, i + 1)to examine each characterPart B — Break it: test
wordCountwith an empty String and with" two spaces ". In a comment, record what it returns and why it’s wrong.Part B — Fix it: write
public static int robustWordCount(String phrase). A new word starts wherever a non-space character comes right after a space (or at the very start). Use aboolean inWordto remember whether the previous character was part of a word.
Sample Output
Run: 10/11/2026 01:04 PM
Enter a phrase:
This phrase has eight words and twelve vowels.
Words: 8
Vowels: 12
Words (Part B, robust): 8
When the input is " two spaces ":
Words: 8
Vowels: 3
Words (Part B, robust): 2
Think About It (comment at the bottom)
Why does the spaces + 1 method say an empty String has 1 word?
Your
robustWordCountuses thebooleanto “remember” the previous character. What other algorithm in this unit remembered something from an earlier iteration?Does your
vowelCountcounty? Should it? Defend your choice in one sentence.
Submission
WordVowelCount.javawith block comment headerTest Cases document: the sample phrase, an empty String, a single word, extra spaces, and a phrase with no vowels
Grading: AP CSA 5-point Assignment Rubric.
Check for Understanding¶
#############################################################################
Unit 2 Mini-Project — Mad Libs¶
📌 Standards — Mini-Project
Standard |
Description |
|---|---|
ICT 2.0 |
Communications — communicate clearly in written and electronic formats |
ICT 5.8 |
Create and use algorithms and solve problems |
ICT 5.9 |
Deconstruct large problems into components |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures, procedures, and variables |
C4.11 |
Document development work using comments |
C5.5 |
Implement a solution |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 2 |
Communicate clearly, effectively, and with reason |
CRP 5 |
Utilize critical thinking to make sense of problems |
Write String algorithms that find, process, and replace parts of a text.
Use loops to keep the user on track with clear prompts and validation.
Build a complete, readable story from user input.
I will build a Mad Libs program that writes a different story for every user.
Overview
In a Mad Lib, a story has blanks labeled with a part of speech, like [noun] or [adjective]. The player fills each blank without seeing the story, and the result is usually ridiculous. Your program does the hard part: it finds each blank in the story, asks for the right kind of word, replaces the blank, and assembles the finished story.
Required File: MadLibs.java
Submission: One PDF with your code, sample runs, and test values, plus your .java file
How the Algorithm Works¶
Your story is one String with blanks written in square brackets:
String story = "It was a [adjective] morning when a [noun] wandered into the CS lab. ...";
The core algorithm repeats until no [ remains:
open ← position of "[" in story
WHILE open is not -1
close ← position of "]" after open
partOfSpeech ← the text between open and close
ask the user for a word of that type
story ← (text before "[") + answer + (text after "]")
open ← position of the next "[" in story
Because the story itself shrinks and grows as blanks are replaced, the loop always searches the updated story for the next [.
Requirements¶
Your program must:
Store the incomplete Mad Lib in a
Stringvariable with at least five sentences and at least five blanksDisplay the original story (with its blanks) before asking for any words
Use a
whileloop withindexOfandsubstringto find each blank, read its part of speech, and replace it with the user’s answer. Write this as a method:public static String fillBlanks(String text).Keep the user on track:
each prompt names the part of speech:
Enter a(n) adjective:re-prompt (loop) if the user enters a blank answer
Use numbers: include a
[number]blank. Re-prompt until the answer contains only digits (check each character), convert it withInteger.parseInt, and use it in a calculation that appears in the finished story.Include a section choice: offer at least two different endings (or middle sections). Re-prompt until the choice is valid, use selection to include the chosen section, and fill its blanks with the same
fillBlanksmethod.Fix grammar: change
atoanbefore words that start with a vowel (a iguana→an iguana)Display the completed story with a final print statement
Include a test mode: a
final boolean TEST_MODEthat, whentrue, supplies answers from a String of test values (for example"enormous,iguana,backpack,...") instead of the keyboard, so your program can be tested the same way every time
Sample Output (test mode. Your story and words will be your own.)
Run: 10/11/2026 01:18 PM
=== THE ORIGINAL STORY ===
It was a [adjective] morning at school when a [noun] wandered into the CS lab. It climbed onto a [noun] and refused to leave. Everyone tried to [verb] to scare it away, but nothing worked. Then [name] walked in with a [adjective] grin. "I have practiced this for [number] years," they said.
Enter a(n) adjective: enormous
Enter a(n) noun: iguana
Enter a(n) noun: backpack
Enter a(n) verb: juggle
Enter a(n) name: Mr. Okafor
Enter a(n) adjective: elegant
Enter a whole number: 17
Choose an ending (1 = happy, 2 = mysterious): 2
Enter a(n) noun: octopus
=== YOUR STORY ===
It was an enormous morning at school when an iguana wandered into the CS lab. It climbed onto a backpack and refused to leave. Everyone tried to juggle to scare it away, but nothing worked. Then Mr. Okafor walked in with an elegant grin. "I have practiced this for 17 years," they said. They whispered a secret, and the octopus vanished in a puff of semicolons. That's about 6205 days of practice!
Hints
text.indexOf("]", open)searches for]starting at positionopen.To check “only digits,” loop through the answer and use
"0123456789".indexOf(...), the same technique ashasDigitin 2.10.To read test values one at a time, find the first comma with
indexOf(","), take the text before it, then keep the rest for next time.
Mad Libs Rubric¶
Each concept is worth 1 point, awarded when it is used correctly and meaningfully.
# |
Category |
Concept |
What to Demonstrate |
Pts |
|---|---|---|---|---|
1 |
Structure |
Class and main |
Class name matches the file name; program runs from |
1 |
2 |
Structure |
Naming |
camelCase for variables and methods; |
1 |
3 |
Story |
Mad Lib variable |
Incomplete story stored in a |
1 |
4 |
Story |
Original displayed |
The story with its blanks is printed before any prompts |
1 |
5 |
2.10 Algorithms |
Find the blanks |
A |
1 |
6 |
2.10 Algorithms |
Replace the blanks |
Each blank is replaced with the user’s word using |
1 |
7 |
2.07 Loops |
Stay on track |
Prompts name the part of speech; blank answers are re-prompted |
1 |
8 |
2.10 Algorithms |
Number validation |
The |
1 |
9 |
Numbers |
Calculation |
The number is used in a calculation that appears in the story |
1 |
10 |
Selection |
Section choice |
A validated choice decides which section is included, and its blanks are filled too |
1 |
11 |
2.10 Algorithms |
Grammar fix |
|
1 |
12 |
String Methods |
String class |
Uses at least four String methods meaningfully (e.g., |
1 |
13 |
Testing |
Test mode |
|
1 |
14 |
Output |
Final story |
Completed story is printed at the end with correct sentence structure and spacing |
1 |
15 |
Documentation |
Comments and header |
Block comment header completed; comments describe each algorithm |
1 |
16 |
Submission |
Compiles & runs |
Compiles and completes a full run without errors |
1 |
TOTAL |
16 |
Penalties (from the original scoring guidelines):
−1 for sentence structure or grammar problems in the finished story (beyond what the player typed)
−1 for any input that causes a run-time error (for example, a non-number crashing
parseInt)
#############################################################################
2.11 Nested Iteration¶
📌 Standards — 2.11
Standard |
Description |
|---|---|
ICT 5.8 |
Create and use algorithms and solve problems |
ICT 5.9 |
Deconstruct large problems into components |
C4.6 |
Use proper programming language syntax |
C4.9 |
Create programs using control structures and variables |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Write nested loops (a loop inside another loop).
Determine how many times the inner loop body executes.
Trace nested loops where the inner loop depends on the outer loop variable.
How Nested Loops Run
The inner loop runs all the way through for each single pass of the outer loop.
for (int row = 1; row <= 3; row++)
{
for (int col = 1; col <= 4; col++)
{
System.out.print(row * col + "\t");
}
System.out.println(); // end the row AFTER the inner loop finishes
}
1 2 3 4
2 4 6 8
3 6 9 12
The outer loop runs 3 times. Each time, the inner loop runs 4 times, so the inner body runs 3 × 4 = 12 times.
When the Inner Loop Depends on the Outer Loop
for (int row = 1; row <= 4; row++)
{
for (int col = 1; col <= row; col++) // inner count grows with row
{
System.out.print("*");
}
System.out.println();
}
*
**
***
****
The inner body runs 1 + 2 + 3 + 4 = 10 times. In general, 1 + 2 + … + n = n(n + 1) / 2.
Nested Loops with Strings: Comparing Every Pair
To compare every character with every later character, start the inner loop one past the outer index:
String word = "letter";
int pairs = 0;
for (int i = 0; i < word.length(); i++)
{
for (int j = i + 1; j < word.length(); j++)
{
if (word.substring(i, i + 1).equals(word.substring(j, j + 1)))
{
pairs++; // matching pairs: e-e and t-t → 2
}
}
}
Exam Note (AP + Oracle): A
returninside nested loops exits the whole method. Abreak(Oracle) exits only the innermost loop, and the outer loop keeps going.
Exercise 2.11.A — Count the Executions¶
How many times does count++ execute in each segment? Count the inner passes for each outer pass.
Exercise 2.11.B — Write the Method¶
/** Returns true if any character appears more than once in str.
* hasRepeat("java") is true; hasRepeat("code") is false. */
public static boolean hasRepeat(String str)
{
/* your code here */
}
Activity 2.11.1 — Java Patterns: Nested Loop Art¶
Overview
Every ASCII pattern is a grid of rows and columns, which makes it a perfect fit for nested loops: the outer loop chooses the row, and the inner loop prints what goes in that row. You’ll build six patterns: four required ones that each teach a different nested-loop shape, plus two of your choice from the challenge menu.
By the end of this activity you will be able to:
Write nested loops where the inner loop runs a fixed number of times (rectangles)
Write nested loops where the inner loop depends on the outer loop variable (triangles)
Use two inner loops in one row (spaces, then symbols) to center a shape
Count how many times a nested loop body executes (2.12)
The Three Nested-Loop Shapes
Shape |
Inner loop condition |
Example |
|---|---|---|
Rectangle |
|
Solid square |
Triangle |
|
Right triangle |
Centered |
one loop for |
Pyramid |
Required Patterns (all four)
A. Solid Square B. Right Triangle C. Number Triangle D. Star Pyramid
***** * 1 *
***** ** 12 ***
***** *** 123 *****
***** **** 1234 *******
***** ***** 12345 *********
Challenge Menu (choose any two)
E. Hollow Square F. Number Pyramid G. Inverted Triangle H. Diamond
***** 1 ***** *
* * 121 **** ***
* * 12321 *** *****
* * 1234321 ** *******
***** 123454321 * *********
*******
*****
***
*
I. Checkerboard J. Floyd's Triangle K. Times Table
#.#.# 1 1 2 3 4 5
.#.#. 2 3 2 4 6 8 10
#.#.# 4 5 6 3 6 9 12 15
.#.#. 7 8 9 10 4 8 12 16 20
#.#.# 11 12 13 14 15 5 10 15 20 25
To Do
Add the required block comment header and print the run stamp (2.06a) first
Write each pattern as its own
public static voidmethod that takes the sizenas a parameter, for examplesolidSquare(int n)In
main, setint n = 5;, print a label for each pattern, and call all six methodsEvery pattern must use nested loops. Build each line one character at a time with
print. NoString.repeat(), and no hard-coded rows likeSystem.out.println("*****");.Each pattern must still be correct when you change
nto 3 and to 7Run-time comments (2.12): above
solidSquareandrightTriangle, state how many times the inner loop body runs whenn = 5, and write a formula in terms ofnAbove each challenge pattern, add a comment explaining which nested-loop shape(s) it uses
Hints
System.out.print("*")stays on the same line;System.out.println()ends the row.For centered patterns, row
rofnneedsn - rspaces, then2r - 1symbols.Hollow square: print
*when the position is on an edge (first or last row, first or last column), and a space otherwise.Checkerboard:
(row + col) % 2 == 0alternates like a chessboard.
Sample Output (first two patterns; yours continues with all six)
A. Solid Square
*****
*****
*****
*****
*****
B. Right Triangle
*
**
***
****
*****
Submission
Patterns.javawith block comment headerScreenshots of the output with
n = 5andn = 7
Grading: AP CSA 5-point Assignment Rubric. Pay particular attention to:
All six patterns use nested loops and work for any
nThe run-time formulas for patterns A and B are correct
Check for Understanding¶
#############################################################################
2.12 Informal Run-Time Analysis¶
📌 Standards — 2.12
Standard |
Description |
|---|---|
ICT 5.4 |
Interpret information and draw conclusions to make informed decisions |
ICT 5.9 |
Deconstruct large problems into components |
ICT 10.1 |
Interpret and explain ICT-specific terminology |
C4.6 |
Use proper programming language syntax |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 5 |
Utilize critical thinking to make sense of problems |
Count how many times a statement executes for a given input.
Write a statement-execution count in terms of a variable like
n.Compare two algorithms that solve the same problem by the amount of work they do.
College Board Note: The AP exam measures efficiency informally: you count how many times a statement executes. You won’t be asked for Big-O notation. Typical questions: “How many times is the statement
x++executed?” or “Which code segment performs the fewest iterations?”
Counting Statement Executions
Loop |
Times the body runs |
|---|---|
|
|
|
|
|
about |
|
about the number of times |
Two nested loops, each |
|
Inner loop runs |
|
Same Problem, Different Work
You’ve already seen this in action:
Activity |
Version 1 |
Version 2 |
|---|---|---|
2.09.1 Smallest Divisible |
checked 2,520 numbers |
multiples of 10 only: 252 |
2.10.1 |
|
|
2.07.2 Is a Factor? |
repeated subtraction: up to number ÷ divisor passes |
|
Both versions in each pair give the same answer. The second does less work, and on large inputs that difference becomes real time, which you’ll measure in 2.12.1.
Tracing Tools
These visualizers step through Java code one line at a time and show every variable, which is a great way to check a trace table:
Exercise 2.12.A — Count It¶
How many times does sum++ execute in each segment?
Exercise 2.12.B — Which Is Faster?¶
Both segments compute the same sum of the even numbers from 2 to n.
// Segment A
int sumA = 0;
for (int i = 1; i <= n; i++)
{
if (i % 2 == 0)
{
sumA += i;
}
}
// Segment B
int sumB = 0;
for (int i = 2; i <= n; i += 2)
{
sumB += i;
}
Activity 2.12.1 — Event Timer¶
Overview
How long does a loop take? You’ll record the time before and after a for loop that adds up the numbers 1 to n, then calculate the difference with Duration. Running it with bigger and bigger values of n connects what you counted on paper in 2.12 to real time on a real computer: more iterations take more time.
To Do
Add the required block comment header
Read
nwithScanner(usenextLong())Record
LocalTime start = LocalTime.now();just before the loop (2.06a)Use a
forloop to add 1 throughninto a sum. The sum must be along, because adding to a billion overflows anint(recall 1.05 ranges).Record
LocalTime end = LocalTime.now();right after the loopPrint the start and end times with the pattern
HH:mm:ss.SSS, the sum, and the elapsed time fromDuration.between(start, end)in milliseconds (toMillis()) and nanoseconds (toNanos())Run it with
n= 1,000,000, then 100,000,000, then 1,000,000,000. In a comment, record the three times and describe the pattern.
Sample Output (times vary by computer and run)
How many numbers should the loop add? 100000000
Start time: 12:46:06.006
End time: 12:46:06.089
Sum of 1 to 100000000 = 5000000050000000
Elapsed: 83 ms (83157726 ns)
Think About It (comment at the bottom)
When
ngrows 10 times bigger, about how much does the time grow?Why does the sum need to be a
long? What is the largestint(Integer.MAX_VALUE, 1.17)?For very precise timing, programmers often use
System.nanoTime()instead. Why might a clock time likeLocalTimebe less precise for very short loops?
Submission: EventTimer.java with your three recorded times in a comment. No test cases needed.
Grading: AP CSA 5-point Assignment Rubric.
Check for Understanding¶
#############################################################################
Unit 2 End-of-Unit Project — Sevens¶
📌 Standards — End-of-Unit Project
Standard |
Description |
|---|---|
ICT 2.0 |
Communications — communicate clearly in written and electronic formats |
ICT 5.4 |
Interpret information and draw conclusions to make informed decisions |
ICT 5.8 |
Create and use algorithms and solve problems |
ICT 5.9 |
Deconstruct large problems into smaller components |
ICT 7.5 |
Apply high-quality techniques to product design and development |
C4.6 |
Use proper programming language syntax |
C4.7 |
Use various data structures including objects |
C4.8 |
Use OOP concepts: properties, methods, and inheritance |
C4.9 |
Create programs using control structures, procedures, and variables |
C4.11 |
Document development work using comments |
C5.4 |
Design a solution to a problem |
C5.5 |
Implement a solution |
CRP 1 |
Apply appropriate technical skills and academic knowledge |
CRP 2 |
Communicate clearly, effectively, and with reason |
CRP 5 |
Utilize critical thinking to make sense of problems |
CRP 7 |
Act as a responsible and contributing citizen and employee |
Apply selection and iteration from all of Unit 2 (2.01–2.12) in one cohesive program.
Use a standard algorithm (frequency counting) to solve a real rule in a game.
Design repeatable tests for a program that uses randomness.
I will demonstrate mastery of Unit 2 by building a two-player dice game.
Overview
The number 7 is usually considered lucky, but not in this game! In Sevens, any two dice that add up to 7 are taken away. Players try to finish each round with the highest total from the dice that are left, and they must decide when to stop rolling: another roll might help, or it might wipe out their score.
Required Files: Sevens.java, SevensPlayer.java (minimum)
How to Play¶
You need: 2 players and 6 dice.
Set up. Choose the number of rounds (1 to 10). Player 1 goes first each round.
Roll. Player 1 rolls all six dice.
Remove sevens. Any pair of dice that adds up to 7 (1 + 6, 2 + 5, or 3 + 4) is removed and set aside for the rest of the turn. Each die can be in only one pair.
Score. Add up the dice that are left. That total is the player’s current score.
Roll again or stop. A player may roll up to three times per turn. A re-roll uses only the dice still in play; set-aside dice stay out. If every die has been removed, the next roll uses all six again. After each roll, new sevens are removed and the score becomes the total of what’s left. The score from the player’s last roll is their score for the round.
Player 2’s turn. Player 2 follows the same steps, but may roll only as many times as Player 1 did that round. If Player 1 rolled twice, Player 2 may roll up to twice.
End of round. Both round scores are added to the players’ running totals.
Winning. After the last round, the higher total wins. Equal totals are a tie.
Example Round
Player 1: Alex · Player 2: Jamie · 1 round · up to 3 rolls
Alex’s turn
Roll 1: 2, 3, 4, 5, 1, 6 → removed (1, 6), (2, 5), (3, 4) → remaining: none → total 0
Alex rolls again. Every die was removed, so Alex rolls all six.
Roll 2: 2, 2, 3, 5, 4, 1 → removed (2, 5), (3, 4) → remaining: 2, 1 → total 3
Alex stops and scores 3. Alex rolled twice, so Jamie may roll up to twice.
Jamie’s turn
Roll 1: 6, 6, 3, 3, 2, 5 → removed (2, 5) → remaining: 6, 6, 3, 3 → total 18
Jamie stops and scores 18.
Player |
Roll Attempts |
Round Score |
|---|---|---|
Alex |
2 |
3 |
Jamie |
1 |
18 |
Jamie wins the round.
The Key Idea: Counting Pairs¶
You might think you need to compare every die with every other die to find pairs. There’s a much simpler way.
A 1 can only pair with a 6. A 2 can only pair with a 5. A 3 can only pair with a 4. So if you know how many of each face were rolled, the number of pairs is just the smaller count of each partner:
Roll: 2, 2, 3, 5, 4, 1 |
1s |
6s |
2s |
5s |
3s |
4s |
|---|---|---|---|---|---|---|
Count |
1 |
0 |
2 |
1 |
1 |
1 |
Pairs |
min(1, 0) = 0 |
min(2, 1) = 1 |
min(1, 1) = 1 |
That’s 2 pairs: the score is the sum of all dice minus 7 for each pair (17 − 14 = 3), and the dice still in play drop by 4 (two per pair).
Counting how many times each value appears is the frequency count algorithm from 2.09. Six counters, c1 through c6, are all you need. No arrays required.
Part 1 — Plan First¶
Flowchart of one turn (2.01): rolling, removing pairs, the “roll again?” decision, and the roll limit. Use correct symbols, with the loop drawn as an arrow back to a decision diamond.
Pseudocode for counting the faces and computing the pairs, score, and dice remaining.
Part 2 — SevensPlayer.java¶
Stores one player’s state. Requirements:
Instance variables for the name, running total, this round’s score, and this round’s roll count
A constructor that takes the name and initializes everything else to 0
Accessor methods for each instance variable
public void recordRound(int score, int rolls)stores this round’s results and addsscoreto the running totaltoString()returns something likeAlex (total: 12)
Part 3 — Sevens.java¶
Your game must:
Read both players’ names, then the number of rounds. Re-prompt until the number is 1–10 (a
whileordo-whilevalidation loop).Use a
forloop for the rounds and awhileloop for the rolls in a turn. The roll loop keeps going while the player has rolls left AND wants to keep rolling.Use a static method
rollDie()that returns a random value from 1 to 6.Use a static method
playTurn(SevensPlayer player, int maxRolls)for one turn. Call it with3for Player 1 and with Player 1’s roll count for Player 2.On each roll:
roll exactly as many dice as are in play, using a
forloopbuild a display String of the dice, like
2, 3, 4, 5, 1, 6(no comma after the last die)count each face (
switchor anelse ifchain)compute pairs with
Math.min, then the score and the dice remainingprint the roll, the removed pairs (or
none), the remaining dice (ornone), and the total
Print the remaining dice with a nested loop: for each face 1–6, an inner loop prints that face as many times as it is left.
Ask
Roll again? (y/n)only when the player has rolls left, comparing the answer with.equalsIgnoreCase().After each round, print a scoreboard with
printfand announce the round winner, including ties.After the final round, print both players with
toString()and announce the game winner, including ties.Test mode: declare
private static final boolean TEST_MODEand aSEED. WhenTEST_MODEistrue, create yourRandomwith the seed (new Random(SEED)) so the same dice come up every run. Set it tofalsebefore you submit.In a comment above
playTurn, state the maximum number of timesrollDie()can be called in one round and show how you got it (2.12).
Sample Output (test mode, seed 7. Inputs: Alex, Jamie, 12 (rejected), 2, then y, n, y, n, n, n)
=== SEVENS ===
Player 1 name: Alex
Player 2 name: Jamie
How many rounds (1-10)? 12
Please enter a number from 1 to 10.
How many rounds (1-10)? 2
========== ROUND 1 of 2 ==========
Alex's turn (up to 3 rolls)
Roll 1: 5, 3, 4, 5, 5, 5
Removed: (3, 4)
Remaining: 5, 5, 5, 5
Alex's total = 20
Roll again? (y/n): y
Roll 2: 5, 6, 1, 1
Removed: (1, 6)
Remaining: 1, 5
Alex's total = 6
Roll again? (y/n): n
Alex scores 6 this round.
Jamie's turn (up to 2 rolls)
Roll 1: 1, 1, 1, 2, 2, 5
Removed: (2, 5)
Remaining: 1, 1, 1, 2
Jamie's total = 5
Roll again? (y/n): y
Roll 2: 4, 1, 4, 4
Removed: none
Remaining: 1, 4, 4, 4
Jamie's total = 13
Jamie scores 13 this round.
Player Roll Attempts Round Score
Alex 2 6
Jamie 2 13
Jamie wins this round.
========== ROUND 2 of 2 ==========
Alex's turn (up to 3 rolls)
Roll 1: 5, 3, 4, 2, 3, 3
Removed: (2, 5) (3, 4)
Remaining: 3, 3
Alex's total = 6
Roll again? (y/n): n
Alex scores 6 this round.
Jamie's turn (up to 1 roll)
Roll 1: 4, 5, 1, 6, 4, 4
Removed: (1, 6)
Remaining: 4, 4, 4, 5
Jamie's total = 17
Jamie scores 17 this round.
Player Roll Attempts Round Score
Alex 1 6
Jamie 1 17
Jamie wins this round.
========== FINAL ==========
Alex (total: 12)
Jamie (total: 30)
Jamie wins the game!
Notice Alex’s first round: re-rolling four 5s (a score of 20) turned into a 6. That’s the risk in Sevens. Also notice Jamie’s turns: the roll limit follows Alex’s roll count each round.
Part 4 — Test Cases¶
Use test mode so every test can be repeated exactly. Record the seed you used with each test.
An invalid round count (0 or 11) that gets re-prompted
A roll where all dice are removed, followed by a re-roll of all six
A roll with two of the same pair, such as (2, 5) (2, 5)
Player 2’s roll limit following Player 1’s roll count (1, 2, and 3 rolls)
A tied round and a final winner
Each test lists: seed, inputs, expected output, actual output, Pass/Fail
Tip: to find a seed that produces a situation you need (like all dice removed), try a few seeds and keep the one that works.
Unit 2 End-of-Unit Project Rubric¶
Each concept below is worth 1 point. Credit is awarded when the concept is used correctly and meaningfully, not simply present in the code. Partial credit is not awarded per concept.
# |
Category |
Concept |
What to Demonstrate |
Pts |
|---|---|---|---|---|
1 |
2.01 Algorithms |
Flowchart |
Flowchart of one turn with correct symbols, labeled decisions, and the roll loop drawn back to a decision |
1 |
2 |
2.01 Algorithms |
Pseudocode |
Pseudocode for face counting, pairs, score, and dice remaining |
1 |
3 |
2.02 Boolean Expressions |
boolean variable |
A |
1 |
4 |
2.03 / 2.04 Selection |
Round winner |
|
1 |
5 |
2.04 Selection |
Game winner |
Final winner logic correctly handles all three outcomes, including a tie |
1 |
6 |
2.04a Switch (Oracle) |
switch |
Uses a |
1 |
7 |
2.04a Ternary (Oracle) |
Ternary operator |
Uses |
1 |
8 |
2.05 Compound Boolean |
Loop condition |
Roll loop condition combines rolls left && wants to roll |
1 |
9 |
2.05 Compound Boolean |
Input validation |
Round validation uses |
1 |
10 |
2.06 Comparing Boolean |
De Morgan’s Law |
A comment states when the roll loop stops, written as the correct De Morgan form of its condition |
1 |
11 |
2.06 Comparing Objects |
String comparison |
The y/n answer is compared with |
1 |
12 |
2.07 while Loops |
while loop |
Turn rolls are controlled by a |
1 |
13 |
2.07 while Loops |
Validation loop |
Invalid round counts are re-prompted until valid |
1 |
14 |
2.07a do-while (Oracle) |
do-while |
Uses a |
1 |
15 |
2.08 for Loops |
for loop |
Dice are rolled with a |
1 |
16 |
2.08 for Loops |
No off-by-one |
Exactly the chosen number of rounds is played, and Player 2’s limit matches Player 1’s rolls |
1 |
17 |
2.09 Algorithms |
Frequency count |
Counts each face value correctly |
1 |
18 |
2.09 Algorithms |
Pairs and score |
Uses |
1 |
19 |
2.09 Algorithms |
Accumulator |
Running totals accumulate correctly across rounds |
1 |
20 |
2.10 String Algorithms |
String building |
Builds the dice display String in a loop with correct separators (no trailing comma) |
1 |
21 |
2.11 Nested Iteration |
Nested loop |
Remaining dice are printed with a nested loop (faces outer, count inner) |
1 |
22 |
2.12 Run-Time Analysis |
Execution count |
Comment correctly states the maximum |
1 |
23 |
Unit 1 — OOP |
SevensPlayer class |
Required instance variables, constructor, and accessors; |
1 |
24 |
Unit 1 — OOP |
toString() |
Overrides |
1 |
25 |
Unit 1 — Methods |
Static methods |
|
1 |
26 |
Unit 1 — Random |
Random with seed |
Uses |
1 |
27 |
Unit 1 — Scanner |
Input |
Reads names ( |
1 |
28 |
Unit 1 — Formatting |
printf scoreboard |
Round scoreboard is aligned with |
1 |
29 |
Documentation |
Headers and comments |
Required block comment header in both files, all fields completed; meaningful comments throughout |
1 |
30 |
Submission |
Test Cases |
All Part 4 tests included with seeds, inputs, expected and actual output, Pass/Fail |
1 |
31 |
Submission |
Files |
Flowchart, pseudocode, test cases, screenshots, and all |
1 |
32 |
Submission |
Compiles & runs |
Program compiles without errors and plays a complete game without crashing |
1 |
TOTAL |
32 |
Grading Notes:
Code must compile and run to receive credit for most concept points.
A concept used only in a comment, or in code that never executes, does not earn its point (except points 10 and 22, which are comments by design).
Point 18 requires correct handling of the all-removed case: the next roll uses all six dice.
#############################################################################