我正在跟进如何扩展宏以在 AMC 的问题中使用它?,正如@Steven B. Segletes 所建议的那样,因此可以回答这个问题。
语境
我正在尝试使用美国管理公司制作带有代码的考试。然而,使用问题中的逐字代码超出了包的范围。他们建议声明方框并在每个问题里面使用它们。
问题
但是,我发现手动创建\newbox
每个问题并插入存在问题。不过,这个问题可以通过两个解决方案部分解决:
一建议使用与问题相同的字符串来命名框(这有助于在命令中自动检索它们
\insertbox
。但是,这很难维护,因为在更改问题的 ID 时需要修改几个地方。此外,它不允许我在同一个问题上使用多个框(不确定这现在是否重要,但有一个更强大的解决方案可能是个好主意)。另一个在方框编号中使用自动增量,这很好。但是,当问题被打乱时,问题中的数字与方框声明的顺序不同(因此不会检索相同的方框)。
我希望的是两全其美:一种简单的方法来维护问题,最好是一种自动(透明)的方式向用户命名,但问题在打乱顺序时仍然与各自的框结合在一起。
例如,下图显示了代码如何按照声明的顺序显示,但是当问题被打乱时,它们可能不会以相同的顺序出现。
\documentclass{article}
\usepackage[box]{automultiplechoice}
\usepackage{listings}
% a simple wrapper to create boxes automatically
\makeatletter
\newcounter{myboxcounter}
\newenvironment{mybox}{%
\stepcounter{myboxcounter}%
\expandafter\newsavebox\csname foobox\roman{myboxcounter}\endcsname
\global\expandafter\setbox\csname foobox\roman{myboxcounter}\endcsname\hbox\bgroup\color@setgroup\ignorespaces
}{%
\color@endgroup\egroup
}
\newcommand{\insertbox}{\stepcounter{myboxcounter}%
\edef\name{foobox\roman{myboxcounter}}\edef\x{%
\expandafter\usebox\csname\name\endcsname}\x}
\makeatother
\begin{document}
%%% preparation of the groups
\begin{mybox}
\begin{lstlisting}[language=C++]
int a = 10;
a = a + 10;
\end{lstlisting}
\end{mybox}
\element{code}{
\begin{question}{code 1}
Which is the result of \texttt{a}? (question of \texttt{a+10})
\insertbox
\begin{choices}
\correctchoice{10}
\wrongchoice{20}
\wrongchoice{0}
\wrongchoice{30}
\end{choices}
\end{question}
}
\begin{mybox}
\begin{lstlisting}[language=C++]
int a = 10;
a = a++;
\end{lstlisting}
\end{mybox}
\element{code}{
\begin{question}{code 2}
Which is the result of \texttt{a}? (question of \texttt{a++})
\insertbox
\begin{choices}
\correctchoice{10}
\wrongchoice{11}
\wrongchoice{12}
\wrongchoice{0}
\end{choices}
\end{question}
}
%%% copies
\AMCrandomseed{123456789}
\onecopy{1}{
\cleargroup{all}
\setcounter{myboxcounter}{0}
\copygroup{code}{all}
\shufflegroup{all}
\insertgroup{all}
}
\end{document}
答案1
也许你可以使用内部 AMC 问题标识符作为框标识符。如果你在构建问题之前调用 mybox,你必须猜测这个标识符,并强制 AMC 在环境mybox
使用后立即设置标识符(因此简单的方法\element
不起作用)。
\documentclass{article}
\usepackage[box]{automultiplechoice}
\usepackage{listings}
\begin{document}
% a simple wrapper to create boxes automatically
\makeatletter
\newcommand{\insertbox}{%
\edef\name{foobox\romannumeral\AMCid@quest}%
\expandafter\usebox\csname\name\endcsname%
}
\newcount\AMC@nextid
\newenvironment{mybox}{%
% what is the next used AMC internal question identifier?
\AMC@nextid=\AMC@numerotation\advance\AMC@nextid\@ne\relax%
% put it in \AMC@nextid@x
\edef\AMC@nextid@x{\romannumeral\AMC@nextid}%
% define the savebox
\expandafter\newsavebox\csname foobox\AMC@nextid@x\endcsname%
% and fill it with requested content
\global\expandafter\setbox\csname foobox\AMC@nextid@x\endcsname\hbox\bgroup\color@setgroup\ignorespaces%
}{%
\color@endgroup\egroup%
}
\newcommand{\codequestion}[3]{% group-id question-id question-content
% force AMC to affect the internal question identifier right now, to question #2
\AMC@prepare{#2}%
\element{#1}{
\begin{question}{#2}#3\end{question}
}
}
\newcommand{\codequestionmult}[3]{%
\AMC@prepare{#2}%
\element{#1}{
\begin{questionmult}{#2}#3\end{questionmult}
}
}
\makeatother
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{mybox}
\begin{lstlisting}[language=C++]
int a = 10;
a = a + 10;
\end{lstlisting}
\end{mybox}
\codequestion{code}{code 1}{
Which is the result of \texttt{a}? (question of \texttt{a+10})
\insertbox
\begin{choices}
\correctchoice{10}
\wrongchoice{20}
\wrongchoice{0}
\wrongchoice{30}
\end{choices}
}
\begin{mybox}
\begin{lstlisting}[language=C++]
int a = 10;
a = a++;
\end{lstlisting}
\end{mybox}
\codequestion{code}{code 2}{
Which is the result of \texttt{a}? (question of \texttt{a++})
\insertbox
\begin{choices}
\correctchoice{10}
\wrongchoice{11}
\wrongchoice{12}
\wrongchoice{0}
\end{choices}
}
%%% copies
\AMCrandomseed{123456789}
\onecopy{5}{
\begin{center}
\Large\bf Exam
\end{center}
\cleargroup{all}
\copygroup{code}{all}
\shufflegroup{all}
\insertgroup{all}
}
\end{document}