1. The Shared Skeleton — One Algorithm, Two Costumes
Strip away the domain details and both programs run the same four-step loop:
- Choose a candidate next step.
- Commit to it (mark as active).
- Recurse — try to complete from here.
- If recursion fails → undo the commit and try the next candidate.
- Collect valid orthogonal neighbors of the current island.
- Add one cell to the island.
- Recurse: keep growing from that cell.
- If target size not reached from here → remove the cell, try another neighbor.
- Collect unvisited grid neighbors of the current cell.
- Carve the shared wall; mark the neighbor as visited.
- Recurse: keep carving from the neighbor.
- All neighbors exhausted → return (automatic backtrack via the call stack).
Side-by-side pseudocode — the parts in purple are identical; the colored lines are domain-specific substitutions:
removeCell() physically removes the cell. In maze generation, undo
is implicit — there is nothing to remove because the wall was already carved and the
cell was already marked visited. The "backtrack" is simply the function returning,
letting the for-each loop try the next direction. Both are backtracking;
one just has more visible footprints.
2. What They Share
- ✓ Recursive DFS with backtracking — the call stack is the path memory. When a recursive call returns false (or simply returns), the algorithm has "backed up."
-
✓
Grid / cell model — both live on a 2D grid
addressed by
(row, col)pairs. Both use the sameSWGrid/SWColor/SWPointrendering infrastructure. -
✓
Direction arrays — both iterate over neighbor
offsets (
DR,DC), optionally shuffled, to decide which cell to visit next. -
✓
Pre-recorded step queue — neither algorithm draws
directly. Both record every decision into a step queue first,
then the
draw()loop plays it back one frame at a time.
- ✓ Randomize toggle — shuffle the direction / candidate list for organic variety; leave it in fixed order for deterministic, repeatable results.
- ✓ ADD/BACKTRACK log — every step is visible in a scrollable breadcrumb panel and counted in a live Recursion Cost display, so you can measure the algorithm's efficiency numerically.
-
✓
Java mirror — both sets of JavaScript classes are
deliberate ports of Java source studied in APCS A
(
Island.java,RecursiveIslandDriver.java), reinforcing the same logic in two languages. -
✓
Base case — island:
size === targetSize; maze solver:r === endRow && c === endCol. In both, reaching the goal returnstrueimmediately — no more recursion.
3. Where They Differ
| Dimension | 🏝️ Islands (Stages 3–7) | 🧩 Mazes (Maze 1 & 2) |
|---|---|---|
| Problem domain | Grow an organic blob of cells to a target size on an open ocean. | (Generate) carve a perfect maze; (Solve) navigate S → T through it. |
| Number of algorithms | One (growth / backtrack). BFS appears only as a pre-check in Stage 5. | Two back-to-back: DFS generation, then separately DFS solving — plus a BFS solution highlight for contrast. |
| What "commit" means | Add a cell to the island data structure. removeCell() explicitly undoes it on backtrack. |
Mark a cell visited and carve its wall. The wall stays carved — there is nothing to undo. |
| Backtrack visibility | Moderate — backtracked cells turn a dim color and are removed from the island. | High — solver dead ends flash red then gray; multiple wrong corridors accumulate on screen, making the cost of backtracking viscerally obvious. |
| Shape of success | An irregular connected blob: no particular start/end, just a counted number of cells. | A single linear path from corner to corner; the solution route lights up in gold. |
| Obstacle handling | Ocean pits (Stages 4–7) are hard blocks; the algorithm routes around them by simply having fewer valid candidates. | Walls between cells are the obstacles; they are carved away during generation, leaving open passages the solver can travel. |
| Separation constraint | Stage 6b: 8-direction check prevents islands touching even diagonally — adds significant backtrack cost. | No separation concept; the maze is a single connected structure by design. |
| BFS comparison | Implicit only (Stage 5 pre-check uses BFS to verify reachability before recursing). | Explicit: View Solution runs BFS to highlight the shortest path in gold before the DFS solver runs, directly demonstrating the DFS vs. BFS tradeoff. |
| Stage-by-stage complexity | 7 stages, each adding one concept. The complexity curve is gradual and deliberate. | One app with all concepts present at once. Higher density; better as a capstone after the island saga. |
| Connection to Java source | Direct: Stage 7 mirrors Island.java and Coordinates.java method-for-method. |
Indirect: SWMaze is modeled on the style of SWIsland but has no Java counterpart in the APCS A project. |
4. Pedagogical Strengths — What Each Context Teaches Best
- Intuitive domain. "Grow a blob on a grid" needs no explanation — students immediately understand the goal. The algorithm feels like a helper, not the main character.
-
Explicit undo.
removeCell()makes backtracking physically visible: a cell disappears from the island. Students can point to exactly what was undone, which maps directly to "pop the call stack" in the mental model. - Graduated complexity. Seven stages build on each other — pits, cost metrics, multiple islands, separation rules, OOP refactoring. Each stage's change is a single sentence.
-
Java mirror. Stage 7 replicates
Island.javaline-for-line. A student reading both can see that Java and JavaScript solve the same problem identically. - Infinite patience. Because there is no single "right" shape, every run produces an interesting result and students are never "wrong."
- Backtracking drama. Dead-end corridors that flash red and accumulate on screen make the cost of wrong choices viscerally obvious in a way the island rarely achieves. Students feel the frustration of dead ends.
- DFS vs. BFS contrast. Pressing View Solution shows BFS finding the shortest path in one click, then Solve Maze shows DFS wandering before finding a path. No other demo in the saga makes this distinction so concrete.
- Two-algorithm story. Generation and solving use the same skeleton for different purposes, proving the pattern is truly general — it is not "the island algorithm" but "the DFS algorithm."
- Perfect maze guarantee. Because a perfect maze has exactly one solution, the solver must encounter dead ends to find it. Backtracking is not optional — it is guaranteed.
- Transfer signal. After spending weeks on islands, recognizing the same structure in a completely different domain is a powerful metacognitive moment — "I already know how to read this code."
5. Sequencing: Which Should Come First?
The saga is designed to be explored in order — islands first, maze second. Here is why that sequence works:
- Islands build confidence. The first time a student sees recursive backtracking it should feel manageable. Growing a blob is lower-stakes than navigating a maze — there is no "wrong" shape, and the undo operation is concrete and visible.
- Stages 1–2 provide a manual baseline. Students click cells by hand in Stage 2 before the algorithm takes over in Stage 3. This means they understand what the algorithm is computing before they see how it is computed recursively.
- Each island stage adds one idea. By the time students reach Stage 7, they have seen the algorithm add pits, add cost metrics, grow multiple islands, and move into a class — all incrementally.
- The maze is the capstone. After absorbing seven island stages, seeing the same skeleton in a maze generates a "transfer" moment. The student is not learning a new algorithm — they are recognizing an old friend in new clothes.
- DFS vs. BFS lands harder on familiar ground. The contrast between View Solution (BFS) and Solve Maze (DFS) is the most important new concept the maze introduces. It resonates most strongly once the student already deeply understands DFS from the islands.
6. Backtrack Cost — Are They Comparable?
Both apps display a Recursion Cost panel with a backtrack ratio. But the numbers mean different things:
Measures how hard the algorithm worked to hit the target size. A ratio near 0 % means the island grew almost perfectly; a high ratio means many candidate cells were tried and removed before enough dead ends cleared. Pit density is the primary driver: a pitted ocean forces the algorithm into corners it must escape from.
Measures how many wrong turns the DFS solver took before reaching T. In a perfect maze on a 20 × 14 grid, a ratio of 100–200 % is normal (the solver visits more dead-end cells than solution cells). Randomize OFF often finds a shorter route than Randomize ON on the same maze — never shorter than BFS's gold path, but sometimes surprisingly close.
false. A ratio of 50 % means half the total work was
"wasted" exploring paths that failed. That is not a bug — it is the algorithm
demonstrating exactly why we need backtracking: we cannot know which path is right
without trying it.
7. Questions to Think About
Use these to drive a class discussion or written reflection:
removeCell() when backtracking.
The maze generator does not remove anything — it just returns. Are both of these
really "backtracking"? What is the definition of backtracking that covers both?
8. Explore Both
Seven stages building from a single cell to a fully object-oriented multi-island recursive generator with cost metrics and Java parity.
Open Saga Index →DFS Build + DFS Solve + BFS highlight. The clearest backtracking animation in the saga. Three algorithms, one grid.
Open Maze 1 →Identical to Maze 1 plus one orange color cue marking the exact cell where DFS picks back up after each backtrack. Open side-by-side with Maze 1 to compare.
Open Maze 2 →