Beamer: Tic Tac Toe

Beamer: Tic Tac Toe

Gibt es eine bessere Möglichkeit, ein Tic-Tac-Toe-Spiel in LaTeX aufzubauen? Ich habe derzeit den folgenden Code:

\documentclass{beamer}
\mode<presentation>

\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amsthm}
\usepackage{array}
\usepackage{graphicx}

\begin{document}
\begin{frame}
    \frametitle{A game of noughts and crosses}

    Here is a game of noughts and crosses. On the left we have the game, and on the right the commentary.\\

    \begin{columns}

        \begin{column}{0.1\textwidth}

            \vspace{1.75cm}

            \begin{tabular}{c|c|c}
                & & \\      \hline
                & & \\      \hline
                & &
            \end{tabular}
        \end{column} \pause

        \begin{column}{0.70\textwidth}

            \begin{itemize}
                \item crosses goes first, makes optimal move. A good player will never lose from this start.
            \end{itemize}

        \end{column}

    \end{columns}

\end{frame}
\end{document}

Dadurch wird die Folie in zwei Hälften geteilt, wobei ich auf der einen Seite das Spiel und auf der anderen Seite den Kommentar habe. Ich möchte das Spiel spielen können, indem ich Folie für Folie O und X in das Raster einfüge und gleichzeitig einen Kommentar hinzufüge. Der erste Schritt ist eindeutig:

\begin{tabular}{c|c|c}
                & & \\      \hline
                & X & \\      \hline
                & &
\end{tabular}

Ich frage mich nur, ob es dafür eine bessere Möglichkeit gibt. Wie bringe ich das Spiel dazu, Folie für Folie auszufüllen (d. h. X wird auf Folie 1 abgespielt, O wird auf Folie 2 abgespielt, Kommentar hinzufügen, X wird auf Folie 3 abgespielt usw.).

Antwort1

Wenn es viel wiederholten Code gibt (in diesem Fall für die verschiedenen Spiele), schreibe ich ein Makro, um meine Latex-Datei zu vereinfachen – und um spätere Änderungen bei Bedarf zu erleichtern.

(ICH)Der erste Gedanke, der mir in den Sinn kam, war, ein Makro zu schreiben, das als „Eingabe“ Folgendes verwendet:

  • eine durch Kommas getrennte Liste der Positionen der X's
  • eine durch Kommas getrennte Liste der Positionen der O's
  • der Kommentar

Die X- und O-Positionen würde ich als 1,2,...,9 kodieren, wenn ich im Raster von links nach rechts und von oben nach unten lese. Beispielsweise \NoughtsCrosses{5,6}{9}{Third move}würde

Bildbeschreibung hier eingeben

(II)Eine zweite Möglichkeit besteht darin, anzunehmen, dass die Züge abwechselnd als X,O,X,... stattfinden und einfach eine durch Kommas getrennte Liste der Züge zusammen mit dem Kommentar anzugeben. Beispielsweise \NoughtsCrossesII{5,9,6,4}{Fourth move}würde

Bildbeschreibung hier eingeben

Wie cfr in den Kommentaren zur Frage sagt, möchten Sie diese Befehle wahrscheinlich in etwas wie einschließen, \only<5>{\NoughtsCrossesII{5,9,6,4}{Fourth move}}um jeweils einen Zug anzuzeigen. Ich mache das im MWE unten.

(III)Wenn man die letzte Bemerkung berücksichtigt und ein wenig übertreibt, würde ein intelligenteres Makro einfach eine Liste der Spielzüge und Kommentare nehmen und dann alle Folien für das Spiel im Rahmen erstellen. Alle bisherigen Makros verwenden Tikz und der Tikz- \foreachBefehl ermöglicht mehrere durch einen Schrägstrich getrennte Schleifenvariablen. Der einfachste Weg, dies zu implementieren, ist also die Verwendung der folgenden Syntax:

  \NoughtsCrossesGame{%
     5/First move,
     9/Second move,
     6/Third move,
     4/Fouth move
  }

