Blog · Desarrollo móvil · Marzo 2025

Cómo construí ConnectAll: un juego de puzzle para Android con Kotlin

KotlinAndroidJetpackAdMob
ConnectAll — gráfico de funciones de la aplicación

ConnectAll es un juego de puzzle para Android con un objetivo simple: conecta todos los puntos del tablero trazando líneas sin que se crucen. Un concepto clásico con una ejecución que pone a prueba la arquitectura de la app desde el primer nivel.

En este artículo cuento cómo pasé de la idea inicial al lanzamiento en Google Play: las decisiones de arquitectura, la lógica del motor de juego en Kotlin, el sistema de niveles y cómo integré AdMob sin que arruinase la experiencia de usuario.

La idea y el prototipo

Los juegos de puzzle tienen una ventaja clara para un desarrollador en solitario: el bucle de juego es acotado y la progresión es predecible. No necesitas servidores, no hay estado en tiempo real y la retención se puede trabajar con niveles bien diseñados.

El concepto de ConnectAll es directo: un tablero NxN con pares de puntos de colores. El jugador debe unirlos con líneas que cubran todo el tablero sin cruzarse. La dificultad crece aumentando el tamaño del tablero y el número de pares.

Arquitectura: MVVM con Jetpack

Elegí la arquitectura MVVM desde el principio por dos razones: testabilidad del ViewModel y separación limpia entre la lógica del juego y la interfaz.

Usar StateFlow del paquete kotlinx.coroutines en el ViewModel simplificó la comunicación con la vista: cada cambio de estado del tablero se emite como un nuevo valor y la UI reacciona automáticamente.

data class BoardState( val grid: List<List<Cell>>, val paths: Map<Color, List<Point>>, val isComplete: Boolean ) class GameViewModel : ViewModel() { private val _state = MutableStateFlow(BoardState.empty()) val state: StateFlow<BoardState> = _state.asStateFlow() fun onDrag(from: Point, to: Point) { _state.update { current -> current.applyMove(from, to) } } }

El motor de juego: validación de movimientos

La parte más compleja fue la lógica de validación. Cada movimiento tiene que cumplir tres condiciones:

Modelé el tablero como una matriz de celdas con un estado enumerado: Empty, Dot(color) o Path(color). La validación se reduce a comprobar el estado de la celda destino antes de aplicar el movimiento.

Decisión de diseño: Guardé cada nivel como un archivo JSON en los assets de la app en lugar de una base de datos local. Con niveles prediseñados, no necesitas Room ni SQLite: los archivos se empaquetan con la app y se cargan en memoria con Gson al inicio de cada partida.

Monetización con AdMob sin dañar la UX

Integrar publicidad en un juego de puzzle requiere cuidado: un anuncio en el momento equivocado rompe la concentración y genera reseñas negativas. Decidí usar solo dos formatos:

La clave fue implementar un AdFrequencyManager sencillo que cuenta partidas en SharedPreferences y solo muestra el interstitial cuando se cumple el umbral. De esta forma, los jugadores nuevos completan varios niveles antes de ver su primer anuncio completo.

Lanzamiento en Google Play

El proceso de publicación en Google Play tiene más pasos de lo que parece la primera vez:

El primer lanzamiento tardó unos tres días en ser revisado. A partir del segundo update, las revisiones se resuelven en horas.

Lecciones aprendidas

Prueba ConnectAll en Google Play

Descarga el juego, empieza con los niveles fáciles y sube hasta los más complejos.

↓ Descargar gratis en Google Play Ver ficha de la app →