Cómo se juega
El formato clásico del Juego del 15 utiliza un tablero de cuatro filas por cuatro columnas, con fichas del 1 al 15 y un hueco. En Blupoli ese mismo motor deslizante puede jugarse también en 5×5, 6×6 y 7×7: cambian la cantidad de fichas y la longitud de la solución, pero no la regla fundamental. En cada turno sólo puede deslizarse una ficha que esté junto al hueco, y el objetivo sigue siendo reconstruir el orden numérico por filas dejando el espacio vacío en la esquina inferior derecha.
El prototipo funcionaba, pero no estaba terminado
La implementación inicial podía barajar una cuadrícula, rechazar permutaciones imposibles, mover fichas adyacentes y detectar la solución. Era suficiente para demostrar la mecánica, pero no para cumplir el contrato de producto de Blupoli.
Faltaban persistencia, dificultad, historial, reinicio de la misma mezcla, controles de teclado, estadísticas útiles, localización completa y pruebas automáticas. Incluso había un problema de ciclo de partida: después de resolver una partida y volver a mezclar, el estado compartido de estadísticas podía impedir registrar correctamente la siguiente victoria.
De motor genérico a motor nativo
El Juego del 15 salió del archivo de motores mínimos y pasó a tener un módulo nativo propio. Separar la lógica permite probar la paridad, el generador y las bandas de dificultad sin depender del DOM. También hace posible que npm run check importe el motor y ejecute su selfTest() en CI.
El estado del juego incluye la posición inicial, la posición actual, el historial para deshacer, la pila de rehacer, el número de movimientos, la dificultad y el tiempo activo. Todo se guarda localmente, de modo que cerrar la pestaña ya no significa perder la partida.
La regla que el generador no puede romper
No todas las permutaciones de un tablero deslizante son alcanzables. La paridad divide el espacio de estados en clases y la condición exacta depende de si el ancho del tablero es par o impar. Por eso no generamos una permutación al azar: partimos siempre de la posición resuelta y aplicamos movimientos legales. En el 4×4, por ejemplo, intercambiar únicamente el 14 y el 15 produce una posición imposible de resolver.
En vez de crear una permutación aleatoria y comprobar después si pertenece a la mitad correcta, el nuevo generador parte siempre del tablero resuelto y ejecuta una secuencia de movimientos legales. Por construcción, cualquier posición producida pertenece al mismo componente del espacio de estados y es resoluble.
Cuatro dificultades sin falsificar las reglas
Tamaño y dificultad son controles independientes. 4×4, 5×5, 6×6 y 7×7 cambian la cantidad de fichas; Fácil, Normal, Difícil y Experto cambian la complejidad de la posición inicial. Para estimarla usamos una heurística clásica: distancia Manhattan más conflictos lineales, con umbrales escalados según el número de fichas.
La distancia Manhattan suma cuántas filas y columnas separan cada ficha de su destino. Los conflictos lineales detectan parejas que ya están en su fila o columna objetivo, pero en un orden incompatible, y añaden coste porque necesariamente obligarán a movimientos adicionales.
El generador realiza recorridos legales de longitudes crecientes y sólo acepta posiciones cuyo valor heurístico entra en la banda correspondiente. El selfTest() genera múltiples semillas para cada dificultad y exige que todas sean resolubles, estén sin resolver y caigan dentro de su intervalo de complejidad.
Deshacer, rehacer y reiniciar no son lo mismo
Ahora cada movimiento entra en un historial. Deshacer restaura la posición anterior y Rehacer vuelve a aplicar la posición descartada. Reiniciar recupera exactamente la mezcla inicial y pone a cero movimientos y tiempo. Nueva partida, en cambio, genera otra posición y cuenta como una nueva sesión.
Esta separación también arregla las estadísticas. Blupoli registra tiempo y movimientos de la solución y conserva mejores marcas por dificultad. Cambiar de dificultad crea una nueva partida; reiniciar la actual no infla artificialmente el contador.
Persistencia que respeta el cronómetro
No queríamos que dejar una pestaña abierta toda la noche convirtiera automáticamente una partida en una sesión de ocho horas. El cronómetro cuenta tiempo activo. Cuando la página pasa a segundo plano, se consolida el tiempo acumulado y se guarda el estado; al volver, continúa desde ahí.
La carga también valida lo almacenado antes de aceptarlo: deben existir exactamente los valores del 0 al 15, la configuración debe ser resoluble y la dificultad debe ser una de las conocidas. Un estado local corrupto no debe convertirse en una partida imposible.
Ratón, táctil y teclado
En móvil basta con tocar una ficha adyacente al hueco. En escritorio puede hacerse lo mismo con ratón, pero el tablero es además operable con las cuatro flechas del teclado. El foco visible recae sobre el tablero y cada ficha expone su número, fila, columna y si puede moverse.
El hueco dejó de ser un elemento invisible: ahora forma parte visual del marco y también tiene una etiqueta accesible. Las fichas reciben una animación breve al deslizarse, desactivada automáticamente cuando el sistema solicita reducir movimiento.
Por qué este puzzle fue una fiebre
La historia del Juego del 15 es casi tan interesante como su matemática. Una revisión de la Mathematical Association of America del libro de Jerry Slocum y Dic Sonneveld documenta una enorme ola de popularidad en Estados Unidos durante 1879 y 1880, que se extendió también por Europa, Asia, Nueva Zelanda y Australia.
Durante mucho tiempo se repitió que Sam Loyd había inventado el puzzle. La investigación histórica recogida por Slocum y Sonneveld desmonta esa afirmación: Loyd se atribuyó la invención años después de la primera fiebre. Las fuentes modernas sitúan el origen temprano en el entorno de Noyes Palmer Chapman y describen cómo el puzzle empezó a circular comercialmente a finales de 1879.
La misma revisión de la MAA señala además que sólo la mitad de las posiciones iniciales son resolubles y que el célebre reto con 14 y 15 intercambiados pertenece a la mitad imposible. Ya en 1879–1880 se publicaron demostraciones de esa imposibilidad.
Qué verifica CI
- La posición resuelta satisface la invariante de paridad.
- Intercambiar únicamente 14 y 15 produce una posición imposible.
- Las cuatro dificultades generan posiciones distintas de la solución y siempre resolubles.
- Varias semillas de cada dificultad permanecen dentro de su banda heurística.
- El motor exporta la interfaz nativa que Blupoli exige y puede bloquear el build si rompe una invariante.
Fuentes y referencias
Para la historia y la matemática hemos contrastado la reseña de la Mathematical Association of America sobre The 15 Puzzle: How It Drove the World Crazy, de Jerry Slocum y Dic Sonneveld. Como referencia secundaria sobre la cronología temprana y Noyes Palmer Chapman hemos consultado también la síntesis histórica de 15 puzzle.