找回密码
 快速注册
搜索
查看: 2810|回复: 9

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

[复制链接]

15

主题

958

回帖

1万

积分

积分
12454

显示全部楼层

色k 发表于 2017-6-11 16:04 |阅读模式
话说昨天网友问我选择题选项怎么排版,我就给了《撸题集》里的相关代码。
那段代码依赖两个宏包: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

考考大家,为什么同样的 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
xzt2.PNG
这名字我喜欢

830

主题

4862

回帖

3万

积分

积分
36159

显示全部楼层

isee 发表于 2017-6-11 17:03
看着就头大,这代码不友好,长。

15

主题

958

回帖

1万

积分

积分
12454

显示全部楼层

 楼主| 色k 发表于 2017-6-11 17:13
回复 2# isee

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

830

主题

4862

回帖

3万

积分

积分
36159

显示全部楼层

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

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


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

15

主题

958

回帖

1万

积分

积分
12454

显示全部楼层

 楼主| 色k 发表于 2017-6-11 17:58
回复 4# isee

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

830

主题

4862

回帖

3万

积分

积分
36159

显示全部楼层

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


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

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

kuing 发表于 2017-12-14 00:03
回复 6# isee

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

830

主题

4862

回帖

3万

积分

积分
36159

显示全部楼层

isee 发表于 2017-12-14 00:21
回复 7# kuing


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

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

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

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

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

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

手机版|悠闲数学娱乐论坛(第3版)

GMT+8, 2025-3-4 17:08

Powered by Discuz!

× 快速回复 返回顶部 返回列表