免費論壇 繁體 | 簡體
Sclub交友聊天~加入聊天室當版主
分享
返回列表 发帖

之前选择题选项排版的 bug 及改进

话说昨天网友问我选择题选项怎么排版,我就给了《撸题集》里的相关代码。
那段代码依赖两个宏包:calc、ifthen,后来想到,既然作为“零件”使用,代码应尽量不依赖宏包才好,于是决定改写一下。
然而改写完在测试的时候,却发现原先的设计其实存在 bug,只不过一般碰不到,所以在撸题集用这么久都没发现。
请看以下示例:
  1. \documentclass{article}
  2. \usepackage{calc,ifthen}
  3. \newlength\lxxa
  4. \newlength\lxxb
  5. \newlength\lxxc
  6. \newlength\lxxd
  7. \newlength\lxxmax
  8. \newlength\lhalf
  9. \newlength\lhalfhalf
  10. \newcommand\xx[4]{%
  11. \settowidth\lxxa{A. #1}%
  12. \settowidth\lxxb{B. #2}%
  13. \settowidth\lxxc{C. #3}%
  14. \settowidth\lxxd{D. #4}%
  15. \ifthenelse{
  16.     \lengthtest{\lxxa > \lxxb}
  17. }{%
  18.     \setlength\lxxmax\lxxa
  19. }{%
  20.     \setlength\lxxmax\lxxb
  21. }%
  22. \ifthenelse{
  23.     \lengthtest{\lxxmax < \lxxc}
  24. }{%
  25.     \setlength\lxxmax\lxxc
  26. }{}%
  27. \ifthenelse{
  28.     \lengthtest{\lxxmax < \lxxd}
  29. }{%
  30.     \setlength\lxxmax\lxxd
  31. }{}%
  32. \addtolength\lxxmax{1.5em}%
  33. \setlength\lhalf{(\linewidth-\parindent)/2}%
  34. \setlength\lhalfhalf{\lhalf/2}%
  35. \ifthenelse{
  36.     \lengthtest{\lxxmax > \lhalf}
  37. }{%
  38. A. #1 \par B. #2 \par C. #3 \par D. #4%
  39. }{%
  40.     \ifthenelse{
  41.         \lengthtest{\lxxmax > \lhalfhalf}
  42.     }{%
  43.         \begin{minipage}{\lhalf}
  44.         A. #1
  45.         \end{minipage}%
  46.         \begin{minipage}{\lhalf}
  47.         B. #2
  48.         \end{minipage}\par
  49.         \begin{minipage}{\lhalf}
  50.         C. #3
  51.         \end{minipage}%
  52.         \begin{minipage}{\lhalf}
  53.         D. #4
  54.         \end{minipage}%
  55.     }{%
  56.         \begin{minipage}{\lhalfhalf}
  57.         A. #1
  58.         \end{minipage}%
  59.         \begin{minipage}{\lhalfhalf}
  60.         B. #2
  61.         \end{minipage}%
  62.         \begin{minipage}{\lhalfhalf}
  63.         C. #3
  64.         \end{minipage}%
  65.         \begin{minipage}{\lhalfhalf}
  66.         D. #4
  67.         \end{minipage}%
  68.     }%
  69. }}

  70. \begin{document}

  71. \rule{0.3\linewidth}{1ex}

  72. \xx{\rule{0.3\linewidth}{1ex}}234

  73. \end{document}
复制代码
结果:
QQ截图20170611145949.png
2017-6-11 16:04


考考大家,为什么同样的 rule 在选项里却变短了呢?


幸好修正它也不难,顺便地,我决定将“四图选项”命令 \fourtuxx 也改写下(原先的只能一行)。
  1. \documentclass{article}
  2. \usepackage{graphicx}%以下代码不依赖宏包,加它纯粹为演示图形选项

  3. %预备
  4. \newlength\lxxmax
  5. \newlength\lhalf
  6. \newlength\lhalfhalf
  7. \newsavebox\xxboxa
  8. \newsavebox\xxboxb
  9. \newsavebox\xxboxc
  10. \newsavebox\xxboxd
  11. \newcommand\getboxsandmax[4]{%存放内容并获取最大宽
  12. \sbox\xxboxa{#1}%
  13. \sbox\xxboxb{#2}%
  14. \sbox\xxboxc{#3}%
  15. \sbox\xxboxd{#4}%
  16. \ifdim\wd\xxboxa>\wd\xxboxb
  17. \lxxmax\wd\xxboxa\relax
  18. \else
  19. \lxxmax\wd\xxboxb\relax
  20. \fi
  21. \ifdim\lxxmax<\wd\xxboxc
  22. \lxxmax\wd\xxboxc\relax
  23. \fi
  24. \ifdim\lxxmax<\wd\xxboxd
  25. \lxxmax\wd\xxboxd\relax
  26. \fi
  27. }

  28. %四选项自动排版,用法 \xx{选项}{选项}{选项}{选项}
  29. \newcommand\xx[4]{\par
  30. \getboxsandmax{A. #1}{B. #2}{C. #3}{D. #4}%
  31. \addtolength\lxxmax{1em}%
  32. \setlength\lhalf{\dimexpr(\linewidth-\parindent)/2\relax}%
  33. \setlength\lhalfhalf{.5\lhalf}%
  34. \ifdim\lxxmax>\lhalf
  35.     A. #1 \par
  36.     B. #2 \par
  37.     C. #3 \par
  38.     D. #4
  39. \else
  40.     \ifdim\lxxmax>\lhalfhalf
  41.         \begin{minipage}{\lhalf}
  42.         \usebox\xxboxa
  43.         \end{minipage}%
  44.         \begin{minipage}{\lhalf}
  45.         \usebox\xxboxb
  46.         \end{minipage}\par
  47.         \begin{minipage}{\lhalf}
  48.         \usebox\xxboxc
  49.         \end{minipage}%
  50.         \begin{minipage}{\lhalf}
  51.         \usebox\xxboxd
  52.         \end{minipage}%
  53.     \else
  54.         \begin{minipage}{\lhalfhalf}
  55.         \usebox\xxboxa
  56.         \end{minipage}%
  57.         \begin{minipage}{\lhalfhalf}
  58.         \usebox\xxboxb
  59.         \end{minipage}%
  60.         \begin{minipage}{\lhalfhalf}
  61.         \usebox\xxboxc
  62.         \end{minipage}%
  63.         \begin{minipage}{\lhalfhalf}
  64.         \usebox\xxboxd
  65.         \end{minipage}%
  66.     \fi
  67. \fi
  68. }

  69. %四图片选项专用(每图不得太宽)
  70. \newcommand\fourtuxx[4]{\par\vspace{2ex}%
  71. \getboxsandmax{#1}{#2}{#3}{#4}%
  72. \addtolength\lxxmax{1em}%
  73. \setlength\lhalf{.5\linewidth}%
  74. \setlength\lhalfhalf{.5\lhalf}%
  75. \ifdim\lxxmax>\lhalf
  76. images too big! please change width to less than 0.5linewidth-1em.
  77. \else
  78.     \ifdim\lxxmax>\lhalfhalf
  79.         \noindent
  80.         \begin{minipage}[b]{\lhalf}
  81.         \centering
  82.         \usebox\xxboxa\par A
  83.         \end{minipage}%
  84.         \begin{minipage}[b]{\lhalf}
  85.         \centering
  86.         \usebox\xxboxb\par B
  87.         \end{minipage}\par\vspace{2ex}%
  88.         \noindent
  89.         \begin{minipage}[b]{\lhalf}
  90.         \centering
  91.         \usebox\xxboxc\par C
  92.         \end{minipage}%
  93.         \begin{minipage}[b]{\lhalf}
  94.         \centering
  95.         \usebox\xxboxd\par D
  96.         \end{minipage}%
  97.     \else
  98.         \noindent
  99.         \begin{minipage}[b]{\lhalfhalf}
  100.         \centering
  101.         \usebox\xxboxa\par A
  102.         \end{minipage}%
  103.         \begin{minipage}[b]{\lhalfhalf}
  104.         \centering
  105.         \usebox\xxboxb\par B
  106.         \end{minipage}%
  107.         \begin{minipage}[b]{\lhalfhalf}
  108.         \centering
  109.         \usebox\xxboxc\par C
  110.         \end{minipage}%
  111.         \begin{minipage}[b]{\lhalfhalf}
  112.         \centering
  113.         \usebox\xxboxd\par D
  114.         \end{minipage}%
  115.     \fi
  116. \fi
  117. }


  118. \begin{document}

  119. \newcommand\test{test test test test test test test test test test test test test test test test test test test test test test}

  120. \rule{0.15\linewidth}{1ex} \test
  121. \xx{\rule{0.15\linewidth}{1ex}}234

  122. \rule{0.3\linewidth}{1ex} \test
  123. \xx{\rule{0.3\linewidth}{1ex}}234

  124. \rule{0.5\linewidth}{1ex} \test
  125. \xx{\rule{0.5\linewidth}{1ex}}234

  126. \begin{itemize}
  127. \item\rule{0.15\linewidth}{1ex} \test
  128. \xx{\rule{0.15\linewidth}{1ex}}234

  129. \item\rule{0.3\linewidth}{1ex} \test
  130. \xx{\rule{0.3\linewidth}{1ex}}234

  131. \item\rule{0.5\linewidth}{1ex} \test
  132. \xx{\rule{0.5\linewidth}{1ex}}234

  133. \begin{itemize}
  134. \item\rule{0.15\linewidth}{1ex} \test
  135. \xx{\rule{0.15\linewidth}{1ex}}234

  136. \item\rule{0.3\linewidth}{1ex} \test
  137. \xx{\rule{0.3\linewidth}{1ex}}234

  138. \item\rule{0.5\linewidth}{1ex} \test
  139. \xx{\rule{0.5\linewidth}{1ex}}234
  140. \end{itemize}
  141. \end{itemize}


  142. \test
  143. \fourtuxx
  144. {\includegraphics[width=0.2\linewidth]{example-image}}
  145. {\includegraphics[width=0.2\linewidth]{example-image}}
  146. {\includegraphics[width=0.2\linewidth]{example-image}}
  147. {\includegraphics[width=0.2\linewidth]{example-grid-100x100pt}}

  148. \test
  149. \fourtuxx
  150. {\includegraphics[width=\dimexpr0.5\linewidth-1em\relax]{example-image}}
  151. {\includegraphics[width=\dimexpr0.5\linewidth-1em\relax]{example-image}}
  152. {\includegraphics[width=\dimexpr0.5\linewidth-1em\relax]{example-image}}
  153. {\includegraphics[width=0.45\linewidth]{example-grid-100x100pt}}

  154. The above image width is max, try more 0.01pt will get:
  155. \fourtuxx
  156. {\includegraphics[width=\dimexpr0.5\linewidth-1em+0.01pt\relax]{example-image-a}}
  157. {}{}{}

  158. \end{document}
复制代码
代码仍在测试中,效果:
xzt1.PNG
2018-3-2 15:51

xzt2.PNG
2018-3-2 15:51
分享到: QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
这名字我喜欢

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

TOP

回复 2# isee

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

TOP

回复  isee

那不过是因为有四个选项,每次总要重复四次才显得长啊,其实原理是很好理解的。 ...
色k 发表于 2017-6-11 17:13


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

TOP

本帖最后由 色k 于 2017-6-11 18:01 编辑

回复 4# isee

相信原理都差不多的,肯定不会比我改进前的代码短多少。
重点是原理,上面的代码其实要改短也完全可以,比如将 minipage 环境改成 \parbox ,三行变一行,就会短很多,但我懒得改
习惯了用 minipage,尽管和 \parbox 几乎无区别。

TOP

话说昨天网友问我选择题选项怎么排版,我就给了《撸题集》里的相关代码。
那段代码依赖两个宏包:calc、ift ...
色k 发表于 2017-6-11 16:04


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

TOP

回复 6# isee

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

TOP

回复 7# kuing


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

TOP

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

TOP

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

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

TOP

返回列表 回复 发帖