之前选择题选项排版的 bug 及改进
话说昨天网友问我选择题选项怎么排版,我就给了《撸题集》里的相关代码。那段代码依赖两个宏包:calc、ifthen,后来想到,既然作为“零件”使用,代码应尽量不依赖宏包才好,于是决定改写一下。
然而改写完在测试的时候,却发现原先的设计其实存在 bug,只不过一般碰不到,所以在撸题集用这么久都没发现。
请看以下示例:[code]\documentclass{article}
\usepackage{calc,ifthen}
\newlength\lxxa
\newlength\lxxb
\newlength\lxxc
\newlength\lxxd
\newlength\lxxmax
\newlength\lhalf
\newlength\lhalfhalf
\newcommand\xx[4]{%
\settowidth\lxxa{A. #1}%
\settowidth\lxxb{B. #2}%
\settowidth\lxxc{C. #3}%
\settowidth\lxxd{D. #4}%
\ifthenelse{
\lengthtest{\lxxa > \lxxb}
}{%
\setlength\lxxmax\lxxa
}{%
\setlength\lxxmax\lxxb
}%
\ifthenelse{
\lengthtest{\lxxmax < \lxxc}
}{%
\setlength\lxxmax\lxxc
}{}%
\ifthenelse{
\lengthtest{\lxxmax < \lxxd}
}{%
\setlength\lxxmax\lxxd
}{}%
\addtolength\lxxmax{1.5em}%
\setlength\lhalf{(\linewidth-\parindent)/2}%
\setlength\lhalfhalf{\lhalf/2}%
\ifthenelse{
\lengthtest{\lxxmax > \lhalf}
}{%
A. #1 \par B. #2 \par C. #3 \par D. #4%
}{%
\ifthenelse{
\lengthtest{\lxxmax > \lhalfhalf}
}{%
\begin{minipage}{\lhalf}
A. #1
\end{minipage}%
\begin{minipage}{\lhalf}
B. #2
\end{minipage}\par
\begin{minipage}{\lhalf}
C. #3
\end{minipage}%
\begin{minipage}{\lhalf}
D. #4
\end{minipage}%
}{%
\begin{minipage}{\lhalfhalf}
A. #1
\end{minipage}%
\begin{minipage}{\lhalfhalf}
B. #2
\end{minipage}%
\begin{minipage}{\lhalfhalf}
C. #3
\end{minipage}%
\begin{minipage}{\lhalfhalf}
D. #4
\end{minipage}%
}%
}}
\begin{document}
\rule{0.3\linewidth}{1ex}
\xx{\rule{0.3\linewidth}{1ex}}234
\end{document}
[/code]结果:
[attach]5100[/attach]
考考大家,为什么同样的 rule 在选项里却变短了呢?
幸好修正它也不难,顺便地,我决定将“四图选项”命令 \fourtuxx 也改写下(原先的只能一行)。[code]\documentclass{article}
\usepackage{graphicx}%以下代码不依赖宏包,加它纯粹为演示图形选项
%预备
\newlength\lxxmax
\newlength\lhalf
\newlength\lhalfhalf
\newsavebox\xxboxa
\newsavebox\xxboxb
\newsavebox\xxboxc
\newsavebox\xxboxd
\newcommand\getboxsandmax[4]{%存放内容并获取最大宽
\sbox\xxboxa{#1}%
\sbox\xxboxb{#2}%
\sbox\xxboxc{#3}%
\sbox\xxboxd{#4}%
\ifdim\wd\xxboxa>\wd\xxboxb
\lxxmax\wd\xxboxa\relax
\else
\lxxmax\wd\xxboxb\relax
\fi
\ifdim\lxxmax<\wd\xxboxc
\lxxmax\wd\xxboxc\relax
\fi
\ifdim\lxxmax<\wd\xxboxd
\lxxmax\wd\xxboxd\relax
\fi
}
%四选项自动排版,用法 \xx{选项}{选项}{选项}{选项}
\newcommand\xx[4]{\par
\getboxsandmax{A. #1}{B. #2}{C. #3}{D. #4}%
\addtolength\lxxmax{1em}%
\setlength\lhalf{\dimexpr(\linewidth-\parindent)/2\relax}%
\setlength\lhalfhalf{.5\lhalf}%
\ifdim\lxxmax>\lhalf
A. #1 \par
B. #2 \par
C. #3 \par
D. #4
\else
\ifdim\lxxmax>\lhalfhalf
\begin{minipage}{\lhalf}
\usebox\xxboxa
\end{minipage}%
\begin{minipage}{\lhalf}
\usebox\xxboxb
\end{minipage}\par
\begin{minipage}{\lhalf}
\usebox\xxboxc
\end{minipage}%
\begin{minipage}{\lhalf}
\usebox\xxboxd
\end{minipage}%
\else
\begin{minipage}{\lhalfhalf}
\usebox\xxboxa
\end{minipage}%
\begin{minipage}{\lhalfhalf}
\usebox\xxboxb
\end{minipage}%
\begin{minipage}{\lhalfhalf}
\usebox\xxboxc
\end{minipage}%
\begin{minipage}{\lhalfhalf}
\usebox\xxboxd
\end{minipage}%
\fi
\fi
}
%四图片选项专用(每图不得太宽)
\newcommand\fourtuxx[4]{\par\vspace{2ex}%
\getboxsandmax{#1}{#2}{#3}{#4}%
\addtolength\lxxmax{1em}%
\setlength\lhalf{.5\linewidth}%
\setlength\lhalfhalf{.5\lhalf}%
\ifdim\lxxmax>\lhalf
images too big! please change width to less than 0.5linewidth-1em.
\else
\ifdim\lxxmax>\lhalfhalf
\noindent
\begin{minipage}[b]{\lhalf}
\centering
\usebox\xxboxa\par A
\end{minipage}%
\begin{minipage}[b]{\lhalf}
\centering
\usebox\xxboxb\par B
\end{minipage}\par\vspace{2ex}%
\noindent
\begin{minipage}[b]{\lhalf}
\centering
\usebox\xxboxc\par C
\end{minipage}%
\begin{minipage}[b]{\lhalf}
\centering
\usebox\xxboxd\par D
\end{minipage}%
\else
\noindent
\begin{minipage}[b]{\lhalfhalf}
\centering
\usebox\xxboxa\par A
\end{minipage}%
\begin{minipage}[b]{\lhalfhalf}
\centering
\usebox\xxboxb\par B
\end{minipage}%
\begin{minipage}[b]{\lhalfhalf}
\centering
\usebox\xxboxc\par C
\end{minipage}%
\begin{minipage}[b]{\lhalfhalf}
\centering
\usebox\xxboxd\par D
\end{minipage}%
\fi
\fi
}
\begin{document}
\newcommand\test{test test test test test test test test test test test test test test test test test test test test test test}
\rule{0.15\linewidth}{1ex} \test
\xx{\rule{0.15\linewidth}{1ex}}234
\rule{0.3\linewidth}{1ex} \test
\xx{\rule{0.3\linewidth}{1ex}}234
\rule{0.5\linewidth}{1ex} \test
\xx{\rule{0.5\linewidth}{1ex}}234
\begin{itemize}
\item\rule{0.15\linewidth}{1ex} \test
\xx{\rule{0.15\linewidth}{1ex}}234
\item\rule{0.3\linewidth}{1ex} \test
\xx{\rule{0.3\linewidth}{1ex}}234
\item\rule{0.5\linewidth}{1ex} \test
\xx{\rule{0.5\linewidth}{1ex}}234
\begin{itemize}
\item\rule{0.15\linewidth}{1ex} \test
\xx{\rule{0.15\linewidth}{1ex}}234
\item\rule{0.3\linewidth}{1ex} \test
\xx{\rule{0.3\linewidth}{1ex}}234
\item\rule{0.5\linewidth}{1ex} \test
\xx{\rule{0.5\linewidth}{1ex}}234
\end{itemize}
\end{itemize}
\test
\fourtuxx
{\includegraphics[width=0.2\linewidth]{example-image}}
{\includegraphics[width=0.2\linewidth]{example-image}}
{\includegraphics[width=0.2\linewidth]{example-image}}
{\includegraphics[width=0.2\linewidth]{example-grid-100x100pt}}
\test
\fourtuxx
{\includegraphics[width=\dimexpr0.5\linewidth-1em\relax]{example-image}}
{\includegraphics[width=\dimexpr0.5\linewidth-1em\relax]{example-image}}
{\includegraphics[width=\dimexpr0.5\linewidth-1em\relax]{example-image}}
{\includegraphics[width=0.45\linewidth]{example-grid-100x100pt}}
The above image width is max, try more 0.01pt will get:
\fourtuxx
{\includegraphics[width=\dimexpr0.5\linewidth-1em+0.01pt\relax]{example-image-a}}
{}{}{}
\end{document}
[/code]代码仍在测试中,效果:
[attach]5924[/attach]
[attach]5925[/attach] 看着就头大,这代码不友好,长。 [b]回复 [url=http://kuing.orzweb.net/redirect.php?goto=findpost&pid=21704&ptid=4686]2#[/url] [i]isee[/i] [/b]
那不过是因为有四个选项,每次总要重复四次才显得长啊,其实原理是很好理解的。 [quote]回复 isee
那不过是因为有四个选项,每次总要重复四次才显得长啊,其实原理是很好理解的。 ...
[size=2][color=#999999]色k 发表于 2017-6-11 17:13[/color] [url=http://kuing.orzweb.net/redirect.php?goto=findpost&pid=21707&ptid=4686][img]http://kuing.orzweb.net/images/common/back.gif[/img][/url][/size][/quote]
有曾看到过四选自动排列的代码,相对要短些,可惜,现在找不到了。。。。 [i=s] 本帖最后由 色k 于 2017-6-11 18:01 编辑 [/i]
[b]回复 [url=http://kuing.orzweb.net/redirect.php?goto=findpost&pid=21709&ptid=4686]4#[/url] [i]isee[/i] [/b]
相信原理都差不多的,肯定不会比我改进前的代码短多少。
重点是原理,上面的代码其实要改短也完全可以,比如将 minipage 环境改成 \parbox ,三行变一行,就会短很多,但我懒得改{:lol:}
习惯了用 minipage,尽管和 \parbox 几乎无区别。 [quote]话说昨天网友问我选择题选项怎么排版,我就给了《撸题集》里的相关代码。
那段代码依赖两个宏包:calc、ift ...
[size=2][color=#999999]色k 发表于 2017-6-11 16:04[/color] [url=http://kuing.orzweb.net/redirect.php?goto=findpost&pid=21700&ptid=4686][img]http://kuing.orzweb.net/images/common/back.gif[/img][/url][/size][/quote]
对了,这是不是最终版了?若是想拿来就用了。。
哈哈,虽然一般不超过二十道选择题,手控。。。。 [b]回复 [url=http://kuing.orzweb.net/redirect.php?goto=findpost&pid=24498&ptid=4686]6#[/url] [i]isee[/i] [/b]
嗯,发完这帖后就没改过了(而且也没实际用过了,已经好久没录入过什么了,懒得要死……) [b]回复 [url=http://kuing.orzweb.net/redirect.php?goto=findpost&pid=24503&ptid=4686]7#[/url] [i]kuing[/i] [/b]
你自己写了个“宏包”。。。。。先标记。。。。 稍微优化了一下,不用 \newlength\lxxa 什么了,后面直接用 \wd\xxboxa 来代替即可。
不过奇怪的是,这样替换后,赋值时(\lxxmax\wd\xxboxc 等)后面要加 \relax,否则有可能会出现错误的判断,不知为什么。 又改了一下,当 \lxxmax>\lhalf 时还是用回 A. #1 \par B. #2 \par C. #3 \par D. #4 好了。
这是因为如果选项很长(比 \linewidth 还长)时,用 \usebox 的话它不会换行,导致右突出。
另外,如果想让很长的选项换行时能有悬挂缩进,还可以将其改为用列表环境来写,或者用 \hangafter 、\hangindent 什么的,这里就不写了,碰到再说。
页:
[1]