我正在尝试创建一个由圆形和正方形组成的 10x10 网格,其中对象的位置是随机分配的。
例如,以下代码创建一个 10x10 的网格,其中 80% 是圆形,20% 是正方形,但位置不是随机的:
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\foreach \x in {1,2,3,4,5,6,7,8,9,10}{
\foreach \y in {3,4,5,6,7,8,9,10}{
\begin{scope}[shift={(2*\x,2*\y)}]
\node[circle,draw,minimum size =1.25cm,fill=black] (c) at (0,0){};
\end{scope}
}
}
\foreach \x in {1,2,3,4,5,6,7,8,9,10}{
\foreach \y in {1,2}{
\begin{scope}[shift={(2*\x,2*\y)}]
\node[rectangle,draw,minimum size =1.25cm,fill=black] (c) at (0,0){};
\end{scope}
}
}
\end{tikzpicture}
\end{document}
图像如下所示:
是否可以让 tikz 随机分配对象/节点的位置?
答案1
欢迎来到 TeX.SE。有多种可能性,其中包括\pgfmathrandom
和方便的 ( \pgfmathdeclarerandomlist
, \pgfmathrandomitem
) 对。以下是使用后者的解决方案:
\documentclass[tikz,border=2mm]{standalone}
\begin{document}
\begin{tikzpicture}
\pgfmathdeclarerandomlist{shapes}{{circle}{rectangle}}
\foreach \x in {1,...,10} {
\foreach \y in {1,...,10} {
\pgfmathrandomitem{\myShape}{shapes}
\node[\myShape, draw, minimum size=1.25cm, fill=black] at (2*\x,2*\y) {};
}
}
\end{tikzpicture}
\end{document}
如果各种图片的代码更难分解,您可以使用相同的技术,在和之间随机\macroA
选择\macroB
:
\pgfmathdeclarerandomlist{mymacros}{{\macroA}{\macroB}}
...
\pgfmathrandomitem{\randMacro}{mymacros}
\randMacro
保持圆形和矩形之间的固定比例
根据您的评论,我们现在将重点获取 80% 的圆形和 20% 的矩形。
概率方法
在这种方法中,每次我们将一个项目添加到“画布”时,都会随机选择其形状,圆形的概率为 0.8,矩形的概率为 0.2。在这些条件下,当绘制 100 个项目时,圆圈的数量可以是 0 到 100 之间的任何数字(包括 0 和 100);获得的圆圈数量遵循二项分布带有参数n = 100 且页 =0.8)。
为了实现这一点,您可以重复使用以前的技术,输入列表例如包含四个circle
元素和一个rectangle
元素。这是另一种使用random()
(即\pgfmathrandom
)的方法,它返回 0 到 1 之间的随机浮点数(具有均匀分布):
\documentclass[tikz,border=2mm]{standalone}
\begin{document}
\begin{tikzpicture}
\pgfmathdeclarerandomlist{shapes}{{circle}{rectangle}}
\foreach \x in {1,...,10} {
\foreach \y in {1,...,10} {
\pgfmathsetmacro{\myShape}{(random() < 0.8) ? "circle" : "rectangle"}
\node[\myShape, draw, minimum size=1.25cm, fill=black] at (2*\x,2*\y) {};
}
}
\end{tikzpicture}
\end{document}
注意:使用此方法时,随机种子似乎每分钟都会发生变化(使用 pdfTeX 引擎进行测试)。从钛钾Z 和 PGF 手册:
精确方法
使用以下代码,如果您绘制 100 个项目,其中 80 个将是圆形,20 个将是矩形。此方法的工作原理是创建一个包含 100 个项目(80 个circle
和 20 个rectangle
项目)的列表,随机打乱此列表,然后逐个弹出每个项目。
\documentclass[tikz,border=2mm]{standalone}
\ExplSyntaxOn
% We need global assignments for this sequence because \foreach executes each
% iteration in its own group.
\seq_new:N \g_dave_shapes_seq
\cs_new_protected:Npn \dave_init_shapes:
{
\seq_gclear:N \g_dave_shapes_seq
\int_step_inline:nn { 80 }
{ \seq_gput_right:Nn \g_dave_shapes_seq { circle } }
\int_step_inline:nn { 20 }
{ \seq_gput_right:Nn \g_dave_shapes_seq { rectangle } }
\seq_gshuffle:N \g_dave_shapes_seq
}
\msg_new:nnn { dave } { no-more-items }
{ No~ more~ items~ in~ the~ \token_to_str:N #1 sequence. }
\cs_new_protected:Npn \dave_pop_one_shape:N #1
{
\seq_gpop_left:NN \g_dave_shapes_seq #1
\quark_if_no_value:NT #1
{ \msg_error:nnn { dave } { no-more-items } { \g_dave_shapes_seq } }
}
\cs_new_eq:NN \initShapes \dave_init_shapes:
\cs_new_eq:NN \popOneShape \dave_pop_one_shape:N
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\initShapes
\foreach \x in {1,...,10} {
\foreach \y in {1,...,10} {
\popOneShape{\myShape}
\node[\myShape, draw, minimum size=1.25cm, fill=black] at (2*\x,2*\y) {};
}
}
\end{tikzpicture}
\end{document}