[英]How to validate command line input from multiple choice prompt in Ruby?
我正在寫一個多項選擇測驗,用戶必須通過輸入從a
到d
的字母來選擇答案。 每個問題提示如下所示:
What is the last letter in alphabet?
(a) Y
(b) R
(c) Z
(d) Q
如果用戶輸入其他任何內容,我想顯示一條消息並再次打印整個問題,直到輸入為a
、 b
、 c
或d
。
這是我嘗試過的:(簡化)
question = "What is the last letter in alphabet?\n(a) Y\n(b) R\n(c) Z\n(d) Q"
puts question
answer = gets.chomp.to_s
while answer > "d"
puts "Please enter a, b, c, or d"
puts
puts question
answer = gets.chomp.to_s
end
它在輸入e
、 f
、 g
等時工作正常,但它不會捕獲像ab
、 1
、 Z
之類的輸入,或者當用戶只是按下回車鍵時。
您只有四個允許的輸入。 直接檢查那些。 即使像不雅一樣if.(answer == "a" || answer == "b"...
)。 其他任何東西都會接受一些無效的輸入。 特別是, if answer > "d"
允許"ab"
作為有效答案。
您的方法不起作用,因為answer > "d"
使用它們的(Unicode)代碼點按字符比較兩個字符串。 要了解這意味着什么,請查看基本拉丁圖表:(它相當於一個 ASCII 表)
“d”的代碼點為 U+0064。 任何較小的代碼點(即圖表中“d”之前的每個字符)都被視為較小。 這包括所有(常規)數字、所有(基本拉丁語)大寫字母和幾個符號:
"0" > "d" #=> false
"Z" > "d" #=> false
您可以添加一個下限,例如answer < "a" || answer > "d"
answer < "a" || answer > "d"
但這仍然允許所有以允許的字符之一開頭的字符串,例如:
"apple" < "a" || "apple" > "d" #=> false
要實際將答案限制為四個允許值,您必須將字符串與每個值進行比較。 您可以結合這些比較:
answer == 'a' || answer == 'b' || answer == 'c' || answer == 'd'
在允許值的數組上使用循環:
['a', 'b', 'c', 'd'].any? { |letter| answer == letter }
檢查數組是否包含答案:
['a', 'b', 'c', 'd'].include?(answer)
# or
%w[a b c d].include?(answer)
或使用正則表達式將a
匹配到d
:
answer.match?(/\A[a-d]\z/)
請注意,如果answer
在a
和d
之間,則上述示例為真。 您可以通過.(...)
否定條件:
while !(%w[a b c d].include?(answer))
# ...
end
或使用until
而不是while
:
until %w[a b c d].include?(answer)
# ...
end
其他答案已回答您問題標題中給出的問題。
我建議您考慮采用以下代碼的一些變體。
def get_answer(question, answers)
choices_to_answers = construct_choices_to_answers(answers)
loop do
puts "#{question}"
display_choices(choices_to_answers)
print "answer: "
choice = gets.chomp
puts choice
break choices_to_answers[choice] if choices_to_answers.key?(choice)
puts "\nThat answer is invalid."
puts "Enter a letter between 'a' and '#{choices_to_answers.keys.last}'\n"
end
end
def construct_choices_to_answers(answers)
('a'..('a'.ord + answers.size - 1).chr).to_a.zip(answers).to_h
end
def display_choices(choices_to_answers)
choices_to_answers.each { |k,v| puts "(#{k}): #{v}" }
end
假設可能的答案如下。
answers = %w| Y R Z Q |
#=> ["Y", "R", "Z", "Q"]
然后
choices_to_answers = construct_choices_to_answers(answers)
#=> {"a"=>"Y", "b"=>"R", "c"=>"Z", "d"=>"Q"}
和
display_choices(choices_to_answers)
印刷
(a): Y
(b): R
(c): Z
(d): Q
在這里,我假設選擇總是以"a"
開頭的連續字母。 如果該假設正確,則無需手動將這些字母與可能的答案相關聯。
現在讓我展示與該方法的可能對話( answers
如上定義)。
question = "What is the last letter in the alphabet?"
get_answer(question, answers)
#=> "R"
顯示以下內容。
What is the last letter in the alphabet?
(a): Y
(b): R
(c): Z
(d): Q
answer: e
That answer is invalid.
Enter a letter between 'a' and 'd'
What is the last letter in the alphabet?
(a): Y
(b): R
(c): Z
(d): Q
answer: b
然后,您可以構建一個散列數組,提供問題、可能的答案、正確答案、可能問題的權重以及指示是否給出了正確答案的 boolean。
questions = [
...
{ question: "What is the last letter in the alphabet?",
answers: ["Y", "R", "Z", "Q"],
correct_answer: "Z",
weight: 1,
correct_answer_given: nil
},
...
]
回答問題時,每個問題的:correct_answer_given
值都會更新為true
或false
。 回答完所有questions
后,可以使用問題來確定考試的分數。
如果你想為每個問題分配一個數字,你可以寫
question_number = 0
questions.each do |h|
question_number += 1
g = h.merge(question: "#{question_number}. #{h[:question]}")
answer = get_answer(question, g[:answers])
h[:correct_answer_given] = h[:correct_answer] == answer
end
如果question_number #=> 12
並且
h[:question]
#=> "What is the last letter in the alphabet?",
然后
g[:question]
#=> "12. What is the last letter in the alphabet?"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.