tinusg/word-search

Word search puzzle generator: hides words in an N×N grid in eight directions, with optional hidden message in the leftover cells

Maintainers

Package info

github.com/tinusg/word-search

pkg:composer/tinusg/word-search

Transparency log

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-07-17 08:51 UTC

This package is auto-updated.

Last update: 2026-07-17 08:56:43 UTC


README

Generate word search puzzles in pure PHP. Hides words in an N×N letter grid across all eight directions and returns the solution coordinates, so you can render the puzzle and the answer key.

  • Zero dependencies — plain PHP 8.2+, no framework required
  • Deterministic — pass a seed and get the same puzzle every time (great for shareable/permalink puzzles and tests)
  • Hidden message mode — the leftover cells spell out a secret message in reading order
  • Quality-aware search — backtracking placement with restarts guarantees a share of diagonal words instead of boring row-stacked grids

See it in action: the Emoji (in Dutch) word search maker at emojioneel.nl/woordzoeker.

Installation

composer require tinusg/word-search

Usage

use TinusG\WordSearch\WordSearchGrid;

$puzzle = new WordSearchGrid(
    size: 13,
    words: ['elephant', 'giraffe', 'penguin', 'crocodile', 'butterfly', /* … */],
);

$puzzle->grid();        // 13×13 array of single uppercase letters
$puzzle->placedWords(); // [['word' => 'ELEPHANT', 'cells' => [['row' => 2, 'col' => 5], …]], …]
$puzzle->wordList();    // sorted list of the words that made it into the grid

Words are normalized automatically: uppercased, deduplicated, and skipped when they contain non-A–Z characters, are shorter than 3 letters, or don't fit the grid. Supply more words than the target count and the generator picks a good mix.

Reproducible puzzles

$puzzle = new WordSearchGrid(13, $words, seed: 20260717);

Same seed + same input = same puzzle. Handy for "puzzle of the day" pages and snapshot tests.

Hidden message

Fill the unused cells with a secret message instead of random letters. Solvers find it by crossing out all the listed words and reading the leftovers:

$puzzle = new WordSearchGrid(13, $words, seed: 7, message: 'Happy birthday!');

$puzzle->encodedMessage(); // 'HAPPYBIRTHDAY' — letters only, as embedded

The generator runs an exact-cover style search so the placed words cover every cell except exactly the ones needed for the message. Throws InvalidArgumentException when the message is longer than the grid, and RuntimeException when no exact cover can be found for the given word pool — supply more (and more varied) words if that happens.

Grid sizes

Any size works. Sizes 11, 13, and 15 have tuned target word counts (10, 13, and 16 words); other sizes default to one word per row:

WordSearchGrid::targetWordCount(13); // 13

Testing

composer test

License

MIT. See LICENSE.

Special thanks to Puzzelpedia.