在我的上一篇,我问过如何使用两个循环来构造一个带有值的网格。一个精彩的回答 给出的是安德鲁·斯旺。
\documentclass{article}
\usepackage{tikz}
\begin{document}
\def\n{6}
\def\m{8}
\def\s{1.5cm}
\tikz\draw grid[step=\s](\n*\s,\m*\s) foreach[evaluate] \x in {1,...,\n}
{ foreach[evaluate={\z = int(min(\x,\n+1-\x)+\n*min(\y-1,\m-\y)/2)}] \y in {1,...,\m}
{({\s*(.5+(\x-1))},{\s*(\m+.5-\y)}) node{$a=\z$}}};
\end{document}
他提供了一个\z
可以根据不同的价值观排列进行修改的公式。
例如,我做过-
[评估= {\z = int(\x+\n*min(\y-1,\m+\y))}]
这使-
1 2 3 4
5 6 7 8
9 10 11 12
3*4 网格。但如果我想要 -
1 2 2 1
3 4 4 3
5 6 6 5
7 8 8 7
和 ,
1 2 3 4
5 6 7 8
0 9 10 0
0 11 12 0
0 13 14 0
我做不到!我真的很难使用循环和 if else 条件。可能是我太习惯 C++ 和类似的东西了,我可以轻松地做 a=a+1 或写 if 条件。我能想到一种打印上述值排列的方法,使用健康)状况(if/else),但我不知道把它放在哪里(我试过,但都是错的)。
所以我的问题是,如何健康)状况(if/else)之前,\z
以便我可以打印输出,如上所示?
答案1
您可以在 tikz 节点中轻松使用 ifthenelse:
\documentclass{minimal}
\usepackage{tikz}
\usepackage{ifthen}
\begin{document}
\def\n{4}
\def\m{4}
\def\s{1.5cm}
\tikz\draw grid[step=\s](\n*\s,\m*\s)
foreach[evaluate] \x in {1,...,\n} {
foreach[evaluate={
\zt = int(\x+\n*min(\y-1,\m+\y));
\zb = int(\x+(\n-2)*min(\y-1,\m+\y)+3)
}] \y in {1,...,\m} {
({\s*(.5+(\x-1))},{\s*(\m+.5-\y)}) node{$a=\ifthenelse{\y>2}{\ifthenelse{\x=1 \OR \x>3}{0}{\zb}}{\zt}$}
}
};
\end{document}
这将创建您想要的第三个网格。
另请参阅以下问题的答案以获取更多带有 ifthenelse 和循环的示例: TikZ 图内的 If-then-else?
答案2
您可以在 TikZ 中使用“条件赋值”语句,您可能从 C 语言中知道这个语句。语法是result = cond?v0:v1
。如果条件cond
为真,v0
则将赋值给result
,否则v1
赋值给。
此表达式可用作evaluate
代码中键的一部分。此外,该表达式可嵌套在另一个条件赋值中,例如:result = cond1?(cond2?v0:v1):v2
因此,就您而言(代码改编自 val 的答案):
\documentclass[border=1cm]{standalone}
\usepackage{tikz}
\begin{document}
\def\n{4}
\def\m{4}
\def\s{1.5cm}
\noindent\tikz\draw grid[step=\s](\n*\s,\m*\s)
foreach[evaluate] \x in {1,...,\n} {
foreach[evaluate={
\zt = int(\x+\n*min(\y-1,\m+\y));
\zb = int(\x+(\n-2)*min(\y-1,\m+\y)+3);
\zr = \y>2?((\x==1)||(\x>3)?0:\zb):\zt % <-------- see here
}] \y in {1,...,\m} {
({\s*(.5+(\x-1))},{\s*(\m+.5-\y)}) node{\zr}
}
};
\end{document}
其结果为:
答案3
可以使用比较/逻辑数学函数pgf
(3.0.1a 手册中的 89.3.5 比较和逻辑函数)例如,如果和不相等则equal(x,y)
返回,否则返回,以及如果和否则则返回,并将它们与和函数一起合并到您的指令中。0
x
y
1
greater(x,y)
1
x>y
0
evaluate
min
max
\documentclass[tikz,border=5mm]{standalone}
\begin{document}
\def\n{4}
\def\m{6}
\def\blnk{1}
\def\mx{8}
\def\s{1.5cm}
\tikz\draw grid[step=\s](\n*\s,\m*\s) foreach \x in {1,...,\n}
{ foreach[evaluate={\z = int(divide(\n,2)*(\y-1)+min(\x,\n+1-\x))}] \y in {1,...,\m}
{({\s*(.5+(\x-1))},{\s*(\m+.5-\y)}) node{$a=\z$}}};
\tikz\draw grid[step=\s](\n*\s,\m*\s) foreach \x in {1,...,\n}
{ foreach[evaluate={\z = int(notless(\n*(\y-1),\mx)*greater(min(\x-\blnk,\n+1-\x-\blnk),0)*((\n-2*\blnk)*(\y-ceil(divide(\mx,\n))-1) +\x-\blnk+\n*ceil(divide(\mx,\n)))+less(\n*(\y-1),\mx)*(\n*(\y-1)+\x))}] \y in {1,...,\m}
{({\s*(.5+(\x-1))},{\s*(\m+.5-\y)}) node{$a=\z$}}};
\end{document}
对于您的第一个例子,该函数int(divide(\n,2)*(\y-1)+min(\x,\n+1-\x))
似乎符合您的第一个例子,实际上并不需要任何条件,只min
需要具有适当的+\x
和-\x
项的函数。
分段性质是通过使用notless
和greater
函数作为实际感兴趣的数字的乘数来引入的,它们具有与您所追求的条件相同的效果。
我们可以想象一个更普遍的情况来描述你的第二种情况,它打印出所有的数字,直到出现某些行,之后它在两边\mx
放置一些零作为填充,同时仍然不断增加,函数似乎可以完成这项工作,向上舍入到最接近的整数。\blnk
int(notless(\n*(\y-1),\mx)*greater(min(\x-\blnk,\n+1-\x-\blnk),0)*((\n-2*\blnk)*(\y-ceil(divide(\mx,\n))-1)+\x-\blnk+\n*ceil(divide(\mx,\n)))+less(\n*(\y-1),\mx)*(\n*(\y-1)+\x))
ceil
对于仅表示您想要的函数的更简单情况int(notless(\y,3)*greater(min(\x-1,\n-\x),0)*((\n-2)*(\y-3)+\x+7)+less(\y,3)*(4*(\y-1)+\x))
,再次使用notless and
less to separate into two cases, and the
min function inside the
greater` 函数来确定哪些列应该为零。