Existe uma maneira decente de implementar um quiz no Bash, onde as perguntas são aleatórias a cada vez e onde as diferentes respostas dos usuários (correto, errado, aprovado) são registradas e dadas no final do quiz?
Suponho que matrizes poderiam ser usadas para armazenar as perguntas e respostas do questionário, e as próprias perguntas do questionário poderiam ser feitas dentro de um loop while ou até, e as várias perguntas poderiam ser incrementadas até que a última fosse alcançada, então o desempenho do usuário poderia ser avaliado usando várias declarações condicionais?
Por favor, note queessa velha perguntadiscuti software de teste gráfico e mencionei explicitamente sons/gráficos, etc., enquanto estou falando apenas de um teste baseado em texto de linha de comando.
(Eu respondi minha própria pergunta abaixo... mas se alguém tiver outra estrutura para um teste no Bash, poste.)
Responder1
A estrutura do questionário que criei está publicada abaixo e também emGitHub(a página original do GitHub do usuário não existe mais).
Como parece um tanto complicado, é melhor dar algumas explicações de como funciona.
No script, as versões do Ubuntu e os codinomes de todos os lançamentos até agora são armazenados em dois arrays. As variáveis são então inicializadasforado loop até, para que possam ser incrementados conforme necessário no loop usando (( var++ ))
a notação estilo C.
Em seguida, crio outra matriz para os números das perguntas; neste caso, para 19 perguntas, devo incluir de 0 a 18 inclusive:
questions_order=(15 4 1 10 8 3 13 0 11 16 2 7 5 17 6 9 14 18 12)
e embaralhe-o usando shuf
e crie um novo array e use-o para esta execução específica do script:
shuffled_order=( $(shuf -n19 -e ${questions_order[@]}) )
Isso deve ser feitoforado loop, pois só quero que ele seja executado uma vez.
Resumindo, o loop agora é executado até que o número atual de questões seja igual à "${target_questions}"
variável e então os resultados são fornecidos.
Quando um usuário responde a uma pergunta, ela será interpretada pelas diversas condições da case
declaração. Não respostas (espaços em branco), respostas erradas, respostas corretas e aprovações são todas detectadas e recebem respostas, e as diversas variáveis são todas incrementadas (por exemplo, para uma resposta errada, (( wrong++ ))
).
Quando a última pergunta for respondida, o desempenho do usuário é avaliado onde são retransmitidos o número de respostas certas, erradas e aprovações (se houver) e também é dado o tempo gasto.
Esta é uma breve explicação, mas o script em si tem vários comentários que devem deixar o funcionamento claro (ish)! Poderia ser adaptado para qualquer outro tipo de questionário, por exemplo, sobre capitais e países.
Depois de copiar o script para um arquivo, torne-o executável ( chmod u+x
) e execute-o ./scriptname
ou coloque-o em sua ~/bin
pasta e chame-o pelo nome como qualquer outro programa, supondo que você ~/bin
esteja em PATH
.
#!/usr/bin/env bash
# by mik, aka Exactus29, https://github.com/Exactus29
#
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#########
# Requires at least bash 3.1. As it makes extensive use of arrays, it would be a pain to
# try to write it to be sh compatible, but it may be possible.
# arrays for questions and answers
codenames=("Warty Wharthog" "Hoary Hedgehog" "Breezy Badger" "Dapper Drake" "Edgy Eft" "Feisty Fawn"
"Gutsy Gibbon" "Hardy Heron" "Intrepid Ibex" "Jaunty Jackalope" "Karmic Koala" "Lucid Lynx" "Maverick Meerkat"
"Natty Narwahl" "Oneric Ocelot" "Precise Pangolin" "Quantal Quentzal" "Raring Ringtail" "Saucy Salamander")
versions=(4.10 5.04 5.10 6.06 6.10 7.04 7.10 8.04 8.10 9.04 9.10 10.04 10.10
11.04 11.10 12.04 12.10 13.04 13.10)
# must intialize quest_index at -1 so we can use array index 0
quest_index=-1
target_questions=19
# we start question counter at 0, so we can increment it to the value in number_questions
questions=0
# the other variables below will all be incremented as necessary in the quiz
correct=0
wrong=0
no_response=0
pass=0
# declare questions_order array and then shuffle it and use that for this run of the script.
# must be declared outside of the loop, as only want it executed once
questions_order=(15 4 1 10 8 3 13 0 11 16 2 7 5 17 6 9 14 18 12)
shuffled_order=( $(shuf -n19 -e ${questions_order[@]}) )
printf "\nPress 0 to exit the quiz at any time.\n"
printf "You can ignore case in your answers, but correct spelling of the Ubuntu codenames is crucial.\n"
printf "Please enter the word pass if you don't know the answer.\n\n\n"
timer_begin=$SECONDS
until (( questions == target_questions )); do
(( questions++ ))
(( quest_index++ ))
new_index=$( echo ${shuffled_order[$quest_index]})
# alternate style of questions, separate odd and even
if (( questions % 2 > 0 )); then
new_question="${codenames[$new_index]}"
ans="${versions[$new_index]}"
question_text="Ubuntu release had the development codename"
else
new_question="${versions[$new_index]}"
ans="${codenames[$new_index]}"
question_text="was the Ubuntu development codename (both adjective and animal) for release"
fi
read -p "(${questions}) What ${question_text} ${new_question}? " response
# necessary to switch on nocasematch to cover if the answer is in capitals, as can't use normal [Mm] in case statement
shopt -s nocasematch
case $response in
"$ans")
printf "Well done, correct answer. "
(( correct++ ))
if (( questions < target_questions )); then
printf "Next question.\n\n"
else
printf "\nHowever, the quiz has now finished. Let us calculate your performance...\n"
sleep 1
fi
;;
0)
printf "\nOk, time to finish with the quiz.\n"
break
;;
"pass")
(( pass++ ))
printf "Ok, you passed on this one..."
if (( pass >= 10 )); then
printf "The passes are mounting, as you have now had ${pass} passes.\n"
elif (( pass >= 2 )); then
printf "Please try to give an answer, as you have now had ${pass} passes.\n"
fi
if (( questions < target_questions )); then
printf "Let us try another question.\n\n"
else
printf "\nHowever, the quiz has now finished. Let us calculate your performance.....\n"
sleep 1
fi
;;
*)
if [[ -z ${response} ]]; then
printf "Please provide an answer, as a blank answer is counted as a wrong answer; "
(( no_response++ ))
(( wrong++ ))
if (( no_response == 1 )); then
printf "${no_response} blank response has been given so far. \n"
elif (( no_response > 1 )); then
printf "${no_response} blank responses have been given so far. \n"
fi
else
(( wrong++ ))
if (( questions % 2 > 0 )); then
printf "That is incorrect..."
else
printf "That is incorrect, ${response} was not the codename of ${new_question}. \n"
fi
fi
if (( questions < target_questions )); then
printf "Let us try another question.\n\n"
else
printf "\nHowever, the quiz has now finished. Let us calculate your performance.....\n"
sleep 1
fi
;;
esac
done
quiz_duration=$(( SECONDS - timer_begin ))
# could further process the $quiz_duration if it is over 60 seconds, and output the total in
# minutes and seconds using bc or awk
# checking against target_questions here, i.e. all of the questions
if (( questions == target_questions )); then
if (( correct == target_questions )); then
printf "\nYou got them all right in ${quiz_duration} seconds, well done!\n\n"
elif (( no_response == target_questions )); then
printf "\nYou gave ${no_response} blank responses, and so effectively gave ${no_response} wrong answers.\n\n"
elif (( wrong == target_questions )); then
printf "\nYou got them all wrong in ${quiz_duration} seconds, oh dear!\n\n"
elif (( pass == target_questions )); then
printf "\nYou passed on all the questions. Was this just a trial run?\n\n"
else
printf "\nOut of ${target_questions} questions, you got "
# have to do this now because we have added the pass option, as you can have none wrong/correct,
# some correct/wrong, and some passes
(( wrong > 0 )) && printf "${wrong} wrong and "
(( correct > 0 )) && printf "${correct} correct "
if (( pass == 0 )); then
printf "with no passess at all in a time of ${quiz_duration} seconds.\n "
elif (( pass == 1 )); then
printf "with 1 pass in a time of ${quiz_duration} seconds.\n "
elif (( pass > 1 )); then
printf "with ${pass} passes in a time of ${quiz_duration} seconds.\n"
fi
fi
fi
exit
O quiz em ação, com perguntas aleatórias: