TikZ 不同的随机整数

TikZ 不同的随机整数

我正在尝试生成 BINGO 卡,但卡上的所有数字都必须不同。以下是我目前得到的结果:

\documentclass[a4paper]{article}
\usepackage{xstring}
\usepackage{tikz}
\usetikzlibrary{calc}

\def\NumOfColumns{5}%
\def\Sequence{1/A/1/15, 2/B/16/30, 3/C/31/45, 4/D/46/60, 5/E/61/71}%

\newcommand{\Size}{1.5cm}
\tikzset{Square/.style={
    inner sep=0pt,
    text width=\Size, 
    minimum size=\Size,
    draw=black,
    fill=white,
    align=center,
    }
}

\begin{document}

\begin{tikzpicture}[draw=black, ultra thick, x=\Size,y=\Size]
    \node [Square] at ($(0.5,-0.5)-(0,0)$) {\Huge B};
    \node [Square] at ($(0.5,-0.5)-(-1.0,0)$) {\Huge I};
    \node [Square] at ($(0.5,-0.5)-(-2.0,0)$) {\Huge N};
    \node [Square] at ($(0.5,-0.5)-(-3.0,0)$) {\Huge G};
    \node [Square] at ($(0.5,-0.5)-(-4.0,0)$) {\Huge O};
    \foreach \row/\rowLetter/\MinNumber/\MaxNumber in \Sequence{%
        \foreach \col/\colLetter/\MinNumber/\MaxNumber in \Sequence {%
            \pgfmathtruncatemacro{\value}{\col+\NumOfColumns*(\row-1)}
            \def\NodeText{\pgfmathparse{random(\MinNumber,\MaxNumber)}\pgfmathresult}
            \pgfmathsetmacro{\ColRowProduce}{\col*\row}
            \IfEq{\ColRowProduce}{9}{% If is center square
                \node [Square] at ($(\col,-\row)-(0.5,0.5)$) {\Huge X};
            }{
                \node [Square] at ($(\col,-\row)-(0.5,0.5)$) {\Huge \NodeText};
            }
        }
    }
\end{tikzpicture}
\end{document}

在此代码中,一列可以有重复的数字。我该如何避免这种情况?

答案1

我曾经定义过\pgfmathrandomitemnorepeat'\pgfmathdeclarerandomlist\pgfmathrandomitem

语法完全相同:首先使用

\pgfmathdeclarerandomlist{⟨list name⟩}{{⟨item-1⟩}{⟨item 2⟩}...}

进而

\pgfmathrandomitemnorepeat{⟨macro⟩}{⟨list name⟩}
\documentclass[a4paper]{article}
\usepackage{xstring}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
    \def\glet{\global\let}
    \def\pgfmathrandomitemnorepeat#1#2{%
        \pgfmath@ifundefined{pgfmath@randomlist@#2}{\pgfmath@error{Unknown random list `#2'}}{%
        \xdef\pgfmath@randomlistlength{\csname pgfmath@randomlist@#2\endcsname}%
        \pgfmathrandominteger{\pgfmath@randomtemp}{1}{\pgfmath@randomlistlength}%
        \expandafter\glet\expandafter#1\csname pgfmath@randomlist@#2@\pgfmath@randomtemp\endcsname%
        \expandafter\glet\expandafter\pgfmathrandomlist@lastitem\csname pgfmath@randomlist@#2@\pgfmath@randomlistlength\endcsname%
        \expandafter\glet\csname pgfmath@randomlist@#2@\pgfmath@randomtemp\endcsname\pgfmathrandomlist@lastitem%
        \expandafter\pgfmathtruncatemacro\csname pgfmath@randomlist@#2\endcsname{\pgfmath@randomlistlength-1}%
        \expandafter\xdef\csname pgfmath@randomlist@#2\endcsname{\csname pgfmath@randomlist@#2\endcsname}%
    }}
    \pgfmathdeclarerandomlist{1-100}{
        {00}{01}{02}{03}{04}{05}{06}{07}{08}{09}
        {10}{11}{12}{13}{14}{15}{16}{17}{18}{19}
        {20}{21}{22}{23}{24}{25}{26}{27}{28}{29}
        {30}{31}{32}{33}{34}{35}{36}{37}{38}{39}
        {40}{41}{42}{43}{44}{45}{46}{47}{48}{49}
        {50}{51}{52}{53}{54}{55}{56}{57}{58}{59}
        {60}{61}{62}{63}{64}{65}{66}{67}{68}{69}
        {70}{71}{72}{73}{74}{75}{76}{77}{78}{79}
        {80}{81}{82}{83}{84}{85}{86}{87}{88}{89}
        {90}{91}{92}{93}{94}{95}{96}{97}{98}{99}
    }


