Java Foundations Checkpoint
Welcome to your very first milestone! You’ve made it through 11 parts of intense learning. We’ve covered variables, loops, arrays, strings, methods, and even melted our brains a little with recursion. Now, it’s time to prove to yourself that you can actually build something with all these puzzle pieces. Today, we step away from theory and build a Java Mini Project: a fully functional Console Calculator and Number Guessing Game.

Table of Contents
- Why Checkpoints Matter
- Consolidated Review: Parts 1–11
- The Top 15 Beginner Pitfalls, Revisited
- Debugging Basics
- Self-Assessment Quiz
- Mini Project Brief: Calculator + Guessing Game
- Design & Planning
- Building the Console Calculator
- Building the Number Guessing Game
- Combining Both with a Main Menu
- Full Code Walkthrough
- Testing Your Program
- Common Mistakes at This Stage
- Best Practices Recap
- Frequently Asked Questions (FAQ)
- Interview Questions (Foundations-Wide)
- Test Your Knowledge (MCQs)
- Practice Coding Questions
- Extended Assignment
- Stretch Challenge
- Summary and Cheat Sheet
Why Checkpoints Matter
Learning to code step-by-step is great, but if you don’t actively combine those steps, your brain files them away in separate folders labeled “Part 5 stuff” and “Part 9 stuff.”
A checkpoint forces integration. It proves you can pick up several previously separate tools and use them together to build something real. This is also your first taste of how professional software development works: you’ll get a brief, you’ll have to plan it out, and then you’ll build it.
Consolidated Review: Parts 1–11
Let’s quickly walk back through our journey and see exactly how it applies to today’s Java mini project:
- Part 1 & 2 (Setup & Variables): Today’s project is a fully runnable
.javafile. We will strategically chooseintfor menu choices,doublefor calculator math, andbooleanfor our game loop. - Part 3 (Operators): The calculator’s entire existence is built on arithmetic operators!
- Part 4 (Scanner & I/O): Every user interaction will flow through a single, well-managed
Scanner. - Part 5 (Conditionals): We will use
switchstatements to handle our main menu, andif-elseladders to tell the user if their guess is too high or too low. - Part 6 (Loops): The main menu and the guessing attempts will be powered by
whileloops. - Part 9 (Strings): We’ll use essential String methods to validate input.
- Part 10 (Methods): This is the big one. Today’s entire project will be organized into clean, single-responsibility methods. No more writing 200 lines of code inside
main!
The Top 15 Beginner Pitfalls, Revisited
Treat this as your pre-flight checklist. Before you write any code today, remember these classic traps:
- Integer division:
5 / 2gives2, not2.5. Use doubles! ==vs.equals(): Always use.equals()for Strings!- The
nextInt()trap: Don’t forget to consume that leftover newline if you switch to reading Strings. - Off-by-one errors: Double-check
<vs<=in your loops. - Array bounds: Arrays go from
0tolength - 1. - Forgetting
breakinswitch: Welcome to unintended fall-through. - Dangling else: Always use
{ }braces. - Infinite loops: Make sure your
whilecondition eventually becomes false. (int)casting: It truncates decimals, it doesn’t round them.- Immutable Strings: String methods return new strings. You must capture the return value!
- Pass-by-value confusion: Reassigning a parameter inside a method doesn’t change the original outside.
- Missing returns: Every path in a non-void method needs a
returnstatement. - Forgetting base cases: Hello,
StackOverflowError. lengthvslength(): Arrays use the field (no parentheses). Strings use the method (parentheses).- Using floats for money: Beware of binary floating-point rounding errors!
Debugging Basics
Before we build, let’s talk about what happens when things break.
1. Reading Compiler Errors
Don’t panic. The compiler usually tells you the exact line number where the issue happened. Always fix the very first error on the list—often, fixing one error magically makes the rest disappear.
2. The Power of Print Statements
If your logic is failing, don’t just stare at the screen. Drop in some temporary System.out.println("DEBUG: myVar is " + myVar); statements. Actually seeing what your variables hold at runtime is the fastest way to spot a bug.
3. Tracing by Hand
If your loop or recursion is broken, get a piece of paper and a pen. Manually track the variables through the first three loops. You will almost always spot the flaw instantly.
Self-Assessment Quiz
Can you answer these from memory?
- What is the difference between
==and.equals()for Strings? - What does
array.lengthreturn, and is it a field or a method? - Why does
5 / 2equal2in Java? - What’s the difference between
breakandcontinue?
(If you nailed those, you are 100% ready to build this project!)
Mini Project Brief: Console Calculator + Number Guessing Game
Here is your assignment, written exactly how a boss or a client might hand it to you:
The Brief: Build a single console application that presents the user with a main menu offering three options: (1) a calculator that performs basic arithmetic operations chosen by the user, (2) a number guessing game with a limited number of attempts, and (3) exit. The program should loop back to the main menu after each activity completes, until the user chooses to exit. Handle invalid menu choices gracefully.
Design & Planning
We aren’t just going to start typing. Let’s break this down into clean methods:
| Method | Responsibility |
|---|---|
main | Shows the menu loop and calls the right activity. |
showMainMenu() | Just prints the text options to the screen. |
runCalculator(Scanner) | Handles all calculator inputs and outputs. |
performOperation(...) | Does the actual math and returns the result. |
runGuessingGame(Scanner) | Handles the entire game loop. |
Notice how we are passing the Scanner into the methods? We only want to create one Scanner in our entire program to avoid weird input bugs!
Building the Console Calculator
First, let’s build the math engine:
static double performOperation(double num1, double num2, char operator) {
switch (operator) {
case '+': return num1 + num2;
case '-': return num1 - num2;
case '*': return num1 * num2;
case '/':
if (num2 == 0) {
System.out.println("Error: Cannot divide by zero.");
return Double.NaN; // "Not a Number" - a safe way to return a failure!
}
return num1 / num2;
default:
System.out.println("Invalid operator.");
return Double.NaN;
}
}
Now, the method that talks to the user:
static void runCalculator(Scanner scanner) {
System.out.print("Enter first number: ");
double num1 = scanner.nextDouble();
System.out.print("Enter an operator (+, -, *, /): ");
char operator = scanner.next().charAt(0); // Grabs the very first character they type
System.out.print("Enter second number: ");
double num2 = scanner.nextDouble();
double result = performOperation(num1, num2, operator);
if (!Double.isNaN(result)) { // If it wasn't a failure, print it!
System.out.printf("Result: %.2f %c %.2f = %.2f%n", num1, operator, num2, result);
}
}
Building the Number Guessing Game
Next up, the game logic. This combines random numbers, while-loops, and if-else ladders perfectly:
static void runGuessingGame(Scanner scanner) {
Random random = new Random();
int secretNumber = random.nextInt(100) + 1; // Random number 1 to 100
final int MAX_ATTEMPTS = 7;
int attemptsUsed = 0;
boolean hasWon = false;
System.out.println("\nI'm thinking of a number between 1 and 100.");
System.out.println("You have " + MAX_ATTEMPTS + " attempts.");
while (attemptsUsed < MAX_ATTEMPTS) {
System.out.print("Enter your guess: ");
int guess = scanner.nextInt();
attemptsUsed++;
if (guess == secretNumber) {
hasWon = true;
break; // They won! Break out of the loop immediately.
} else if (guess < secretNumber) {
System.out.println("Too low! Attempts remaining: " + (MAX_ATTEMPTS - attemptsUsed));
} else {
System.out.println("Too high! Attempts remaining: " + (MAX_ATTEMPTS - attemptsUsed));
}
}
if (hasWon) {
System.out.println("Congrats! You guessed it in " + attemptsUsed + " attempts.");
} else {
System.out.println("Out of attempts! The number was: " + secretNumber);
}
}
Combining Both with a Main Menu
Finally, we need a way to tie it all together. Our main method will just be an orchestrator that runs a simple switch statement inside a while loop!
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
boolean running = true;
while (running) {
showMainMenu();
int choice = scanner.nextInt();
switch (choice) {
case 1:
runCalculator(scanner);
break;
case 2:
runGuessingGame(scanner);
break;
case 3:
running = false; // Changes the flag so the while-loop stops!
System.out.println("Goodbye!");
break;
default:
System.out.println("Invalid option. Please choose 1, 2, or 3.");
}
}
scanner.close();
}
Full Code Walkthrough
When you paste all of those methods into one file called FoundationsMiniProject.java, here is what it looks like when you run it!
Sample Run:
===== MAIN MENU =====
1. Calculator
2. Number Guessing Game
3. Exit
Choose an option: 1
Enter first number: 15
Enter an operator (+, -, *, /): *
Enter second number: 4
Result: 15.00 * 4.00 = 60.00
===== MAIN MENU =====
1. Calculator
2. Number Guessing Game
3. Exit
Choose an option: 3
Goodbye!
Why this code is great:
- One Shared Scanner: We followed best practices by passing the scanner into the methods.
- Single Responsibility: Every method does exactly one job.
- Graceful Failures: We handled division by zero using
Double.NaNinstead of letting the program crash!
Testing Your Program
Before you call any code “done,” you need to try and break it.
- Happy path: Does
10 + 5work? - Edge cases: What happens if you try to divide by zero? What happens if you guess the number on the very first try?
- Invalid input: What happens if you type
9at the main menu?
Best Practice: Deliberately trying to break your own program is a fantastic habit. It is far better that you find the bug than your user does!
Common Mistakes at This Stage
- Forgetting to pass the
Scannerand creating a new one inside every method. - Forgetting the
defaultcase in the switch statement, causing the menu to do weird things if a user types a bad number. - Letting your
mainmethod get massive. Delegate tasks to helper methods!
Best Practices Recap
- Plan your methods and their responsibilities before you start coding.
- Keep your
mainmethod focused purely on orchestration (the menu loop). - Handle bad input with clear, friendly messages.
Frequently Asked Questions (FAQ)
Q1. Why use Double.NaN instead of returning 0 on an error?
Because 0 is a valid answer for 10 - 10! Double.NaN literally means “Not a Number”, which makes it the perfect flag to signal that a calculation failed.
Q2. What happens if the user types a letter “A” instead of a number in the menu?
Currently, the program will crash with an InputMismatchException because nextInt() expects a number! Handling this gracefully requires a concept called “Exception Handling”, which we will cover in depth later in the roadmap (Part 23).
Interview Prep Questions
Basic:
- Why is passing the same
Scannerinstance into multiple methods considered good practice? - What is the purpose of the
finalkeyword, and where did we use it here?
Intermediate:
- Explain how the main menu’s
whileloop andbooleanflag work together to keep the program running. - How would you refactor
performOperationif you wanted to also support integer-only operations separately?
Test Your Knowledge (MCQs)
Q1. What must every recursive method include to avoid infinite recursion?
a) A while loop
b) A base case
Answer: b)
Q2. In our mini project, what does Double.isNaN(result) check for?
a) Whether the result is zero
b) Whether the result is a valid number
Answer: b) It checks to make sure the math didn’t fail (like a divide-by-zero error).
Practice Coding Questions
- Extend the calculator to support the modulus (
%) operator. - Add a
printWelcomeBanner()method that displays some cool ASCII art when the program first starts up. - Modify the calculator to keep a running count of how many times it has been used during the session.
Extended Assignment: Calculation History Tracker
Extend the mini project:
- Create an array of size 10 to store the results of the last several calculations.
- Add a new main menu option: “View Calculation History”.
- Use a loop to print out all the stored results!
Summary and Cheat Sheet
- A checkpoint’s real purpose is integration. You just proved you can combine everything you’ve learned.
- Planning your method structure before coding is essential.
- This Java mini project successfully combined variables, operators, conditionals, loops, arrays, strings, and methods into one cohesive application!
Foundations Cheat Sheet (Parts 1–11)
| Part | Core Concept | One-Line Reminder |
|---|---|---|
| 2 | Variables & Types | 8 primitives; final for constants. |
| 3 | Operators | / truncates for ints; &&/|| short-circuit. |
| 5 | Conditionals | Always use braces; switch needs break. |
| 6 | Loops | for = known count; while = condition-driven. |
| 7 | Arrays | Zero-indexed; .length is a field. |
| 9 | Strings | Immutable; always use .equals(). |
| 10 | Methods | Pass-by-value always. One method = One job. |
Further Reading
- Oracle Docs: Java Random Class
Conclusion
Congratulations! You’ve just completed the first major checkpoint of your Java journey, and you built a fantastic, multi-feature console application entirely from a brief. Every concept from Parts 1-11 showed up today.
From here, the roadmap shifts gears dramatically. We are leaving behind procedural programming and stepping into the real power of Java: Object-Oriented Programming (OOP).
Ready to level up your mindset? Check out Part 13 — OOP Introduction: Classes & Objects!