6

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.

3
  • 4
    What 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. Commented Nov 27 at 1:15
  • 1
    Please 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. Commented 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. Commented Nov 27 at 8:39

4 Answers 4

11

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}

5
  • Nice 😊 / What if you just draw a double line with round caps? Commented Nov 27 at 4:57
  • @MS-SPO I don't know what you means by double? Is this could make the above two rectangle tangent more sound? Commented Nov 27 at 7:54
  • Thank you so much! Commented Nov 27 at 8:35
  • 1
    @Explorer: this one tikz.dev/tikz-actions#sec-15.3.4 . The inner color might need some opacity. Commented Nov 27 at 8:52
  • 1
    @MS-SPO With double and opacity=.5, I get: i.sstatic.net/mLrnJw2D.png Add opacity is good(I would add it), but is that double was OP after? You could edit my answer directly. :) Commented Nov 27 at 10:18
7

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.

1
  • 1
    This is nice, I'm sure people will be interested to use the code! Commented 2 days ago
5

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}
1
  • 1
    I 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. Commented 2 days ago
5

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}.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.