r-exams题目结构随机化实现:电路电阻计算测验题型动态切换
问题核心原因
你的判断是正确的,knitr的每个代码块都是独立执行的,拆分if分支到不同代码块会导致R无法识别完整逻辑,必然报错。
可行实现方案
最常用的两种实现随机题型切换的方法如下:
方法1:使用results='asis'代码块动态输出内容
在同一段R代码块内完成分支判断,用cat()函数直接输出需要渲染的LaTeX内容,不需要拆分代码块。示例完整代码如下:
题干部分
\begin{question} 请问以下电路中a、b两点的总电阻是多少? <<echo=FALSE, results='asis'>>= # sel是提前随机生成的取值:1代表两电阻串联,2代表三电阻串联 if (sel == 1) { # 输出两电阻场景的题干文本,注意LaTeX的反斜杠需要双重转义 cat(sprintf("$R_1 = %.1f %s\\Omega$,$R_2 = %.1f %s\\Omega$,电路连接方式如下图所示\n", r1, char1_insert, r2, char2_insert)) } else if (sel == 2) { # 输出三电阻场景的题干文本 cat(sprintf("$R_1 = %.1f %s\\Omega$,$R_2 = %.1f %s\\Omega$,$R_3 = %.1f %s\\Omega$,电路连接方式如下图所示\n", r1, char1_insert, r2, char2_insert, r3, char3_insert)) } @ \setkeys{Gin}{width=0.3\textwidth} <<fig=TRUE, height = 4, width = 4, echo=FALSE, eps=FALSE, results=hide>>= # 提前根据sel生成对应电路图赋值给im即可 plot.new() rasterImage(im, 0, 0, 1, xmax) @ \end{question}
解答部分
\begin{solution} <<echo=FALSE, results='asis'>>= if (sel == 1) { cat("串联电阻总阻值为所有电阻阻值之和,计算过程如下: \\begin{eqnarray*} R_{tot} & = & R_1 + R_2\\\\ R_{tot} & = & ", r1_val, " + ", r2_val, "\\\\ R_{tot} & = & ", res, "~\\Omega \\end{eqnarray*}") } else if (sel == 2) { cat("串联电阻总阻值为所有电阻阻值之和,计算过程如下: \\begin{eqnarray*} R_{tot} & = & R_1 + R_2 + R_3\\\\ R_{tot} & = & ", r1_val, " + ", r2_val, " + ", r3_val, "\\\\ R_{tot} & = & ", res, "~\\Omega \\end{eqnarray*}") } @ \end{solution}
方法2:子文档调用(适合题型逻辑复杂的场景)
如果每种题型的内容比较多,可以把不同题型单独写成独立的.Rnw子文件,在分支里调用knit_child()渲染对应子文档即可:
<<echo=FALSE, results='asis'>>= if (sel == 1) { cat(knit_child('two_res_series.Rnw', quiet = TRUE)) } else if (sel == 2) { cat(knit_child('three_res_series.Rnw', quiet = TRUE)) } @
注意事项
- 用
cat()输出LaTeX内容时,所有反斜杠都需要双重转义,比如\Omega要写成\\Omega,公式里的换行符\\要写成\\\\ - 所有随机变量(电阻阻值、题型选择变量
sel、对应电路图对象)建议统一放在文档最开头的setup代码块中生成,方便维护
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

