在循环中使用数组的正确方法是什么\foreach
?我试图说明汉诺塔问题。我有一组“磁盘大小”/“杆”对序列,我的代码应该按照我的序列在放置在那里的杆上绘制磁盘。但是,数组似乎存在一些问题(我使用arrayjobx
包,但如果更合适,我很乐意切换到其他技术)。
\documentclass{article}
\usepackage{tikz}
\usepackage{arrayjobx}
\begin{document}
\def\sequence{4/1,3/2,2/1,1/2}
\begin{tikzpicture}
\newarray\last
% Initialise \last and print the rod indices
\foreach \rod in {1, 2}{
\last(\rod)={0};
\node at (5 * \rod, -1) {\rod};
}
\foreach \size/\rod in \sequence{
% Load \last(\rod) in variable \y
\checklast(\rod);
\let\l\cachedata;
\xdef\y{\l};
% Update \last(\rod)
\last(\rod)={\y + 1};
% Draw the disk
\draw[ultra thick] (5*\rod - 0.5*\size, \y)--(5*\rod + 0.5*\size, \y);
}
\end{tikzpicture}
\end{document}
我得到以下结果:
而预期的是:
汉诺塔只是一个玩具例子;关键是我的实际情况需要在\foreach
循环内对几个数组进行非连续的读写。
答案1
我定义了三个宏:
\gset
: 表示“全局集”。使用方法如下\gset data[2]=3
\get
: 表示“获取”。使用方法如下\get data[2]
\ginc
: 表示“全局增量”。使用方法如下\ginc data[1]+=2
使用示例:
\documentclass[tikz,border=7mm]{standalone}
% set the value
\def\gset #1[#2]=#3{%
\expandafter\xdef\csname #1#2\endcsname{#3}
}
% get the value
\def\get #1[#2]{%
\csname #1#2\endcsname
}
% increment the value
\def\ginc #1[#2]+=#3{%
\pgfmathparse{\get #1[#2]+#3}%
\gset #1[#2]=\pgfmathresult
}
\begin{document}
% the sequence
\def\sequence{7/1,6/3,5/1,4/1,3/2,2/3,1/3}
\begin{tikzpicture}[line width=4mm, line cap=round,xscale=3,brown!30]
% init colors
\foreach[count=\j] \c in {red,green,blue,orange,pink,purple,gray}
\gset col[\j]={\c};
\edef\numdisks{\j}
% init positions and draw support
\foreach \j in {1,2,3}{
\gset pos[\j]=0
\draw (\j,-.5) -- +(0,3);
}
\draw (.5,-.5) -- +(3,0);
% draw
\foreach[count=\k] \i/\j in \sequence{
\draw[draw={\get col[\i]}] (\j,\get pos[\j]) +(-.4*\i/\numdisks,0) -- +(.4*\i/\numdisks,0);
\ginc pos[\j]+={.5}
}
\end{tikzpicture}
\end{document}
答案2
感谢您的评论。在您的帮助下,我设法弄清楚了如何使用 \csname 机制实现这一点:
\documentclass{article}
\usepackage{tikz}
\begin{document}
\def\sequence{4/1,3/2,2/1,1/2}
\begin{tikzpicture}
% Initialise "last" and print the rod indices
\foreach \rod in {1, 2}{
\expandafter\xdef\csname last@array@\rod\endcsname{0}
\node at (5 * \rod, -1) {\rod};
}
\foreach \size/\rod in \sequence{
% Load last[\rod] in variable \y
\pgfmathparse{\csname last@array@\rod\endcsname}
\let\y=\pgfmathresult
% Update last[\rod]
\pgfmathparse{\y + 1}
\let\newy=\pgfmathresult;
\expandafter\xdef\csname last@array@\rod\endcsname{\newy};
% Draw the disk
\draw[ultra thick] (5*\rod - 0.5*\size, \y)--(5*\rod + 0.5*\size, \y);
}
\end{tikzpicture}
\end{document}