\def\NumOfColumns{5}%
\def\Sequence{1/A/1/15, 2/B/16/30, 3/C/31/45, 4/D/46/60, 5/E/61/71}%
\newcommand{\Size}{1.5cm}
\tikzset{Square/.style={
    inner sep=0pt,
    text width=\Size, 
    minimum size=\Size,
    draw=black,
    fill=white,
    align=center,
    }
}
\begin{document}

\begin{tikzpicture}[draw=black, ultra thick, x=\Size,y=\Size]
    \node [Square] at ($(0.5,-0.5)-(0,0)$) {\Huge B};
    \node [Square] at ($(0.5,-0.5)-(-1.0,0)$) {\Huge I};
    \node [Square] at ($(0.5,-0.5)-(-2.0,0)$) {\Huge N};
    \node [Square] at ($(0.5,-0.5)-(-3.0,0)$) {\Huge G};
    \node [Square] at ($(0.5,-0.5)-(-4.0,0)$) {\Huge O};
    \foreach \row/\rowLetter/\MinNumber/\MaxNumber in \Sequence{%
        \foreach \col/\colLetter/\MinNumber/\MaxNumber in \Sequence {%
            \pgfmathtruncatemacro{\value}{\col+\NumOfColumns*(\row-1)}
            \pgfmathrandomitemnorepeat\NodeText{1-100}
            \pgfmathsetmacro{\ColRowProduce}{\col*\row}
            \IfEq{\ColRowProduce}{9}{% If is center square
                \node [Square] at ($(\col,-\row)-(0.5,0.5)$) {\Huge X};
            }{
                \node [Square] at ($(\col,-\row)-(0.5,0.5)$) {\Huge \NodeText};
            }
        }
    }
\end{tikzpicture}
\end{document}

答案2

您还可以将已经使用的值存储在列表中,将新值与其进行比较,并获取另一个值(如果它在列表中)。

\documentclass[a4paper]{article}
\usepackage{xstring}
\usepackage{tikz}
\usetikzlibrary{calc}

\def\NumOfColumns{5}%
\def\Sequence{1/A/1/15, 2/B/16/30, 3/C/31/45, 4/D/46/60, 5/E/61/71}%

\newcommand{\Size}{1.5cm}
\tikzset{Square/.style={
    inner sep=0pt,
    text width=\Size, 
    minimum size=\Size,
    draw=black,
    fill=white,
    align=center,
    }
}

\newif\ifNumberNotUnique

\begin{document}

\begin{tikzpicture}[draw=black, ultra thick, x=\Size,y=\Size]
    \node [Square] at ($(0.5,-0.5)-(0,0)$) {\Huge B};
    \node [Square] at ($(0.5,-0.5)-(-1.0,0)$) {\Huge I};
    \node [Square] at ($(0.5,-0.5)-(-2.0,0)$) {\Huge N};
    \node [Square] at ($(0.5,-0.5)-(-3.0,0)$) {\Huge G};
    \node [Square] at ($(0.5,-0.5)-(-4.0,0)$) {\Huge O};
    % initialize list of used numbers, needs to be global
    \xdef\NumbersUsed{0}
    \foreach \row/\rowLetter/\MinNumber/\MaxNumber in \Sequence{%
        \foreach \col/\colLetter/\MinNumber/\MaxNumber in \Sequence {%
            \pgfmathtruncatemacro{\value}{\col+\NumOfColumns*(\row-1)}
            % primitive \loop, because a repeat-until is needed
            \loop
                \pgfmathtruncatemacro{\NodeText}{random(\MinNumber,\MaxNumber)}
                % also the \ifNumberNotUnique need to be global
                \global\NumberNotUniquefalse
                % test all used numbers against new number
                \foreach \NewNumber in \NumbersUsed{%
                    \IfEq{\NewNumber}{\NodeText}{%
                        \global\NumberNotUniquetrue
                    }{}%
                }
            \ifNumberNotUnique  
            \repeat
            % add new number to list
            \xdef\NumbersUsed{\NumbersUsed,\NodeText}
            \pgfmathsetmacro{\ColRowProduce}{\col*\row}
            \IfEq{\ColRowProduce}{9}{% If is center square
                \node [Square] at ($(\col,-\row)-(0.5,0.5)$) {\Huge X};
            }{
                \node [Square] at ($(\col,-\row)-(0.5,0.5)$) {\Huge \NodeText};
            }
        }
    }
\end{tikzpicture}

% for debugging
\NumbersUsed\quad\ifNumberNotUnique Shit\else Ok\fi
\end{document}

\Sequence(如果对此有任何顾虑的话,此解决方案的另一个优点是,列中的数字保持在给定的范围内。)

相关内容