Skip to content

Commit d8e2658

Browse files
authored
Update ex4-layered-bug.md
1 parent 093c47a commit d8e2658

1 file changed

Lines changed: 21 additions & 23 deletions

File tree

src/ex4-layered-bug.md

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,10 @@ We’ll add two more files:
2828
```java
2929
public class InputParser {
3030

31-
// Parses level from an input string like "level:3"
3231
public static int parseLevel(String input) {
33-
// BUG 1: assumes the string always has "level:" and a valid number
3432
String[] parts = input.split(":");
35-
String numberPart = parts[1]; // can throw if input is wrong
33+
String numberPart = parts[1];
3634

37-
// BUG 2: doesn't trim spaces, can cause NumberFormatException
3835
return Integer.parseInt(numberPart);
3936
}
4037
}
@@ -45,7 +42,6 @@ public class InputParser {
4542
```java
4643
public class LevelLoader {
4744

48-
// Returns an array of enemy counts for the given level.
4945
public static int[] loadEnemiesForLevel(int level) {
5046
if (level == 1) {
5147
return new int[] {2, 3};
@@ -54,16 +50,14 @@ public class LevelLoader {
5450
} else if (level == 3) {
5551
return new int[] {10};
5652
} else {
57-
// BUG 3: unexpected control flow – returns null instead of empty array
5853
return null;
5954
}
6055
}
6156

62-
// Computes a "difficulty" score from enemy counts.
6357
public static int computeDifficulty(int[] enemies) {
58+
int enemyCount = (enemies == null) ? 0 : enemies.length;
6459
int difficulty = 0;
6560

66-
// BUG 4: off‑by‑one and assumes enemies is never null
6761
for (int i = 0; i <= enemies.length; i++) {
6862
difficulty += enemies[i] * (i + 1);
6963
}
@@ -73,42 +67,45 @@ public class LevelLoader {
7367
}
7468
```
7569

76-
### Update `GameApp.java`
70+
### Update `Main.java`
7771

78-
Add this method to the bottom of `GameApp` (inside the class, after `printPlayerStats`):
72+
Add this method to the bottom of `Main` (inside the class, after `printPlayerStats`):
7973

8074
```java
8175
private static void demoLevels() {
8276
System.out.println("=== Level Loader Demo ===");
8377

84-
String input = "level: 4"; // note the space before 4
78+
String input = "level: 4";
8579
System.out.println("Parsing input: \"" + input + "\"");
8680

8781
int level = InputParser.parseLevel(input);
8882
System.out.println("Parsed level: " + level);
8983

9084
int[] enemies = LevelLoader.loadEnemiesForLevel(level);
85+
int enemyCount = (enemies == null) ? 0 : enemies.length;
9186
int difficulty = LevelLoader.computeDifficulty(enemies);
9287

9388
System.out.println("Total difficulty for level " + level + ": " + difficulty);
9489
}
9590
```
9691

92+
`enemyCount` is there so you can inspect length in the debugger (OnlineGDB does not show array length reliably).
93+
9794
Then, in `main`, after the `mystery` player block, add:
9895

9996
```java
10097
demoLevels();
10198
```
10299

103-
Make sure `GameApp.java` now:
100+
Make sure `Main.java` now:
104101

105102
- Uses `Player`, `ScoreUtils`, `LevelLoader`, and `InputParser`.
106103

107104
---
108105

109106
## 2. Run and observe
110107

111-
1. Open `GameApp.java`.
108+
1. Open `Main.java`.
112109
2. Click **Run**.
113110

114111
**Expected symptoms**:
@@ -131,16 +128,15 @@ Use the debugger to trace the whole path:
131128

132129
1. Set a breakpoint at the first line of `demoLevels`.
133130
2. Click **Debug**.
134-
3. When paused:
131+
3. Click the green **Start** button.
132+
4. When paused:
135133
- **Step Over** the print statements.
136134
- Use **Step Into** on `InputParser.parseLevel(input)`.
137135

138136
Inside `parseLevel`:
139137

140138
1. Inspect `input`, `parts`, and `numberPart`.
141-
2. Step line‑by‑line and watch for:
142-
- `ArrayIndexOutOfBoundsException` on `parts[1]`.
143-
- `NumberFormatException` on `Integer.parseInt`.
139+
2. Step line-by-line and identify exactly where and why the first failure happens.
144140

145141
Once you understand the problem, stop debugging and **fix `parseLevel`** to:
146142

@@ -152,7 +148,7 @@ Run again with the debugger to confirm the parsing step works.
152148

153149
---
154150

155-
## 4. Follow the null / off‑by‑one bugs
151+
## 4. Follow the next bug after parse is fixed
156152

157153
Next, set a breakpoint on:
158154

@@ -162,13 +158,15 @@ int[] enemies = LevelLoader.loadEnemiesForLevel(level);
162158

163159
1. Debug again and **Step Into** `LevelLoader.loadEnemiesForLevel`.
164160
2. For the given `level`, see which branch runs and what it returns.
165-
3. Step back to `demoLevels` and then **Step Into** `computeDifficulty`.
161+
3. Fix the null issue you observe first.
162+
4. Re-run Debug and Start.
163+
5. Step back to `demoLevels` and then **Step Into** `computeDifficulty`.
166164

167-
Inside `computeDifficulty`:
165+
Inside `computeDifficulty` (only **after** the null-related issue is fixed):
168166

169-
1. Watch the values of `i`, `enemies.length`, and `difficulty`.
170-
2. See what happens when `i` equals `enemies.length`.
171-
3. If `enemies` is null, notice how that changes things.
167+
1. Watch the values of `i`, **`enemyCount`** (the local `int` in `computeDifficulty`), and `difficulty`.
168+
2. See what happens when `i` reaches the same value as `enemyCount`.
169+
3. Use that to isolate the loop issue.
172170

173171
Fix the bugs by:
174172

0 commit comments

Comments
 (0)