From iOS to Android in Days: What I Learned Building a Cross-Platform Game with Claude Code

A few weeks ago I finished the iOS version of The Caves — a seeded, deterministic cave exploration game built in Swift 6 and SwiftUI. The iOS app took about three weeks. The Android port, feature-complete and tested, took eight days. Here’s how that happened, and what I’d do the same way again.


It Started with a Spec

Before writing a single line of code, I wrote a plain-text design document. It wasn’t fancy. It described the 68 caves, the movement rules, the twelve hazard types, nine treasures, eight possessions, and how the game ends. It read like notes than a spec — because that’s what it was.

That document became the foundation for everything. When I eventually handed it to Claude Code, it could answer questions by referring to the spec rather than guessing. That mattered more than I expected.


Stories Changed Everything

The spec told what to build. Stories told how much to build at a time.

I broke the iOS app into 22 stories — things like “Seeded Randomizer,” “Cave Entry Evaluator,” “Home Screen UI,” “Per-Cave Audio.” Each story had a clear definition of done. Before implementing each one, Claude Code would write failing unit tests. Then implement enough to make them pass. Then commit. No scope creep. No “while I’m in here” rewrites.

By the time I started the Android port, I had 46 iOS stories to draw from. Each one was a precise description of a unit of behavior — and Android needed almost all of them. I didn’t write the Android stories from scratch. I adapted the iOS stories, adjusted for Kotlin and Jetpack Compose idioms, and added Android-specific stories for SoundPool preloading and rememberSaveable for configuration change handling.

The result: 51 Android stories, fully implemented and committed, in eight days.

When you work with an AI coding assistant, stories are leverage. A vague request produces vague code. A story with a clear scope, acceptance criteria, and a test-first discipline produces code you can trust — and commit with confidence.


The RNG Problem Nobody Warns You About

Here’s the part that surprised me the most.

The Caves is seeded and deterministic. The same number — say, 42 — always generates the same cave layout. That’s the whole point. Players can share seeds, compare scores, and challenge each other to the same run.

When I built the iOS app, I used a Linear Congruential Generator with the Knuth multiplier — a clean, well-understood PRNG. It worked perfectly on iOS.

When I started the Android port, I reached for java.util.Random. It’s built in, it’s fast, it’s obvious. And then I ran the cross-platform parity tests.

The cave maps didn’t match.

Turns out java.util.Random uses a 48-bit LCG with a specific multiplier (0x5DEECE66DL), addend, and bit-shift that is nothing like the Knuth multiplier. Two different algorithms, two different sequences, even with the same seed.

The fix required replacing the iOS Randomizer with a Java-compatible 48-bit LCG — rewriting the core engine to mirror java.util.Random’s exact algorithm in Swift. Once I did that and ran the verification suite (first five outputs for seed 42: [26, 11, 0, 12, 26]), both platforms produced identical cave maps. Same seed, same caves, same game.

The lesson: if cross-platform parity matters, nail down your RNG contract before you build both sides. Retrofitting it cost real time. Deciding it upfront would have cost nothing.


How Claude Code Fit In

I want to be direct about this because the hype around AI coding tools makes it hard to know what’s real.

Claude Code was genuinely fast at the things that are genuinely tedious in mobile development: standing up boilerplate, translating architecture patterns between platforms, wiring state management, writing unit tests for pure logic, and doing code reviews on its own output. The Android GameEngine, CaveEntryEvaluator, MovementEngine, and WarningEngine were all translated from Swift to Kotlin accurately and quickly because the iOS originals were clean and well-tested.

The stories made this work. Because each story had a narrow scope and clear acceptance criteria, Claude Code knew exactly what to build — and more importantly, what not to build. Without that structure, AI-generated code tends to grow in directions you didn’t ask for.

The TDD pattern mattered too. Write a failing test first. Implement to pass it. Commit. This rhythm forced each story to be small enough to fit in a single well-understood context. It also meant that when something was wrong, I knew exactly where to look.


What Required Human Eyes

The things Claude Code couldn’t do: look at a screen and notice it was wrong.

Move buttons that wrapped awkwardly on a real device. Warning badges that overflowed their container at certain text lengths. An ambient audio track that started correctly in tests but failed silently on hardware because of a missing audio focus request. An app icon where both the foreground and background were accidentally set to the same solid color drawable — visible only when you actually installed the app.

None of these were logic errors. None showed up in unit tests. All of them required running the app on a device or simulator and simply looking at it.

This is the part of mobile development that hasn’t changed and probably won’t: the last mile of polish requires a human in the loop with a phone in their hand.


What I’d Recommend

If you’re building a mobile app — or porting one — and you’re thinking about using AI-assisted development, here’s what worked:

Start with a written spec. Even a rough one. It gives the AI something authoritative to reason from, and it gives you something to point to when scope starts drifting.

Break the work into stories. Small, specific, with clear acceptance criteria. The smaller the story, the faster and more accurate the output.

Write tests before code. It forces story scope to stay tight and gives you a safety net for every change that follows.

Lock down your shared contracts early. In my case that was the RNG. In your case it might be an API format, a data schema, or a navigation pattern. Anything that spans platforms or services needs to be agreed on before either side builds to it.

Plan for device time. No amount of unit test coverage replaces running the app on actual hardware. Budget for it at the end of every story, not just at the end of the project.


The Caves is a text-and-image adventure for iOS and Android — 68 caves, nine treasures, and one seed that determines everything. Both apps are built from the same design spec, the same stories, and the same RNG.

The iOS app took three weeks. The Android port took eight days.

The stories did that.


Compliment Circle Games · 2026