THE SYLLABUS TASK
What you need to build
Design and implement a Java program to simulate an ATM PIN verification system using string comparison techniques.
Full syllabus requirements: classes, fields and methods
Demo username, stored four-digit PIN, then up to three entered PINs, one per line. Entered values are strings so leading zeros remain intact. Stops after success or three failures.
UNDERSTAND THE IDEA
Explanation
PIN strings must be compared by content using equals, not by reference identity. The stored four-digit PIN can contain leading zeros.
authenticate accepts at most three attempts, returns immediately on success and prints ACCOUNT LOCKED after the third failure. This is a single-run lab simulation; it does not implement persistent account locking or real authentication.
TURN THE IDEA INTO STEPS
Step-by-step algorithm
- Validate the stored PIN’s four-digit format.
- Read each entered PIN as text.
- Compare content with verifyPIN.
- Return after a successful match.
- Print the locked message only after three incorrect attempts.
SEE THE CORE OPERATION
Flowchart
This chart focuses on the named operation or core OOP decision. Diamonds show conditions; labeled branches show outcomes. Read it with the complete algorithm and source for input handling and other operations. Scroll within the diagram on a phone.
PIN verification with three attempts
Main.java
import java.util.*;
public class Main {
private static final Scanner IN = new Scanner(System.in).useLocale(Locale.ROOT);
static String text() {
if (!IN.hasNextLine()) throw new IllegalArgumentException("Incomplete input.");
String value = IN.nextLine().trim();
if (value.isEmpty() || value.length() > 200) throw new IllegalArgumentException("Text must have 1–200 characters.");
return value;
}
static int integer(int low, int high) {
int value = Integer.parseInt(text());
if (value < low || value > high) throw new IllegalArgumentException("Integer out of range.");
return value;
}
static double number(double low, double high) {
double value = Double.parseDouble(text());
if (!Double.isFinite(value) || value < low || value > high) throw new IllegalArgumentException("Number out of range.");
return value;
}
static void money(String label, double value) { System.out.printf(Locale.ROOT, "%s: %.2f%n", label, value); }
static class ATMPinChecker {
private final String username, pinStored;
ATMPinChecker(String username, String pinStored) {
if (!pinStored.matches("[0-9]{4}")) throw new IllegalArgumentException("Stored PIN must be four digits.");
this.username=username; this.pinStored=pinStored;
}
boolean verifyPIN(String enteredPIN) { return pinStored.equals(enteredPIN); }
void authenticate() {
System.out.println("User: " + username);
for (int attempt=1; attempt<=3; attempt++) {
String entered = text();
if (verifyPIN(entered)) { System.out.println("PIN ENTERED CORRECT"); return; }
System.out.println("Incorrect PIN, attempt " + attempt + ".");
}
System.out.println("ACCOUNT LOCKED");
}
}
// Demo username/stored four-digit PIN, then up to three entered PIN lines.
public static void main(String[] args) {
try { new ATMPinChecker(text(),text()).authenticate(); }
catch (IllegalArgumentException e) { System.out.println("Invalid input: " + e.getMessage()); }
}
}
Copy a source file or download the project to preserve its file names.
USE THE RIGHT ENVIRONMENT
How to compile and run
Install a JDK (Java 11 or newer; JDK 17 is suitable), extract this project’s ZIP into its own folder, then open a terminal in that folder.
javac -encoding UTF-8 Main.java
java MainThe standalone source is named Main.java and its entry class is Main. You may also paste it into an online Java compiler and supply the sample input there. Choose Java explicitly; these pages do not change the site compiler or import code automatically.
Each experiment has its own folder because many use the public class Main. Compile and run one experiment at a time.
UNDERSTAND THE JAVA CODE
Line-by-line explanation
These steps follow the exact Java source above. Related statements are grouped; line numbers count blank lines and restart for each file. Start with main to follow execution, then open the constructors, methods or event handlers it uses.
Main.java
Lines 1–4Import utilities and create the shared input reader
import java.util.*;
public class Main {
private static final Scanner IN = new Scanner(System.in).useLocale(Locale.ROOT);java.util.* imports utility type names such as Scanner, Locale and collections. Main is the public class matching Main.java. The private static final IN field holds one shared Scanner for System.in; final prevents replacing that reference. The scanner uses Locale.ROOT.
Lines 5–10Read one nonempty trimmed input line
static String text() {
if (!IN.hasNextLine()) throw new IllegalArgumentException("Incomplete input.");
String value = IN.nextLine().trim();
if (value.isEmpty() || value.length() > 200) throw new IllegalArgumentException("Text must have 1–200 characters.");
return value;
}text checks whether a line exists, reads it and removes leading/trailing whitespace. Reject empty text and lengths above 200 by throwing IllegalArgumentException. Otherwise return the string. One field is read per line, so these helpers do not mix nextInt with leftover newlines.
Lines 11–15Parse and range-check an integer field
static int integer(int low, int high) {
int value = Integer.parseInt(text());
if (value < low || value > high) throw new IllegalArgumentException("Integer out of range.");
return value;
}Integer.parseInt converts the returned string to int or throws NumberFormatException, a subtype of IllegalArgumentException. Reject values outside the caller’s inclusive low/high limits, then return the accepted integer.
Lines 16–20Parse and range-check a finite decimal field
static double number(double low, double high) {
double value = Double.parseDouble(text());
if (!Double.isFinite(value) || value < low || value > high) throw new IllegalArgumentException("Number out of range.");
return value;
}Double.parseDouble reads the string as a double. Double.isFinite rejects NaN and infinities as well as the explicit low/high range check. Return only a finite accepted value; exceptions transfer control to a matching catch block.
Line 21Format a labelled numeric result consistently
static void money(String label, double value) { System.out.printf(Locale.ROOT, "%s: %.2f%n", label, value); }money is a formatting helper: %s prints the label, %.2f prints two decimal places, and %n ends the line. Locale.ROOT fixes locale-sensitive formatting. The helper can also display non-currency quantities; it does not change the stored value.
Lines 22–27Store a checked four-digit demo PIN as a string
static class ATMPinChecker {
private final String username, pinStored;
ATMPinChecker(String username, String pinStored) {
if (!pinStored.matches("[0-9]{4}")) throw new IllegalArgumentException("Stored PIN must be four digits.");
this.username=username; this.pinStored=pinStored;
}Keeping the PIN as text preserves leading zeros. The constructor requires exactly four digits for the stored PIN, then assigns final identity fields.
Lines 28–30Compare PIN contents and begin authentication
boolean verifyPIN(String enteredPIN) { return pinStored.equals(enteredPIN); }
void authenticate() {
System.out.println("User: " + username);equals compares the stored and entered character sequences; == would compare String references instead. Print the demonstration username before asking for attempts.
Lines 31–35Allow up to three attempts and return early on success
for (int attempt=1; attempt<=3; attempt++) {
String entered = text();
if (verifyPIN(entered)) { System.out.println("PIN ENTERED CORRECT"); return; }
System.out.println("Incorrect PIN, attempt " + attempt + ".");
}Read one nonempty PIN line per attempt. A match prints success and returns from authenticate immediately. A mismatch prints its attempt number and continues while attempts remain.
Lines 36–38Reach the lock message only after three failures
System.out.println("ACCOUNT LOCKED");
}
}If no earlier return occurred, print ACCOUNT LOCKED. This is the exercise’s in-memory control flow, not an actual external account lock.
Lines 39–44Construct the demo checker and handle invalid input
// Demo username/stored four-digit PIN, then up to three entered PIN lines.
public static void main(String[] args) {
try { new ATMPinChecker(text(),text()).authenticate(); }
catch (IllegalArgumentException e) { System.out.println("Invalid input: " + e.getMessage()); }
}
}main reads username and stored PIN, constructs an object and calls authenticate. The catch reports missing/invalid input lines. The supplied program does not use a banking service.
FOLLOW THE STATE
Dry run
- Stored PIN 0123 is compared with 9999 and fails.
- The second entered string 0123 matches and succeeds.
- No third attempt is read.
- Entering 123 would not match 0123 because the leading zero matters.
CHECK THE BEHAVIOUR
Sample input & output
These outputs were captured by running the exact delivered Java project.
Sample 1
Demo
0123
9999
0123
User: Demo
Incorrect PIN, attempt 1.
PIN ENTERED CORRECT
Sample 2
Demo
0123
123
0000
9999
User: Demo
Incorrect PIN, attempt 1.
Incorrect PIN, attempt 2.
Incorrect PIN, attempt 3.
ACCOUNT LOCKED
Common mistakes
- Do not use == for string content.
- Do not parse a PIN as an integer.
- Stop reading immediately after a successful attempt.
WHY THIS GROWTH RATE?
Time and space complexity
At most three comparisons; O(L) comparison work per attempt, fixed four-character stored PIN.
String equality depends on compared text length, but both attempt count and stored-PIN width are fixed here.
The example therefore has bounded comparison work; reading entered text contributes its length. It stores only the username, stored PIN and current attempt.
These bounds describe the implemented data processing. Input/output text length, scheduling, framework rendering and runtime/library internals are identified separately where they matter. Educational limits bound the actual examples.
PREPARE FOR YOUR LAB VIVA
Related viva questions & answers
Try answering aloud, then expand to check your reasoning. Questions focus on this program’s classes, state and behavior.
Why does verifyPIN use equals instead of ==?
equals compares the characters. The == operator checks whether both references identify the same String object, which is not the required PIN comparison.
Why is 0123 different from 123 in this program?
PINs are character sequences, not numeric quantities. The leading zero is preserved and must also be entered for an exact match.
What prevents a fourth PIN attempt?
The loop condition permits only attempt values 1 through 3. After that range is exhausted, the method prints the locked message and returns.
Why does authenticate return as soon as a PIN matches?
Success completes authentication for this demonstration. Continuing would consume unnecessary input and could incorrectly produce failure messages afterward.
What happens if all three entries are wrong?
The method reports each failed attempt and then prints exactly ACCOUNT LOCKED. No balance operation or additional PIN attempt follows.
Is the lock remembered after restarting this Java program?
No. This is a classroom simulation with in-memory state. Persistent locking and protected credential storage are outside this exercise.