Grid Engines
Word Search Generator
Generates word search puzzles dynamically. The database only stores words and clues; the engine generates the grid.
Usage
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);Response
{ "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}Directions
| Direction | Vector | Description |
|---|---|---|
| Horizontal → | [0, 1] | Always available |
| Vertical ↓ | [1, 0] | Always available |
| Diagonal ↘ | [1, 1] | If allowDiagonal: true |
| Diagonal ↙ | [1, -1] | If allowDiagonal: true |
| Horizontal ← | [0, -1] | If allowReverse: true |
| Vertical ↑ | [-1, 0] | If allowReverse: true |
| Diagonal ↖ | [-1, -1] | If both: true |
| Diagonal ↗ | [-1, 1] | If both: true |
Algorithm
- Sort words by length (longest first)
- For each word, try 100 random positions
- Place if no conflict (empty cell or same letter)
- Fill empty cells with random letters (A-Z)
- Return grid + placed words metadata
Crossword Generator
Generates crosswords with automatic backtracking.
Usage
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);Response
{ "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}Algorithm
- Sort words by length (longest first)
- Place first word horizontally in the center
- For each remaining word, find valid intersections with backtracking
- Validate no adjacent letter conflicts
- Retry up to 50 times if it fails
- Fallback to linear mode (separate words) if crossing fails
- Auto-assign clue numbers
Crossing Rules
- A word must share at least one letter with existing words
- No perpendicular adjacent letters that aren’t part of another word
- No letters before or after the word in the same direction
Integration with the Engine
The ExerciseEngineService exposes both generators:
// Word Searchconst ws = engine.generateWordSearch(words, 12, true, false);
// Crosswordconst cw = engine.generateCrossword(words, 10);The VocabularyProcessor uses them internally to evaluate WORD_SEARCH and CROSSWORD exercises.