Motores de Grid
Word Search Generator
Genera sopas de letras dinámicamente. La BD solo guarda las palabras y pistas; el motor genera el grid.
Uso
const grid = engine.generateWordSearch( [ { word: 'APPLE', clue: { type: 'TEXT', value: 'A red fruit' } }, { word: 'DOG', clue: { type: 'TEXT', value: 'A loyal pet' } }, ], 12, // gridSize true, // allowDiagonal false, // allowReverse);Respuesta
{ "grid": [ ["A", "P", "P", "L", "E", "X", "K", "M", "R", "T", "W", "Z"], ["B", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "A"], ["...", "...", "...", "...", "...", "...", "...", "...", "...", "...", "...", "..."] ], "placedWords": [ { "word": "APPLE", "clue": { "type": "TEXT", "value": "A red fruit" }, "startRow": 0, "startCol": 0, "direction": [0, 1] } ], "size": 12}Direcciones
| Dirección | Vector | Descripción |
|---|---|---|
| Horizontal → | [0, 1] | Siempre disponible |
| Vertical ↓ | [1, 0] | Siempre disponible |
| Diagonal ↘ | [1, 1] | Si allowDiagonal: true |
| Diagonal ↙ | [1, -1] | Si allowDiagonal: true |
| Horizontal ← | [0, -1] | Si allowReverse: true |
| Vertical ↑ | [-1, 0] | Si allowReverse: true |
| Diagonal ↖ | [-1, -1] | Si ambos: true |
| Diagonal ↗ | [-1, 1] | Si ambos: true |
Algoritmo
- Ordena palabras por longitud (más largas primero)
- Para cada palabra, intenta 100 posiciones aleatorias
- Coloca si no hay conflicto (celda vacía o misma letra)
- Rellena celdas vacías con letras aleatorias (A-Z)
- Retorna grid + metadata de palabras colocadas
Crossword Generator
Genera crucigramas con backtracking automático.
Uso
const crossword = engine.generateCrossword( [ { answer: 'CAT', clue: { type: 'TEXT', value: 'A small animal' } }, { answer: 'ACT', clue: { type: 'TEXT', value: 'To do something' } }, { answer: 'DOG', clue: { type: 'TEXT', value: 'A loyal pet' } }, ], 10, // gridSize);Respuesta
{ "grid": [ ["", "", "C", "", ""], ["", "", "A", "", ""], ["C", "A", "T", "", ""], ["", "", "", "", ""], ["...", "...", "...", "...", "..."] ], "placements": [ { "word": "CAT", "clue": { "type": "TEXT", "value": "A small animal" }, "row": 2, "col": 0, "direction": "across", "number": 1 }, { "word": "ACT", "clue": { "type": "TEXT", "value": "To do something" }, "row": 0, "col": 2, "direction": "down", "number": 1 } ], "size": 10}Algoritmo
- Ordena palabras por longitud (más largas primero)
- Coloca la primera palabra horizontalmente en el centro
- Para cada palabra restante, busca intersecciones válidas con backtracking
- Valida que no haya conflictos de letras adyacentes
- Reintenta hasta 50 veces si falla
- Fallback a modo lineal (palabras separadas) si no se puede cruzar
- Asigna números de pista automáticamente
Reglas de cruce
- Una palabra debe compartir al menos una letra con palabras existentes
- No puede haber letras adyacentes perpendiculares que no formen parte de otra palabra
- No puede haber letras antes o después de la palabra en la misma dirección
Integración con el motor
El ExerciseEngineService expone ambos generadores:
// Word Searchconst ws = engine.generateWordSearch(words, 12, true, false);
// Crosswordconst cw = engine.generateCrossword(words, 10);El VocabularyProcessor los usa internamente para evaluar ejercicios de tipo WORD_SEARCH y CROSSWORD.