Why Loops? โ The Game Loop Concept
A loop is just "repeat until done." In games, this is the Game Loop โ the heartbeat of every game engine running 60 times per second, keeping your player's world alive.
The Mental Model
Real-World Analogy: Think of a conveyor belt at checkout โ items (frames) keep moving through scan โ bag โ receipt until the belt stops. Your game does the same: input โ update โ render, forever.
The Game Loop โ Every Engine Ever
// THE GAME LOOP โ runs 60 times per second! while (gameIsRunning) { processInput(); // 1. Read keyboard/mouse/controller update(); // 2. Move entities, check collisions render(); // 3. Draw everything to screen }
Without loops, you'd need to write render() 3,600 times for just one minute of gameplay. Loops let computers do the repetitive work so you can focus on the fun stuff.
Why Java Has Four Loop Types
| Loop Type | Best For | Game Example |
|---|---|---|
| for | Known count | Spawn 10 enemies, tick 60fps timer |
| while | Unknown count | Game loop, resource gathering, input wait |
| do-while | Run at least once | Menu systems, retry logic |
| for-each | Collections | Render all entities, check all bullets |
The for Loop โ "I Know Exactly How Many Times"
Use the for loop when you know the exact number of iterations up front โ inventory slots, level counts, countdown timers. The three-part header puts initialization, condition, and update all in one visible line.
Anatomy of a for Loop
for (int i = 0; i < 10; i++) { // body runs 10 times (i = 0,1,2,...,9) } // โ init โ condition โ update
๐ฎ Example 1: Inventory Slot Initialization
// Create 20 empty inventory slots for an RPG String[] inventory = new String[20]; for (int slot = 0; slot < inventory.length; slot++) { inventory[slot] = "[EMPTY]"; System.out.println("Slot " + (slot + 1) + ": " + inventory[slot]); } // Output: Slot 1: [EMPTY] ... Slot 20: [EMPTY]
๐ฎ Example 2: Countdown Timer (Boss Fight Warning)
System.out.println("โ๏ธ BOSS SPAWNING IN:"); for (int seconds = 10; seconds >= 1; seconds--) { System.out.println(seconds + "..."); // Thread.sleep(1000); // Uncomment for real delay } System.out.println("๐ THE BOSS HAS ARRIVED!");
Notice the loop counts DOWN: seconds = 10; seconds >= 1; seconds--. The init starts high, condition checks it's still positive, and the update decrements.
๐ฎ Example 3: XP Table Generator
// Exponential XP curve โ common in RPGs for (int level = 1; level <= 20; level++) { int xpRequired = (int) (100 * Math.pow(1.5, level - 1)); System.out.printf("Level %2d โ %,d XP%n", level, xpRequired); } // Level 1 โ 100 XP // Level 2 โ 150 XP // Level 20 โ 221,683 XP
for (int i = 5; i <= 10; i++)<= (less than OR EQUAL TO), so 10 is included.Spell Cooldown Display
Write a for loop that prints all 5 spells in an array with their cooldown in seconds. Cooldowns: {3, 5, 8, 12, 20}.
- Print:
Fireball: 3s cooldown(one per spell) - Use
String[]for names,int[]for cooldowns - Bonus: mark spells with cooldown > 10 as "LONG"
The while Loop โ "Keep Going While True"
Use while when you don't know how many iterations you'll need โ only when to stop. The condition is checked before each iteration. If it starts false, the body never runs.
When you know how many times
for (int i=0; i<10; i++)
Counter is built-in, clean syntax
When you know the stop condition
while (playerIsAlive)
Flexible, works for unknown counts
while (condition) { // body โ condition checked BEFORE each iteration // if condition starts false, body NEVER runs }
๐ฎ Example 1: Input Validation (Menu System)
Scanner scanner = new Scanner(System.in); int choice = -1; while (choice < 1 || choice > 4) { System.out.println(""" === MAIN MENU === 1. New Game 2. Load Game 3. Settings 4. Quit Choose (1-4): """); if (scanner.hasNextInt()) { choice = scanner.nextInt(); if (choice < 1 || choice > 4) System.out.println("โ Invalid! Enter 1-4."); } else { System.out.println("โ Numbers only!"); scanner.next(); // consume bad input } } System.out.println("โ You chose: " + choice);
๐ฎ Example 2: Resource Gathering (Idle Game Mechanic)
int gold = 0; int workers = 3; int targetGold = 1000; System.out.println("โ๏ธ Mining gold... (target: " + targetGold + ")"); while (gold < targetGold) { gold += workers * 5; // each worker mines 5 gold/tick System.out.printf("Gold: %,d | Workers: %d%n", gold, workers); // Hire more workers at milestones if (gold >= 500 && workers == 3) { workers = 5; System.out.println("๐ Hired 2 more workers!"); } } System.out.println("๐ฐ Target reached! Total: " + gold);
Always make sure something inside the loop eventually makes the condition false. A while(true) loop with no break will freeze your program โ and your game!
false when a while loop is first reached, what happens?while loop checks the condition BEFORE each iteration. If it's false immediately, the body is skipped entirely โ zero executions. This is what makes it different from do-while.The do-while Loop โ "Run Once, Then Check"
The do-while loop guarantees the body runs at least once before checking the condition. Perfect for menu systems, retry logic, and any situation where you need one initial action before deciding to repeat.
The Key Difference
| Loop | Checks Condition | Guaranteed First Run? | Use When |
|---|---|---|---|
| while | Before each iteration | โ No | Condition may already be false |
| do-while | After each iteration | โ Yes | Must execute once regardless |
do { // body runs FIRST // THEN condition is checked } while (condition); // โ semicolon required!
๐ฎ Example 1: Retry Mechanism (Server Connection)
int maxAttempts = 3; int attempt = 0; boolean connected = false; do { attempt++; System.out.println("๐ Attempt " + attempt + " of " + maxAttempts); connected = Math.random() < 0.3; // 30% success rate if (!connected && attempt < maxAttempts) System.out.println("โ Failed. Retrying..."); } while (!connected && attempt < maxAttempts); if (connected) System.out.println("โ Connected to game server!"); else System.out.println("๐ฅ Failed after " + maxAttempts + " attempts.");
๐ฎ Example 2: Play Again Prompt
Scanner scanner = new Scanner(System.in); String playAgain; do { playGame(); // Your game logic here โ always runs first! System.out.print("\n๐ฎ Play again? (y/n): "); playAgain = scanner.nextLine().trim().toLowerCase(); } while (playAgain.equals("y") || playAgain.equals("yes")); System.out.println("๐ Thanks for playing!");
Ask yourself: "Is it possible I should skip this entirely?" If yes โ while. If no, it must happen at least once โ do-while. Menu systems, first attempts, and initial prompts almost always use do-while.
do-while guarantees the body (the login attempt) runs at least once before checking whether to retry. A while loop could theoretically skip the attempt entirely if the condition was somehow false from the start.Enhanced for Loop โ "For Each Item in Collection"
The enhanced for (or "for-each") loop gives you clean syntax for iterating over arrays and collections. No index arithmetic, no off-by-one errors โ just "for each item, do this."
for (Type item : collection) { // use item directly โ no index needed! // works with arrays, Lists, Sets, and more }
Need the index variable
Can modify the array
Risk of off-by-one
Cleaner, no index needed
Read-only (can't modify source)
Cannot skip or reverse
๐ฎ Example 1: Displaying Player Inventory
List<String> inventory = Arrays.asList( "๐ก๏ธ Iron Sword", "๐ก๏ธ Wooden Shield", "๐งช Health Potion", "๐งช Mana Potion", "๐ฐ Gold Coin x50", "๐๏ธ Dungeon Key" ); System.out.println("๐ YOUR INVENTORY:"); int slot = 1; for (String item : inventory) { System.out.println(" [" + slot++ + "] " + item); } // [1] ๐ก๏ธ Iron Sword // [2] ๐ก๏ธ Wooden Shield ... etc
๐ฎ Example 2: Calculating Total Damage
int[] hits = {15, 22, 8, 30, 18, 25}; int totalDamage = 0; int critCount = 0; for (int damage : hits) { totalDamage += damage; if (damage >= 25) critCount++; System.out.println(" Hit: " + damage + " dmg"); } System.out.println("๐ฅ Total: " + totalDamage + " | Crits: " + critCount);
๐ฎ Example 3: Leaderboard Display
record PlayerScore(String name, int score) {} List<PlayerScore> leaderboard = List.of( new PlayerScore("ShadowStrike", 98750), new PlayerScore("PixelPwner", 87650), new PlayerScore("CodeCrusher", 82340) ); System.out.println("๐ GLOBAL LEADERBOARD:"); int rank = 1; for (PlayerScore p : leaderboard) { String medal = switch (rank) { case 1 -> "๐ฅ"; case 2 -> "๐ฅ"; case 3 -> "๐ฅ"; default -> " "; }; System.out.printf("%s #%-2d %-15s %,d%n", medal, rank++, p.name(), p.score()); }
for loop instead of the enhanced for loop?for is read-only and index-free. Use a traditional for when you need i (to modify elements via arr[i] = x, to iterate backwards, or to skip certain indexes).Nested Loops โ Grids, Boards & Tile Maps
Nested loops are the key to working with 2D data. Every tile map, game board, pixel buffer, and grid system in game development uses this pattern: outer loop handles rows, inner loop handles columns.
for (int row = 0; row < rows; row++) { // OUTER: rows for (int col = 0; col < cols; col++) { // INNER: columns // Process cell [row][col] // Inner loop completes ALL columns before outer advances } }
Think of a book: the outer loop turns pages (rows), the inner loop reads each word on that page (columns). When you finish a row, you start the next one from the beginning.
๐ฎ Example 1: Tic-Tac-Toe Board
char[][] board = { {'X', 'O', 'X'}, {'O', 'X', ' '}, {' ', 'O', 'X'} }; System.out.println(" 0 1 2"); for (int r = 0; r < board.length; r++) { System.out.print(r + " "); for (int c = 0; c < board[r].length; c++) { System.out.print(board[r][c]); if (c < 2) System.out.print("|"); } if (r < 2) System.out.println("\n -----"); } // Output: // 0 1 2 // 0 X|O|X // ----- // 1 O|X| // ----- // 2 |O|X
๐ฎ Example 2: Tile Map Renderer
// Legend: G=Grass, W=Water, T=Tree, P=Player char[][] world = { {'G','G','G','W','W','W'}, {'G','T','G','W','W','W'}, {'G','G','P','G','G','G'}, }; for (int r = 0; r < world.length; r++) { for (int c = 0; c < world[r].length; c++) { String emoji = switch (world[r][c]) { case 'G' -> "๐ข"; case 'W' -> "๐ต"; case 'T' -> "๐ฒ"; case 'P' -> "๐ง"; default -> "โ"; }; System.out.print(emoji + " "); } System.out.println(); } // ๐ข ๐ข ๐ข ๐ต ๐ต ๐ต // ๐ข ๐ฒ ๐ข ๐ต ๐ต ๐ต // ๐ข ๐ข ๐ง ๐ข ๐ข ๐ข
๐ฎ Example 3: RPG Stat Scaling Table
System.out.println(" STR: 5 10 15 20 25"); System.out.println("LVL ---------------------"); for (int level = 1; level <= 5; level++) { System.out.printf("%-4d", level); for (int str : new int[]{5, 10, 15, 20, 25}) { int damage = level * str / 2; System.out.printf("%4d", damage); } System.out.println(); }
Dungeon Generator
Create a 10ร10 dungeon map using nested loops:
- Fill the border cells (row 0, row 9, col 0, col 9) with walls
'#' - Fill interior cells with floor tiles
'.' - Place a player
'@'at position (5, 5) - Render it with nested loops, printing each row on its own line
Loop Control โ break, continue & Labels
Sometimes you need to exit a loop early or skip an iteration. break and continue give you precise control over loop flow โ and labeled versions let you escape nested loops entirely.
| Statement | Effect | Common Use |
|---|---|---|
| break | Exit the loop immediately | Found what you were searching for |
| continue | Skip to next iteration | Skip invalid/null items |
| label: + break label | Exit outer (nested) loops | Found in 2D grid, stop all loops |
๐ฎ Example 1: Search Inventory (break)
String[] inventory = {"Sword", "Shield", "Potion", "Key", "Map"}; String target = "Key"; for (int i = 0; i < inventory.length; i++) { System.out.println(" Checking slot " + i + ": " + inventory[i]); if (inventory[i].equals(target)) { System.out.println(" โ Found at slot " + i + "!"); break; // Stop searching โ we found it! } } // Checking slot 0: Sword // Checking slot 1: Shield // Checking slot 2: Potion // Checking slot 3: Key // โ Found at slot 3!
๐ฎ Example 2: Process Valid Items (continue)
String[] loot = {"Gold", null, "Sword", "", "Potion", "Gem"}; int validCount = 0; for (String item : loot) { if (item == null || item.trim().isEmpty()) { System.out.println(" โ ๏ธ Skipping empty slot"); continue; // Skip to next item } System.out.println(" โ Added: " + item); validCount++; } System.out.println("Total valid: " + validCount);
๐ฎ Example 3: Labeled break (Find Player in Grid)
int[][] dungeon = { {0, 0, 0, 0}, {0, 1, 0, 2}, // 1=Player, 2=Exit {0, 0, 0, 0} }; int playerRow = -1, playerCol = -1; searchLoop: // Label the OUTER loop for (int r = 0; r < dungeon.length; r++) { for (int c = 0; c < dungeon[r].length; c++) { if (dungeon[r][c] == 1) { playerRow = r; playerCol = c; break searchLoop; // Breaks BOTH loops at once! } } } System.out.println("๐ง Player at (" + playerRow + ", " + playerCol + ")");
Labels can make code hard to read. In production, consider refactoring the nested loop into a separate method that returns early. But for grid searches and game map traversal, labels are perfectly valid.
continue do inside a loop body?continue skips the remaining code in the current iteration and jumps to the update step (for for loops) or rechecks the condition (for while loops). The loop itself keeps going โ only that one iteration is cut short.Capstone โ Turn-Based Combat Prototype
Put it all together. This mini game engine uses every loop type you've learned โ while for the main game loop, do-while for combat rounds, nested while for input validation, and for-each to iterate enemies.
Architecture Overview
Full Combat Engine
import java.util.*; public class CombatDemo { record Entity(String name, int hp, int maxHp, int atk, int def) {} public static void main(String[] args) { Entity player = new Entity("๐ง Hero", 100, 100, 15, 5); List<Entity> enemies = Arrays.asList( new Entity("๐ Rat", 30, 30, 8, 2), new Entity("๐บ Wolf", 50, 50, 12, 4), new Entity("๐ Dragon", 200, 200, 25, 10) ); Scanner sc = new Scanner(System.in); boolean gameOver = false; int wave = 1; // โโโโ MAIN GAME LOOP (while) โโโโ while (!gameOver && wave <= enemies.size()) { Entity enemy = enemies.get(wave - 1); System.out.println("\nโโโ WAVE " + wave + ": " + enemy.name() + " โโโ"); // โโโโ COMBAT LOOP (do-while) โโโโ do { printStatus(player, enemy); // โโโโ INPUT VALIDATION (while) โโโโ int choice = -1; while (choice < 1 || choice > 3) { System.out.print("[1] Attack [2] Heal [3] Flee: "); if (sc.hasNextInt()) choice = sc.nextInt(); else sc.next(); } switch (choice) { case 1 -> attack(player, enemy); case 2 -> heal(player); case 3 -> { System.out.println("๐ You fled!"); gameOver = true; } } if (enemy.hp() > 0 && !gameOver) enemyAttack(enemy, player); if (player.hp() <= 0) { System.out.println("โ ๏ธ YOU DIED."); gameOver = true; } } while (enemy.hp() > 0 && player.hp() > 0 && !gameOver); if (!gameOver) { System.out.println("๐ Defeated! +50 XP"); wave++; } } if (!gameOver) System.out.println("\n๐ VICTORY! All waves cleared!"); sc.close(); } }
Quick Reference Cheatsheet
Practice Exercises
Now that you've mastered loops, move on to Arrays & ArrayLists โ loops are how you'll work with every collection. The combination is where real game code lives.