7

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.enter image description here

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

12

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}

result

resultt

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
9

I've created a Python program that reads a list of words from a text file and generates all the LaTeX code necessary to produce the game board and the solution, as shown below.

Here is the code on GitHub (PR are welcome)

screenshot

screenshot

  1. Edit the list of words in words.txt
  2. Run python main.py
  3. Run pdflatex main.tex

Note 1. To hide the solutions, comment out the line \input{./game_boards/current.solution} in the main.tex file.

Note 2. The position of each word on the board is random. The script attempts to place each word up to 30 times in random mode. If it fails, the word is skipped. You can change this number by redefining MAXIMAL_NUMBER_OF_TRIES = 30 in variables.py

Note 3. The data for each game board is saved in the game_boards folder. You can restore an old game simply by copying its data into the current files.

5
  • 2
    This is nice, I'm sure people will be interested to use the code! Commented Nov 28 at 16:21
  • 2
    @Marijn, I'll try to clean up the code a little bit and host it on Github ASAP. Commented Dec 1 at 12:51
  • 1
    Ping me too when you publish it! Commented yesterday
  • 1
    @Rmano, done. Please, test it. Commented yesterday
  • Very nice! Thanks... Commented 3 hours ago
5

With soup package:

enter image description here

\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
  • 2
    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 Nov 28 at 16:23
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} 

enter image description here

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

enter image description here

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.