Skip to main content

ATM Machine

Imagine walking to an ATM.

You insert your card. You enter your PIN. You withdraw money.

It feels simple.

But behind that simplicity is structure.

This project is about building that structure.

Not visually. Not with databases. Not with real money.

But with logic.

What You Are Building

You will design a console-based ATM system that:

  • Authenticates a user using a PIN
  • Allows balance checking
  • Allows withdrawals
  • Allows deposits
  • Ends session safely
  • Locks after multiple failed attempts

There is no GUI. No database. No external libraries.

Only structured logic.

Why This Project Matters

This project trains:

  • State management
  • Conditional control
  • Defensive programming
  • Flow control
  • Edge-case thinking
  • User-driven loops

An ATM is a controlled system.

Nothing random happens.

Every action follows rules.

That is engineering.

System Rules (Define Before Coding)

Your ATM must:

  • Start with an initial balance
  • Allow only 3 incorrect PIN attempts
  • Prevent withdrawal before authentication
  • Prevent withdrawing more than available balance
  • Prevent negative deposits or withdrawals
  • Exit cleanly when user chooses

These rules define system integrity.

tip

Before writing code, write the rules. Systems fail when rules are unclear.

Think Like a Designer

Before coding, answer mentally:

  • What is the state of the ATM?
  • When does the session begin?
  • When does it end?
  • What conditions block action?
  • What can go wrong?

If you cannot answer these clearly, pause.

Watch First - How Systems Enforce Rules

While watching, focus on:

  • State transitions
  • Authentication logic
  • Defensive checks
  • Controlled termination

Now we build carefully.

Step One - Identify the State

Your ATM needs:

  • stored_pin
  • balance
  • attempts_remaining
  • is_authenticated

These represent system condition.

Everything else depends on them.

Step Two - Outline the Flow

There are two major phases:

Authentication phase
Operation phase

The system must not allow the second without the first.

Pseudocode (Before Python)

Initialize balance
Initialize stored PIN
Initialize attempt counter

While not authenticated and attempts remain:
Ask for PIN
If correct:
Authenticate
Else:
Reduce attempts
If attempts reach zero:
Lock system

If authenticated:
Repeat:
Show menu
Process user choice
Update balance if needed
Exit if chosen

Notice the separation of phases.

That separation is structure.

Basic Implementation

stored_pin = "1234"
balance = 1000
attempts_remaining = 3
is_authenticated = False

while attempts_remaining > 0 and not is_authenticated:
entered_pin = input("Enter PIN: ")

if entered_pin == stored_pin:
is_authenticated = True
print("Access granted.")
else:
attempts_remaining -= 1
print("Incorrect PIN.")
print("Attempts left:", attempts_remaining)

if not is_authenticated:
print("Account locked.")
else:
while True:
print("\n1. Check Balance")
print("2. Withdraw")
print("3. Deposit")
print("4. Exit")

choice = input("Choose option: ")

if choice == "1":
print("Balance:", balance)

elif choice == "2":
amount = float(input("Enter withdrawal amount: "))
if amount <= 0:
print("Invalid amount.")
elif amount > balance:
print("Insufficient funds.")
else:
balance -= amount
print("Withdrawal successful.")

elif choice == "3":
amount = float(input("Enter deposit amount: "))
if amount <= 0:
print("Invalid amount.")
else:
balance += amount
print("Deposit successful.")

elif choice == "4":
print("Session ended.")
break

else:
print("Invalid choice.")

Edge Cases You Must Handle

Ask yourself:

  • What if withdrawal amount equals balance?
  • What if user enters text instead of number?
  • What if PIN attempts reach zero exactly?
  • What if user never chooses exit?

This is defensive thinking.

Growth Reflection

Right now:

One user. One balance. One session.

But imagine:

1,000 users.

Now state must be isolated per account.

Now memory management matters.

Now data structures matter.

Now architecture matters.

Even simple systems hint at scaling problems.

Interview Extension

Improve the system by adding:

  • Transaction history
  • Daily withdrawal limit
  • PIN change feature
  • Lockout timer
  • Decimal-based balance handling

Every enhancement tests structure.

Final Reflection

The ATM is small.

But it forces clarity.

It forces rule definition.

It forces state control.

It forces defensive thinking.

If you design this well, you are not just coding.

You are engineering behavior.

© 2026 EngineersOfAI. All rights reserved.