Die Ausgabe ist „dieselbe“ wie oben, außer dass das „Spiel“ über 4 Folien erscheint. Das Makro \NoughtsCrossesGamenimmt ein optionales Argument an, das sich ähnlich wie das optionale Argument des \pauseBefehls verhält. Das heißt, es fungiert als „Offset“, der steuert, wann die Spielzüge in den Folien für den gegebenen Frame erscheinen.

Hier ist Code, der die Definitionen der drei obigen Makros angibt, vervollständigt zu einem MWE, um zu zeigen, wie sie verwendet werden:

\documentclass{beamer}
\usepackage{tikz}

% Helper macro for placing a node at "position" 1,2,...,9 into the grid
% \PlaceMarker[optional node styling]<position><X or O>
\usepackage{xparse}
\NewDocumentCommand\PlaceMarker{ O{}mm }{%
   \ifnum#2>0
       \def\markercol{#1}
       \def\PlaceMakerNumber{#2}
    \else
       \def\markercol{red}
       \def\PlaceMakerNumber{\numexpr-#2}
    \fi
   \ifcase\PlaceMakerNumber%
      \or\node[\markercol] at (1,3) {#3}; % 1 = (3,1)
      \or\node[\markercol] at (2,3) {#3}; % 2 = (3,2)
      \or\node[\markercol] at (3,3) {#3}; % 3 = (3,3)
      \or\node[\markercol] at (1,2) {#3}; % 4 = (2,1)
      \or\node[\markercol] at (2,2) {#3}; % 5 = (2,2)
      \or\node[\markercol] at (3,2) {#3}; % 6 = (2,3)
      \or\node[\markercol] at (1,1) {#3}; % 7 = (1,1)
      \or\node[\markercol] at (2,1) {#3}; % 8 = (1,2)
      \or\node[\markercol] at (3,1) {#3}; % 9 = (1,3)
   \fi
}

% Creates a noughts and cross game with commentary
%\NoughtsCrosses{x-positions}{y-positions}{Commentary}
\newcommand\NoughtsCrosses[3]{%
  \begin{tikzpicture}
     \foreach \x in {1.5,2.5} {
         \draw[ultra thick](\x,0.5)--+(0,3);
         \draw[ultra thick](0.5,\x)--+(3,0);
     }
     \foreach \x in {#1} {\PlaceMarker{\x}{X}}
     \foreach \y in {#2} {\PlaceMarker{\y}{O}}
     \node[text width=40mm,text ragged, anchor=west] at (5,3) {#3};
  \end{tikzpicture}
}

% Creates a noughts and cross game with commentary
%\NoughtsCrossesII{move positions}{Commentary}
% Moves alternate as X,O,...
\newcommand\NoughtsCrossesII[2]{%
  \begin{tikzpicture}
     \foreach \x in {1.5,2.5} {
         \draw[ultra thick](\x,0.5)--+(0,3);
         \draw[ultra thick](0.5,\x)--+(3,0);
     }
     \foreach \move [count=\m] in {#1} {
         \ifodd\m \PlaceMarker{\move}{X}
         \else\PlaceMarker{\move}{O}
         \fi
     }
     \node[text width=40mm,text ragged, anchor=west] at (5,3) {#2};% add comment
  \end{tikzpicture}
}

% Creates a noughts and cross game with commentary
%\NoughtsCrossesII{move positions}{Commentary}
% Moves alternate as X,O,...
\makeatletter
\newcommand\NoughtsCrossesGame[2][0]{%
  \begin{tikzpicture}
     \foreach \x in {1.5,2.5} {
         \draw[ultra thick](\x,0.5)--+(0,3);
         \draw[ultra thick](0.5,\x)--+(3,0);
     }
     % count length of game
     \foreach \move/\com [count=\lmove] in {#2} {}
     \def\endgame{\the\numexpr\lmove+#1\relax}
     \def\Endgame{\the\numexpr\endgame+1\relax}
     \foreach \move/\com [count=\m,
                          evaluate=\m as \mm using int(\m+#1),
                          evaluate=\move as \mov using int(abs(-\move))] in {#2} {
         \ifodd\m\def\Marker{X}
         \else\def\Marker{O}
         \fi
         \def\mmm{\the\numexpr\mm+1\relax}
         \only<\mm>{\PlaceMarker[blue]{\mov}{\Marker}}
         \ifnum\move<0
            \only<\mmm-\endgame>{\PlaceMarker{\mov}{\Marker}}
            \only<\Endgame->{\PlaceMarker[blue]{\mov}{\Marker}}
         \else
            \only<\mmm->{\PlaceMarker{\mov}{\Marker}}
         \fi
         \only<\mm>{
           \node[text width=40mm,text ragged, anchor=west] at (5,3){\com};
         }
     }
  \end{tikzpicture}
}
\makeatother

\begin{document}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{frame}{A game of noughts and crosses}
  Here is a game of noughts and crosses. On the left we have the
  game, and on the right the commentary.

  \medskip

  \only<2>{\NoughtsCrosses{5}{}{First move}}
  \only<3>{\NoughtsCrosses{5}{9}{Second move}}
  \only<4>{\NoughtsCrosses{5,6}{9}{Third move}}
  \only<5>{\NoughtsCrossesII{5,9,6,4}{Fourth move}}

\end{frame}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{frame}{Another game of noughts and crosses}
  Here is a game of noughts and crosses. On the left we have the
  game, and on the right the commentary.

  \pause Here is a clever game
  \medskip

  \NoughtsCrossesGame[1]{% offset start of game because of \pause above
    -5/First move,
     6/Middle square,
     7/Forcing,
     3/Forced block,
    -9/Forced block leading to a pincer!,
     8/Forced defence!,
    -1/Wins!
  }

\end{frame}

\end{document}

Einige Kommentare:

  • Alle Makros verwendentikzzum Zeichnen der Spiele, da dies eine bessere Kontrolle über die Platzierung der X/O-Marker und beim Zeichnen des Rasters bietet
  • Das \PlaceMarkerMakro ist eine „Hilfsfunktion“ zum Platzieren eines Markers an der angegebenen Position. Diese dient \ifcasedazu, die Positionsindizes 1,2,...,9in (x,y)Koordinaten umzurechnen.
  • Die Makros verwenden \foreacheine Schleife über die durch Kommas getrennte Liste der Markierungspositionen. Das zweite Makro verwendet sie außerdem, \ifoddum zu bestimmen, ob ein X oder ein O platziert werden soll.
  • Der „Kommentar“ wird in einem Tikz-Knoten als unregelmäßiger linker Text mit einer Breite von 40 mm platziert. Möglicherweise müssen Sie die Platzierung der (x,y)-Koordinaten und die Breite des Textes feinabstimmen.
  • Wie in den Kommentaren gefordert, habe ich die Makros verbessert, um das Hervorheben einiger der Züge zu erleichtern. Wenn Sie einen Index für „negative Position“ angeben, wird jetzt das entsprechende Xoder eingefärbt O. Beispielsweise \NoughtsCrosses{-5,-6}{9}{Third move}werden die beiden Xs rot.
  • Amüsanter ist, dass das \NoughtsCrossesGameMakro jetzt jeden Zug einfärbt und dann am Ende des Spiels die letzte „Gewinn“-Serie blau markiert – die Gewinnserie muss wieder mit negativen Positionsindizes hervorgehoben werden. In beiden Fällen wird die Einfärbung durch eine Erweiterung von vorgenommen \PlaceMarker, obwohl die automatische Einfärbung für \NoughtsCrosseskomplizierter ist.

Der Vollständigkeit halber finden Sie hier eine animierte Version der letzten Folie, die das \NoughtsCrossesGameBeispiel erstellt hat:

Bildbeschreibung hier eingeben

Mit Ausnahme des von Beamer erstellten Rahmens ist diese Foliensammlung im Wesentlichen die Ausgabe des Befehls:

\NoughtsCrossesGame[1]{% offset start of game because of \pause above
  -5/First move,
   6/Middle square,
   7/Forcing,
   3/Forced block,
  -9/Forced block leading to a pincer!,
   8/Forced defence!,
  -1/Wins!
}

verwandte Informationen