字符串条件 tikz

字符串条件 tikz

我正在尝试为棋盘游戏 (Amazons) 制作打印命令。我指定尺寸和棋盘状态,因此 \AmazonsBoard{3}{3}{WXX---BXX} 将绘制一个小型 3x3 棋盘。有 4 种不同的方块类型,“W、B、-、X”,我想为它们各自绘制一些单独的东西。我有的(精简版)代码是,

\documentclass{article}
\usepackage{tikz}

\usepackage{xstring}
\usepackage{xifthen}

\newcommand{\AmazonsBoard}[3]{
\begin{tikzpicture}
\newcounter{index}
\foreach \x in {1,...,#1}
\foreach \y in {1,...,#2}
{
    \setcounter{index}{(\x)+(#2 - \y) * #1};
    \draw[draw = black] (\x, \y) rectangle ++(1, 1);
    \IfStrEq{W}{\StrChar{#3}{\value{index}}} 
    {
        \draw[color= black](\x + 0.5,\y + 0.5) node{\StrChar{#3}{\value{index}}};
    }{}
}
\end{tikzpicture}%
}
\begin{document}

\AmazonsBoard{3}{3}{WXX---BXX}

\end{document}

但这不起作用,因为\IfStrEq{W}{\StrChar{#3}{\value{index}}}。它没有做我认为它应该做的事情,也就是类似的事情if (#3[index] == "W"){}。为什么不是这样,我该如何解决这个问题?

答案1

您不能pgfmath在中使用表达式\setcounter,但这不是唯一的问题。

由于两个原因,它也\StrChar{#3}{\value{index}不能使用\IfStrEq:它不可扩展并且\value{index}不是字符串,而是一个抽象数字。

这有效:

\documentclass{article}
\usepackage{tikz}

\usepackage{xstring}

\newcommand{\AmazonsBoard}[3]{%
  \begin{tikzpicture}
    \foreach \x in {1,...,#1}{
      \foreach \y in {1,...,#2}{
        \pgfmathsetmacro{\tempA}{int((\x)+(#2 - \y) * #1)}
        \draw[draw = black] (\x, \y) rectangle ++(1, 1);
        \StrChar{#3}{\tempA}[\tempB]
        \IfStrEq{W}{\tempB}{%
          \draw[color= black](\x + 0.5,\y + 0.5) node{\tempB};%
        }{}%
      }
    }
  \end{tikzpicture}%
}

\begin{document}

\AmazonsBoard{3}{3}{WXX-W-BXX}

\end{document}

在此处输入图片描述

答案2

您不需要使用一堆条件来检查一个字母WX或者B-可以只定义一些名称中包含该字母的样式,比如说

amazonsBoard/W/.style={fill=red},
amazonsBoard/X/.style={fill=blue!50},
amazonsBoard/B/.style={fill=green},
amazonsBoard/-/.style={fill=gray},

你现在要做的就是

\path[amazonsBoard/\macroThatHasThatLetterStored] …;
% or to be on the safe side
\path[amazonsBoard/\macroThatHasThatLetterStored/.try] …;

(这处理程序.try意味着 PGFKeys 将尝试该密钥,但如果找不到则不会发出任何抱怨。)

如果你现在接受以下形式的输入

{{W,X,X},{-,-,-},{B,X,X}}

即行列表,其中每行都是自己的列表,您的宏可以定义为

\newcommand{\AmazonsBoard}[2][]{%
\begin{tikzpicture}[#1]
\foreach[count=\rowY] \row in {#2} {
  \foreach[count=\colX] \column in \row {
    \draw[black, amazonsBoard/\column/.try]
      (\colX,\rowY) rectangle node{\column} ++(1, 1);
  }
}
\end{tikzpicture}}

\AmazonsBoard[
  amazonsBoard/W/.style={fill=red},
  amazonsBoard/X/.style={fill=blue!50},
  amazonsBoard/B/.style={fill=green},
  amazonsBoard/-/.style={fill=gray},
]{{W,X,X},{-,-,-},{B,X,X}}

你已经得到了

在此处输入图片描述

无需操作字符串。


但你想省去右边的,部分?

在这里,我定义了一个no separator键,它自定义了\foreach列表解析器,以便它只抓取一个标记(即一个字母)并将其用作其元素。(...当然,语法不再起作用。)

现在你只需要给出列数和一些evaluate离子 你的\AmazonsBoard命令可以自行解决其余问题。

代码

\documentclass[tikz]{standalone}
\makeatletter
\pgfkeys{
  /pgf/foreach/no separator/.code={% token for token
    \def\pgffor@scan@custom##1{\def\pgffor@value{##1}\pgffor@scanned}%
    \def\pgffor@scan@custom@comma,{\pgfutil@ifnextchar\pgffor@stop
        \pgffor@scanone{\pgffor@scan@custom,}}%
    \def\pgffor@scan{\pgfutil@ifnextchar,\pgffor@scan@custom@comma{%
      \pgfutil@ifnextchar\pgffor@stop
      \pgffor@scanone\pgffor@scan@custom}}}}
\makeatother
\newcommand{\AmazonsBoard}[3][]{%
\begin{tikzpicture}[#1]
\foreach[
  count=\i from 0, no separator, % ← !
  evaluate=\i as \colX using {mod(\i,#2)},
  evaluate=\i as \rowY using {int(\i/#2)}
] \elem in {#3} {
    \draw[black, amazonsBoard/\elem/.try]
      (\colX,\rowY) rectangle node{\elem} ++(1, 1);}
\end{tikzpicture}}
\begin{document}
\AmazonsBoard[
  amazonsBoard/W/.style={fill=red},
  amazonsBoard/X/.style={fill=blue!50},
  amazonsBoard/B/.style={fill=green},
  amazonsBoard/-/.style={fill=gray},
]{3}{WXX---BXX}
\end{document}

相关内容