在 Tikz 中使用循環 (For) 內的條件 (If/Else)

在 Tikz 中使用循環 (For) 內的條件 (If/Else)

在我的上一篇文章,我問如何使用兩個循環來建構一個網格,其中包含值。一個完美的回答 是由安德魯·斯旺

\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),但我不知道該把它放在哪裡(我已經嘗試過,但都錯了)。

所以,我的問題是,如何放置狀態(如果/否則)之前,\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 比較和邏輯函數)例如,if和不相等則equal(x,y)返回,否則返回,以及if和 else 則返回,並將它們與和函數一起合併到您的指令中。0xy1greater(x,y)1x>y0evaluateminmax

\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項的函數即可。

分段性質是透過使用notlessgreater函數作為實際感興趣數量的乘數而引入的,其與您所追求的條件具有相同的效果。

人們可以想像一種更一般的情況,它描述了您的第二種情況,它會列印所有數字,直到出現的某些行,之後它在兩側\mx放置許多零作為填充,同時仍然不斷增加該函數似乎所做的事情作業,向上捨入到最接近的整數。\blnkint(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 andless to separate into two cases, and themin function inside theGreater` 函數來確定哪些列應該為零。

相關內容