带反馈和多个if循环的psychopy构建实验
我正在尝试使用Coder视图来做一个实验,这个实验涉及反馈和多个条件判断。不过,我该怎么做呢?这个任务最终会包含4道数学题,参与者每道题最多可以尝试3次。结构大概是这样的……
循环1:遍历这4道题
循环2:每道题允许最多3次尝试
循环3:如果回答正确,就说“正确”,然后进入下一道题;如果回答错误,就说“错误”,并询问他们是否想再试一次或者继续下一道题
这是我第一次使用Python,我在代码中遇到了一些问题。没有返回错误信息,但代码没有记录到回答,因此任务在提示屏幕上卡住了。下面是我的代码。我没有包括库和其他设置。
t=0
nProblem=4
nAttempt=3
while currentProb <= nProblem:
problemTimer.reset()
attempt = 1
# *prompt* updates
prompt.setAutoDraw(True)
prompt.setText(u'Problem prompt will go here.\n\nType in your answer and press enter to submit.', log=False)
while attempt <= nAttempt:
response = []
# *response* updates
core.wait(1) #LB - using this in place of that enormous if-statement
event.clearEvents(eventType='keyboard')
theseKeys = event.getKeys(keyList=['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'])
# check for quit:
if "escape" in theseKeys:
endExpNow = True
if ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0') in theseKeys: # subject responds with number value
response.append(theseKeys) # will tack on responses to previous responses
while event.getKeys(keyList=['return'])==[]:
# *timer* updates
if t <= 0.0:
# keep track of start time/frame for later
timer.setAutoDraw(True)
#elif timer.status == STARTED and t >= (0.0 + (600-win.monitorFramePeriod*0.75)): #most of one frame period left
#timer.setAutoDraw(False)
#if timer.status == STARTED: # only update if being drawn
timer.setText(str(round((600+routineTimer.getTime())/60,1)) , log=False)
# *minutesleft* updates
if t >= 0.0:
# keep track of start time/frame for later
minutesleft.setAutoDraw(True)
#elif minutesleft.status == STARTED and t >= (0.0 + (600-win.monitorFramePeriod*0.75)): #most of one frame period left
#minutesleft.setAutoDraw(False)
numberlist=event.getKeys(keyList=['1','2','3','4','5','6','7','8','9','0','backspace','return'])
for number in numberlist:
#if key isn't backspace, add key pressed to the string
if number !='backspace':
response.append(number)
#otherwise, take the last letter off the string
elif len(text)>=0:
response.remove(numberlist[number-1])
#continually redraw text onscreen until return pressed
answer = visual.TextStim(win, text=response,color="black",pos=(0,-100))
answer.draw()
win.flip()
event.clearEvents()
if len(theseKeys) > 0: # at least one key was pressed
response.keys.extend(theseKeys) # storing all keys
response.rt.append(response.clock.getTime())
#check for quit
if "escape" in theseKeys:
endExpNow = True
if response == '9999': # was this correct?
correctAns = 1
else:
correctAns = 0
if theseKeys == 'enter':
response.keys.extend(theseKeys) # storing all keys
response.rt.append(attemptresponse.clock.getTime())
if correctAns == 1:
attempt += 888 #ends and goes to next problem
currentProb += 1
dataFile.write(attempt,attemptresponse,theseKeys,response,correctAns) #output separated by commas
#dataFile.write('PID COND PROB ATT TIME RESP\n')
response_correct.draw()
win.flip()
event.waitKeys()
if correctAns == 0:
attempt += 1 #LB = was previously setting to 1 forever
dataFile.write(attempt-1,attemptresponse,theseKeys,response,correctAns) #output separated by commas
response_incorrect.draw()
win.flip()
theseKeys = event.getKeys(keyList=['q','space'])
if theseKeys == 'q':
continueRoutine = False
if theseKeys == 'space':
prompt.draw()
win.flip()
event.waitKeys()
1 个回答
我不能给你写完整的代码,但希望能指出一些要点,帮助你接近目标。
获取响应
theseKeys = event.getKeys(keyList=['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'])
if "escape" in theseKeys:
在这里,theseKeys
只能包含 keyList
中的内容,所以“escape”这个键是不会出现的。你可以在 keyList
中添加“escape”键,可能还要加上你后面会用到的“enter”键。
if ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0') in theseKeys:
theseKeys
是一个列表,当你用 "(x,y,z) in list" 这样的方式检查时,它会寻找一个完整的元素 (x,y,z),而不是单独检查 x、y 和 z。如果你的 keyList
是上面的样子,你就知道任何不是“escape”的响应都是其中之一,所以其实不需要这样检查。因此可以这样做:
theseKeys = event.getKeys(keyList=['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'escape'])
if "escape" in theseKeys:
core.quit() # assuming that psychopy.core is imported
elif "enter" in theseKeys:
# Something something
else:
response.append(theseKeys[0]) # OBS: pick the first response
循环
看起来你更想用 for
循环,而不是 while
循环。使用 for 循环时,你不需要自己去跟踪当前的循环次数。所以,不用这样:
while currentProb <= nProblem:
这样做:
for currentProb in range(nProblem):
这样 currentProb
的增加会自动进行,循环会在应该结束的时候自动停止。这样做会更优雅。
等待响应
我有点不确定你是否想在 while 循环中使用 event.waitKeys()
而不是 event.getKeys()
,如果你想控制等待时间,可以使用 maxWait
参数,并且如果你想跟踪时间,可以用 core.Clock()
。如果你想动画某些东西,while 循环是可以的,但如果不是,使用 event.waitKeys()
会简单且安全得多。
最后,在你尝试让这个工作的时候,多用 print
语句来检查 theseKeys
和其他变量的实际内容。这是调试和捕捉问题的最好方法。