悠闲数学娱乐论坛(第2版)'s Archiver

色k 发表于 2017-6-11 16:04

之前选择题选项排版的 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]

isee 发表于 2017-6-11 17:03

看着就头大,这代码不友好,长。

色k 发表于 2017-6-11 17:13

[b]回复 [url=http://kuing.orzweb.net/redirect.php?goto=findpost&pid=21704&ptid=4686]2#[/url] [i]isee[/i] [/b]

那不过是因为有四个选项,每次总要重复四次才显得长啊,其实原理是很好理解的。

isee 发表于 2017-6-11 17:42

[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]

有曾看到过四选自动排列的代码,相对要短些,可惜,现在找不到了。。。。

色k 发表于 2017-6-11 17:58

[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 几乎无区别。

isee 发表于 2017-12-13 23:51

[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]

对了,这是不是最终版了?若是想拿来就用了。。
哈哈,虽然一般不超过二十道选择题,手控。。。。

kuing 发表于 2017-12-14 00:03

[b]回复 [url=http://kuing.orzweb.net/redirect.php?goto=findpost&pid=24498&ptid=4686]6#[/url] [i]isee[/i] [/b]

嗯,发完这帖后就没改过了(而且也没实际用过了,已经好久没录入过什么了,懒得要死……)

isee 发表于 2017-12-14 00:21

[b]回复 [url=http://kuing.orzweb.net/redirect.php?goto=findpost&pid=24503&ptid=4686]7#[/url] [i]kuing[/i] [/b]


    你自己写了个“宏包”。。。。。先标记。。。。

kuing 发表于 2018-3-2 17:13

稍微优化了一下,不用 \newlength\lxxa 什么了,后面直接用 \wd\xxboxa 来代替即可。
不过奇怪的是,这样替换后,赋值时(\lxxmax\wd\xxboxc 等)后面要加 \relax,否则有可能会出现错误的判断,不知为什么。

kuing 发表于 2018-3-3 00:43

又改了一下,当 \lxxmax>\lhalf 时还是用回 A. #1 \par B. #2 \par C. #3 \par D. #4 好了。
这是因为如果选项很长(比 \linewidth 还长)时,用 \usebox 的话它不会换行,导致右突出。

另外,如果想让很长的选项换行时能有悬挂缩进,还可以将其改为用列表环境来写,或者用 \hangafter 、\hangindent 什么的,这里就不写了,碰到再说。

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.