How can I draw such a "word-search" diagram in TikZ? I need to place the letters on a grid and then to add red horizontal, vertical, diagonal or antidiagonal highlighting boxes as in the picture.
-
4What did you try? Do you know how to make a grid of letters? Do you know how to use TikZ? As you know, this is not a site for "please do this complicated thing for me" type of questions.Sandy G– Sandy G2025-11-27 01:15:37 +00:00Commented Nov 27 at 1:15
-
1Please show your code with what have you tried, what exactly stuck you? How to put them in grid? or how to draw the rounded rectangle? Don't ask "do-this-for-me" question.Explorer– Explorer2025-11-27 01:33:16 +00:00Commented Nov 27 at 1:33
-
You are absolutely right. I didn't expected a complete solution, although I'm grateful for it. What I expected was a hint “do this,” and this would already have saved me a lot of time. The TikZ & PGF v3.1.5b documentation is 1,320 A4 pages long, so any hint from somebody having read it makes my life easier! Sorry for misusing the Web site.yannis– yannis2025-11-27 08:39:10 +00:00Commented Nov 27 at 8:39
4 Answers
Just for reference, you could tune the interface and the parameters:
\documentclass[tikz,border=5pt]{standalone}
% https://tex.stackexchange.com/q/755449/322482
\usepackage{libertinus}
\usetikzlibrary{matrix,backgrounds}
\newlength{\mydrawlinewidth}
\setlength{\mydrawlinewidth}{1pt}
\NewDocumentCommand{\markA}{ O{red} m m }{%
\draw[rounded corners=6mm,opacity=.5, line width=2pt,#1,fill=#1!20]
([xshift=5pt,yshift=-5pt]yannis-#2.north west)
rectangle
([xshift=-5pt,yshift=5pt]yannis-#3.south east);
}
\NewDocumentCommand{\markB}{ O{red} m m }{%
\draw[rounded corners=6mm,opacity=.5,line width=2pt,#1,fill=#1!50]
([yshift=2pt]yannis-#2.north)
-- ([xshift=2pt]yannis-#3.east)
-- ([yshift=-2pt]yannis-#3.south)
-- ([xshift=-2pt]yannis-#2.west)
-- cycle;
}
\begin{document}
\begin{tikzpicture}
\matrix (yannis) [%
matrix of nodes,%
column sep=-\mydrawlinewidth,%
row sep=-\mydrawlinewidth,
nodes={
% draw,
rectangle,anchor=center,
line width=\mydrawlinewidth,
inner sep=2pt,outer sep=0pt,
font=\bfseries\huge,
minimum size=1.5cm,
}
]
{
E & H & A & T & E & U & D & B & L & R & H & S & I & D & S \\
R & E & N & O & U & N & C & E & O & C & W & N & S & N & S \\
T & E & P & K & D & R & D & W & O & O & H & R & N & A & U \\
D & K & S & C & P & C & J & M & G & N & F & K & O & T & B \\
B & W & X & P & F & C & P & Y & H & F & U & N & I & S & M \\
V & W & N & Y & O & A & Q & D & R & E & T & O & T & R & I \\
M & R & G & I & R & N & O & F & G & S & U & D & I & E & T \\
U & I & T & A & N & W & S & D & C & S & R & N & D & D & Q \\
C & S & B & O & V & T & P & I & X & R & E & A & N & N & S \\
V & L & N & J & R & T & B & H & B & Q & C & B & O & U & R \\
E & Y & Z & Q & P & A & G & Y & H & I & E & A & C & F & O \\
X & N & D & M & Q & L & H & B & U & L & L & O & J & L & D \\
C & H & O & F & B & Y & L & P & M & O & C & I & H & F & U \\
Q & R & T & E & N & U & C & R & E & G & R & E & T & E & T \\
P & Z & I & E & N & X & G & Z & A & Q & E & R & F & Y & Y \\
};
\begin{scope}[on background layer]
\markA{2-1}{2-8}
\markA[orange]{2-10}{8-10}
\markB[teal]{2-1}{15-14}
\end{scope}
\end{tikzpicture}
\end{document}
-
Nice 😊 / What if you just draw a double line with round caps?MS-SPO– MS-SPO2025-11-27 04:57:04 +00:00Commented Nov 27 at 4:57
-
@MS-SPO I don't know what you means by
double? Is this could make the above tworectangletangent more sound?Explorer– Explorer2025-11-27 07:54:03 +00:00Commented Nov 27 at 7:54 -
-
1@Explorer: this one tikz.dev/tikz-actions#sec-15.3.4 . The inner color might need some opacity.MS-SPO– MS-SPO2025-11-27 08:52:47 +00:00Commented Nov 27 at 8:52
-
1@MS-SPO With
doubleandopacity=.5, I get: i.sstatic.net/mLrnJw2D.png Addopacityis good(I would add it), but is thatdoublewas OP after? You could edit my answer directly. :)Explorer– Explorer2025-11-27 10:18:23 +00:00Commented Nov 27 at 10:18
Not an answer (too long for a comment and requires image uploads)
I've created a Python program to read a list of words from a text file and create all the LaTeX code necessary to produce the game and the solution, as shown below. If you are interested I can try to host it on GitHub.
-
1This is nice, I'm sure people will be interested to use the code!Marijn– Marijn2025-11-28 16:21:53 +00:00Commented 2 days ago
With soup package:
\documentclass{article}
\usepackage[usetikz=true, highlight=true, highlightcolor=orange, linecolor=red]{soup}
\begin{document}
\begin{alphabetsoup}*[6][6][\sffamily]
\hideinsoup{2}{2}{downright}{a,i,r}
\end{alphabetsoup}
\end{document}
-
1I think this is a very good and clean solution, it doesn't try to "reinvent the wheel" but instead does what the OP wanted in a simple and understandable way.Marijn– Marijn2025-11-28 16:23:44 +00:00Commented 2 days ago
I find it too tedious to type a 15×15 matrix manually and then, when highlighting the various “words” placed horizontally, vertically, or diagonally, to count the exact cells where each word begins and ends.
It is much easier to let LaTeX do this automatically.
The code below requires only entering the rows themselves; LaTeX will construct the table.
The table supports both row and column numbering.
Both the numbering and the grid can be turned off using the keys \WSsetgrid and \WSsetnumbers.
In the first example below, both switches are in the off position.
\documentclass[tikz,border=5pt]{standalone}
\usepackage{xstring}
\usetikzlibrary{calc}
% ===== Switches for grid and numbering =====
\newif\ifWSshowgrid
\newif\ifWSshownumbers
% default values:
\WSshowgridtrue % show the grid
\WSshownumbersfalse % do not show the numbering
\let\WSshowgridon\WSshowgridtrue
\let\WSshowgridoff\WSshowgridfalse
\let\WSshownumberson\WSshownumberstrue
\let\WSshownumbersoff\WSshownumbersfalse
\newcommand\WSsetgrid[1]{%
\csname WSshowgrid#1\endcsname
}
\newcommand\WSsetnumbers[1]{%
\csname WSshownumbers#1\endcsname
}
% ===== Field dimensions: rows / columns =====
\newcounter{wsrow} % internal counter
\newcommand\WSrows{0}% total number of rows
\newcommand\WScols{0}% total number of columns
\newcommand\WSreset{%
\setcounter{wsrow}{0}%
\gdef\WSrows{0}%
\gdef\WScols{0}%
}
% #1 = a row of letters without spaces
\newcommand\WSrow[1]{%
\stepcounter{wsrow}%
% store the total number of rows
\xdef\WSrows{\arabic{wsrow}}
\StrLen{#1}[\rowlen]%
% store the number of columns from the first row
\ifnum\value{wsrow}=1\relax
\xdef\WScols{\rowlen}%
\fi
\foreach \c in {1,...,\rowlen}{%
\StrChar{#1}{\c}[\thischar]%
\node (m-\arabic{wsrow}-\c) at (\c,-\arabic{wsrow}) {\thischar};%
}%
}
% style of the box around a word
\tikzset{
ws box/.style={
draw=red,
line width=2pt,
rounded corners=10pt,
fill=none
}
}
% half of the rectangle “thickness”
\newcommand\WSoffset{10pt}
\newcommand\WSgrow{10pt}
% (r1,c1) and (r2,c2) — first and last letters of a word
% nodes are named m-<row>-<col>
% #1 — additional TikZ options (for example, draw=..., fill=..., fill opacity=...)
\newcommand\RWord[5][]{%
% A' and B' – A and B extended by \WSgrow along the word direction
\path
coordinate (wsA) at
($(m-#2-#3.center)!-\WSgrow!(m-#4-#5.center)$)
coordinate (wsB) at
($(m-#4-#5.center)!-\WSgrow!(m-#2-#3.center)$);
%
\draw[ws box,#1]
($(wsA)!\WSoffset!90:(wsB)$)
--
($(wsA)!-\WSoffset!90:(wsB)$)
--
($(wsB)!\WSoffset!90:(wsA)$)
--
($(wsB)!-\WSoffset!90:(wsA)$)
-- cycle;
}
\begin{document}
% ==== rendering mode ====
% debugging (grid + numbering):
\WSsetgrid{off}\WSsetnumbers{off}
\begin{tikzpicture}[
every node/.style={
minimum size=6mm,
font=\ttfamily\large,
}
]
\WSreset
\WSrow{EHATEUDBLRHSIDS}
\WSrow{RENOUNCEOCWNSNS}
\WSrow{TEPKDRDWOOHRNAU}
\WSrow{DKSCPCJMGNFKOTB}
\WSrow{BWXPFCPYHFUNISM}
\WSrow{VWNYOAQDRETOTRI}
\WSrow{MRGIRNOFGSUDIET}
\WSrow{UITANWSDCSRNDDQ}
\WSrow{CSBOVTPIXREANNS}
\WSrow{VLNJRTBHBQCBOUR}
\WSrow{EYZQPAGYHIEACFO}
\WSrow{XNDMQLHBULLOJLD}
\WSrow{CHOFBYLPMOCIHFU}
\WSrow{QRTENUCREGRETET}
\WSrow{PZIENXGZAQERFYY}
% ----- grid with full frame -----
\ifWSshowgrid
% internal horizontal lines
\foreach \r in {1,...,\numexpr\WSrows-1\relax}{%
\draw[gray!40] (0.5,-\r+0.5) -- (\WScols+0.5,-\r+0.5);
}
% internal vertical lines
\foreach \c in {1,...,\numexpr\WScols-1\relax}{%
\draw[gray!40] (\c+0.5,-0.5) -- (\c+0.5,-\WSrows-0.5);
}
% outer frame
\draw[gray!60] (0.5,-0.5) rectangle (\WScols+0.5,-\WSrows-0.5);
\fi
% ----- numbering of rows and columns -----
\ifWSshownumbers
% row numbers on the left
\foreach \r in {1,...,\WSrows}{%
\node[anchor=east,font=\scriptsize]
at (0,-\r) {\r};
}
% column numbers on the top
\foreach \c in {1,...,\WScols}{%
\node[anchor=south,font=\scriptsize]
at (\c,-0.1) {\c};
}
\fi
\RWord[blue]{1}{2}{1}{6}
\RWord{1}{2}{7}{2}
\RWord{1}{2}{5}{6}
\RWord[fill=orange,opacity=0.4]{3}{4}{8}{4}
\RWord[green!80!black,]{4}{3}{15}{14}
\RWord[fill=yellow!40,fill opacity=0.5]{7}{4}{12}{9}
\RWord{12}{1}{12}{9}
\RWord{13}{1}{13}{10}
\RWord{7}{9}{3}{13}
\end{tikzpicture}
\end{document}
P.S.
I have added support for filling and for adjusting its transparency.
I have also included images that illustrate the remaining three possible combinations of the two switches \WSsetgrid{on/off} and \WSsetnumbers{on/off}.