假如一位地理老师的班上有35名学生, 准备进行美国各州首府的一个小测验。不妙的是, 班里有几个坏蛋,无法确信学生不会作弊。 希望随机调整问题的次序,这样每份试卷都是独一无二的, 这让任何人都不能从其他人那里抄袭答案。当然, 手工完成这件事又费时又无聊。好在,懂一些 Python 技术。
下面是程序所做的事:
- 创建35份不同的测验试卷。
- 为每份试卷创建50个多重选择题,次序随机。
- 为每个问题提供一个正确答案和3个随机的错误答案,次序随机。
- 将测验试卷写到35个文本文件中。
- 将答案写到35个文本文件中。
这意味着代码需要做下面的事:
- 将州和它们的首府保存在一个字典中。
- 针对测验文本文件和答案文本文件,
调用 open()
、 write()
和 close()
。
- 利用
random.shuffle()
随机调整问题和多重选项的次序。
将测验数据保存在字典中
第一步是创建一个脚本框架,并填入测验数据。
创建一个名为 randomQuizGenerator.py
的文件,
让它看起来像这样:
#! python3
# randomQuizGenerator.py - Creates quizzes with questions and answers in
# random order, along with the answer key.
import random
# The quiz data. Keys are states and values are their capitals.
capitals = {'Alabama': 'Montgomery', 'Alaska': 'Juneau', 'Arizona': 'Phoenix',
'Arkansas': 'Little Rock', 'California': 'Sacramento', 'Colorado': 'Denver',
'Connecticut': 'Hartford', 'Delaware': 'Dover', 'Florida': 'Tallahassee',
'Georgia': 'Atlanta', 'Hawaii': 'Honolulu', 'Idaho': 'Boise', 'Illinois':
'Springfield', 'Indiana': 'Indianapolis', 'Iowa': 'Des Moines', 'Kansas':
'Topeka', 'Kentucky': 'Frankfort', 'Louisiana': 'Baton Rouge', 'Maine':
'Augusta', 'Maryland': 'Annapolis', 'Massachusetts': 'Boston', 'Michigan':
'Lansing', 'Minnesota': 'Saint Paul', 'Mississippi': 'Jackson', 'Missouri':
'Jefferson City', 'Montana': 'Helena', 'Nebraska': 'Lincoln', 'Nevada':
'Carson City', 'New Hampshire': 'Concord', 'New Jersey': 'Trenton', 'New Mexico': 'Santa Fe', 'New York': 'Albany', 'North Carolina': 'Raleigh',
'North Dakota': 'Bismarck', 'Ohio': 'Columbus', 'Oklahoma': 'Oklahoma City',
'Oregon': 'Salem', 'Pennsylvania': 'Harrisburg', 'Rhode Island': 'Providence',
'South Carolina': 'Columbia', 'South Dakota': 'Pierre', 'Tennessee':
'Nashville', 'Texas': 'Austin', 'Utah': 'Salt Lake City', 'Vermont':
'Montpelier', 'Virginia': 'Richmond', 'Washington': 'Olympia', 'West Virginia': 'Charleston', 'Wisconsin': 'Madison', 'Wyoming': 'Cheyenne'}
# Generate 35 quiz files.
for quizNum in range(35):
# TODO: Create the quiz and answer key files.
# TODO: Write out the header for the quiz.
# TODO: Shuffle the order of the states.
# TODO: Loop through all 50 states, making a question for each.
因为这个程序将随机安排问题和答案的次序,
所以需要导入 random
模块,
以便利用其中的函数。 capitals
变量含一个字典,
以美国州名作为键,以州首府作为值。
因为希望创建35份测验试卷,
所以实际生成测验试卷和答案文件的代码
(暂时用 TODO
注释标注)会放在一个
for
循环中,循环35次(这个数字可以改变,
生成任何数目的测验试卷文件)。
创建测验文件
创建测验文件,并打乱问题的次序。
现在是时候填入那些 TODO
了。
循环中的代码将重复执行35次 (每次生成一份测验试卷),所以在循环中, 只需要考虑一份测验试卷。首先要创建 一个实际的测验试卷文件,它需要有唯一的文件名, 并且有某种标准的标题部分,留出位置, 让学生填写姓名、日期和班级。 然后需要得到随机排列的州的列表, 稍后将用它来创建测验试卷的问题和答案。
在 randomQuizGenerator.py
中添加以下代码行:
#! python3
# randomQuizGenerator.py - Creates quizzes with questions and answers in
# random order, along with the answer key.
--snip--
# Generate 35 quiz files.
for quizNum in range(35):
# Create the quiz and answer key files.
quizFile = open('captalsquiz%s.txt' % (quizNum + 1), 'w')
answerKeyFile = open('captalsquiz_answers%s.txt' % (quizNum + 1), 'w')
# Write out the header for the quiz.
quizFile.write('Name:\n\nDate:\n\nPeriod:\n\n')
quizFile.write((' ' * 20) + 'State Capitals Quiz (Form %s)' % (quizNum + 1))
quizFile.write('\n\n')
# Shuffle the order of the states.
states = list(capitals.keys())
random.shuffle(states)
# TODO: Loop through all 50 states, making a question for each.
测验试卷的文件名将是 capitalsquiz<N>.txt
,
其中 <N>
是该测验试卷的唯一编号,
来自于 quizNum
,即 for
循环的计数器。
针对 capitalsquiz<N>.txt
的答案将保存在一个文本文件中,名为capitalsquiz_answers<N>.txt
。
每次执行循环,'capitalsquiz%s.txt'
和 'capitalsquiz_answers%s.txt'
中的占位符 %s
都将被 (quizNum + 1)
取代,
所以第一个测验试卷和答案将是 capitalsquizl.txt
和capitalsquiz_answersl.txt
。
在©和©的 open()
函数调用将创建这些文件,以 'w'
作为第二个参数,
以写模式打开它们。
©处 write()
语句创建了测验标题,
让学生填写。最后,利用 random.shuffle()
函数,
创建了美国州名的随机列表。
该函数重新随机排列传递给它的列表中的值。
创建答案选项
现在需要为每个问题生成答案选项,
这将是 A
到 D
的多重选择。
需要创建另一个 for
循环,
该循环生成测验试卷的50个问题的内容。
然后里面会嵌套第三个 for
循环,为每个问题生成多重选项。
让代码看起来像这样:
#! python3
# randomQuizGenerator.py - Creates quizzes with questions and answers in
# random order, along with the answer key
--snip--
# Loop through all 50 states, making a question for each.
for questionNum in range(50):
# Get right and wrong answers.
correctAnswer = capitals[states[questionNum]]
wrongAnswers = list(capitals.values())
del wrongAnswers[wrongAnswers.index(correctAnswer)]
wrongAnswers = random.sample(wrongAnswers, 3)
answerOptions = wrongAnswers + [correctAnswer]
random.shuffle(answerOptions)
# TODO: Write the question and the answer options to the quiz file.
# TODO: Write the answer key to a file.
正确的答案很容易得到,
它作为一个值保存在 capitals
字典中。
循环将遍历打乱过的 states
列表中的州,
从 states[0]
到 states[49]
,
在 capitals
中找到每个州,
将该州对应的首府保存在 correctAnswer
中。
可能的错误答案列表需要一点技巧。
可以从 capitals
字典中复制所有的值,
删除正确的答案,然后从该列表中选择3个随机的值。
random.sample()
函数使得这种选择很容易,
它的第一个参数是希望选择的列表,
第二个参数是希望选择的值的个数。
完整的答案选项列表是这3个错误答案与正确答案的组合。
最后,答案需要随机排列,这样正确的答案就不会总是选项D
。
将内容写入测验试卷和答案文件
剩下来就是将问题写入测验试卷文件,将答案写入答案文件。 让代码看起来像这样:
randomQuizGenerator.py
- 创建包含随机顺序的问题和答案以及答案密钥的测验。
#! python3
import random
测验数据。键是州名,值是对应的首府。
capitals = {'Alabama': 'Montgomery', 'Alaska': 'Juneau', 'Arizona': 'Phoenix',
'Arkansas': 'Little Rock', 'California': 'Sacramento', 'Colorado': 'Denver',
'Connecticut': 'Hartford', 'Delaware': 'Dover', 'Florida': 'Tallahassee',
'Georgia': 'Atlanta', 'Hawaii': 'Honolulu', 'Idaho': 'Boise', 'Illinois':
'Springfield', 'Indiana': 'Indianapolis', 'Iowa': 'Des Moines', 'Kansas':
'Topeka', 'Kentucky': 'Frankfort', 'Louisiana': 'Baton Rouge', 'Maine':
'Augusta', 'Maryland': 'Annapolis', 'Massachusetts': 'Boston', 'Michigan':
'Lansing', 'Minnesota': 'Saint Paul', 'Mississippi': 'Jackson', 'Missouri':
'Jefferson City', 'Montana': 'Helena', 'Nebraska': 'Lincoln', 'Nevada':
'Carson City', 'New Hampshire': 'Concord', 'New Jersey': 'Trenton', 'New Mexico': 'Santa Fe',
'New York': 'Albany', 'North Carolina': 'Raleigh',
'North Dakota': 'Bismarck', 'Ohio': 'Columbus', 'Oklahoma': 'Oklahoma City',
'Oregon': 'Salem', 'Pennsylvania': 'Harrisburg', 'Rhode Island': 'Providence',
'South Carolina': 'Columbia', 'South Dakota': 'Pierre', 'Tennessee':
'Nashville', 'Texas': 'Austin', 'Utah': 'Salt Lake City', 'Vermont':
'Montpelier', 'Virginia': 'Richmond', 'Washington': 'Olympia', 'West Virginia': 'Charleston',
'Wisconsin': 'Madison', 'Wyoming': 'Cheyenne'}
生成35个测验文件。
for quizNum in range(35):
# Create the quiz and answer key files.
quizFile = open('/tmp/captalsquiz%s.txt' % (quizNum + 1), 'w')
answerKeyFile = open('/tmp/captalsquiz_answers%s.txt' % (quizNum + 1), 'w')
# Write out the header for the quiz.
quizFile.write('Name:\n\nDate:\n\nPeriod:\n\n')
quizFile.write((' ' * 20) + 'State Capitals Quiz (Form %s)' % (quizNum + 1))
quizFile.write('\n\n')
# Shuffle the order of the states.
states = list(capitals.keys())
random.shuffle(states)
# Loop through all 50 states, making a question for each.
for questionNum in range(50):
# Get right and wrong answers.
correctAnswer = capitals[states[questionNum]]
wrongAnswers = list(capitals.values())
del wrongAnswers[wrongAnswers.index(correctAnswer)]
wrongAnswers = random.sample(wrongAnswers, 3)
answerOptions = wrongAnswers + [correctAnswer]
random.shuffle(answerOptions)
# Write the question and the answer options to the quiz file.
quizFile.write('%s. What is the capital of %s?\n' % (questionNum + 1, states[questionNum]))
for i in range(4):
quizFile.write(' %s. %s\n' % ('ABCD'[i], answerOptions[i]))
quizFile.write('\n')
# Write the answer key to a file.
answerKeyFile.write('%s. %s\n' % (questionNum + 1, 'ABCD'[answerOptions.index(correctAnswer)]))
quizFile.close()
answerKeyFile.close()
一个遍历整数 0
到 3
的 for
循环,
将答案选项写入 answerOptions
列表。
quizFile.write(' %s. %s\n' % ('ABCD'[i], answerOptions[i]))
的表达式 'ABCD'[i]
将字符串 'ABCD'
看成是一个数组,它在循环的每次迭代中,
将分别求值为 'A'
、'B'
、 'C'
和 'D'
。
在最后一行,表达式 answerOptions.index(correctAnswer)
将在随机排序的答案选项中,找到正确答案的整数下标,并且 'ABCD'[answerOptions.index(correctAnswer)]
将求值为正确答案的字母,写入到答案文件中。
在运行该程序后,
下面就是 capitalsquizl.txt
文件看起来的样子。
但是问题和答案选项当然与这里显示的可能会不同。
这取决于 random.shuffle()
调用的结果:
Name:
Date:
Period:
State Capitals Quiz (Form 1)
1.What is the capital of West Virginia?
A.Hartford
B.Santa Fe
C.Harrisburg
D.Charleston
2.What is the capital of Colorado?
A.Raleigh
B.Harrisburg
C.Denver
D.Lincoln
*-*-snip—