передача функций в классы и массивы

#ruby #function

Вопрос:

Это код, который я хотел использовать для повторного кода, поместив его в другую функцию и сохранив переменные в этой другой функции. Я не новичок в этом типе функций, поэтому мне действительно нужна помощь, большое вам спасибо за помощь.

 def main
    marks = 0

    puts "1. What does the == operator do?"
    puts "(a) calculates an arithmetic solution."
    puts "(c) checks for e"
    puts "Your answer: "

    begin
        answer = gets.chomp
    end while (answer != 'a' amp;amp; answer != 'b' amp;amp; answer != 'c' amp;amp; answer != 'd')
    
    if answer == 'c'
        score  = 1
        puts "Correct  " 
    else
        puts "Wrong  " 
    end
    
    puts "2. Which is NOT a C keyword?"
    puts "(a) when"
    puts "(b) const"
    puts "(c) unsigned"
    
    puts "Your answer: "
    
    begin
        answer = gets.chomp
    end while (answer != 'a' amp;amp; answer != 'b' amp;amp; answer != 'c' amp;amp; answer != 'd')
    
    if answer == 'a'
        score  = 1
        puts "Correct  "
    else
        puts "Wrong  "
    end
    
    puts "3. In function call, the actual parameters are separated by"
    puts "(a) semicolons"
    puts "(b) colons"
    puts "(c) commas"
    puts "Your answer: "

    note

    
        answer = gets.chomp
    if answer != 'a' amp;amp; answer != 'b' amp;amp; answer != 'c' amp;amp; answer != 'd'
    
    if answer == 'c'
        score  = 1
        puts "Correct  " 
    else
        puts "Wrong  " 
    end
    
end  

main
 

Комментарии:

1. Вам не нужна функция — вам нужны объекты. Вы, вероятно, захотите иметь объекты вопросов (отвечающие за хранение ваших данных о вопросах — вопрос, сам по себе, ответы и то, какой из них правильный, позже вы можете добавить специальную логику подсчета очков и различные типы вопросов), объект викторины (содержащий массив вопросов) и QuizAttempt (ссылка на викторину, выбранные ответы и итоговый балл) в качестве уровня данных. Затем простой объект QuizRunner будет выступать в качестве консольного интерфейса для перебора вопросов викторины и создания QuizAttempt.

2. не могли бы вы научить меня, как это сделать

3. @BroiSatse: хотя это довольно большой скачок. Лучше действовать детскими шагами: сначала извлеките пару СУХИХ методов.

4. @SergioTulentsev — Я согласен, что это огромный скачок, но его (ИМО) необходимо предпринять. По моему опыту, разработчики на тренировках очень неохотно совершают этот прыжок, что только закрепляет их в процедурном программировании. OO — это другой тип навыка для самостоятельного владения языком и/или алгоритмического мышления, и его можно научить, даже если кто-то вообще не знает, как программировать-я иногда провожу семинары в начальных школах, и дети просто любят рисовать диаграммы «что говорит с чем»:)

Ответ №1:

это непростой шаг, но, согласно комментариям @BroiSatse, создание различных аспектов объекта в виде классов:

Определение объекта для хранения возможных ответов

 class Answer
  attr_accessor :text, :correct
  def initialize text, correct
    @text = text
    @correct = correct
  end
end
 

Определение объекта для хранения вопросов, который будет содержать массив возможных ответов

 class Question
  attr_accessor :text, :answers
  def initialize text
    @text = text
    @answers = []
  end
end
 

Определение класса «Викторина», который содержит оценку и набор вопросов. он также включает в себя процедуру для просмотра вопросов и ответов, хранящихся в викторине

 class Quiz
  attr_accessor :questions, :score
  def initialize
    @questions = []
    @score = 0
  end

  def ask_questions
    @questions.each_with_index do |question, i|
      puts "#{i 1}. #{question.text}"

      question.answers.each_with_index do |answer,i|
        a_letter = (i   'a'.ord).chr
        puts "(#{a_letter}) #{answer.text}"
      end

      while true
        puts "Your answer: "
        user_answer = gets.chomp
        break if (user_answeramp;.ord - 'a'.ord)amp;.between?(0, question.answers.count-1)
      end

      if (question.answers[(user_answer.ord - 'a'.ord)]amp;.correct)
        @score  = 1
        puts "Correct tYour score is now "   @score.to_s
      else
        puts "Wrong tYour score is still "   @score.to_s
      end
    end
  end
end
 

Используйте новые классы/объекты

Теперь, когда классы настроены, мы можем создать нашу «Викторину».:

 quiz=Quiz.new

question = Question.new("What does the == operator do?")
question.answers << Answer.new('calculates an arithmetic solution.', false)
question.answers << Answer.new('assigns a value to a variable.', false)
question.answers << Answer.new("checks for equality", true)
question.answers << Answer.new("draws the '=' character", false)
quiz.questions << question

question = Question.new("Which is NOT a C keyword?")
question.answers << Answer.new('when', true)
question.answers << Answer.new('const', false)
question.answers << Answer.new('unsigned', false)
question.answers << Answer.new('do', false)
quiz.questions << question

question = Question.new("In function call, the actual parameters are separated by")
question.answers << Answer.new('semicolons', false)
question.answers << Answer.new('colons', false)
question.answers << Answer.new('commas', true)
question.answers << Answer.new('space', false)
quiz.questions << question
 

и, наконец, запустите процедуру «ask_questions»

 quiz.ask_questions
 

демонстрационный вывод

 2.7.2 :124 > quiz.ask_questions
1. What does the == operator do?
(a) calculates an arithmetic solution.
(b) assigns a value to a variable.
(c) checks for equality
(d) draws the '=' character
Your answer:
c
Correct         Your score is now 1
2. Which is NOT a C keyword?
(a) when
(b) const
(c) unsigned
(d) do
Your answer:
c
Wrong   Your score is still 1
3. In function call, the actual parameters are separated by
(a) semicolons
(b) colons
(c) commas
(d) space
Your answer:
c
Correct         Your score is now 2
 

Комментарии:

1. Придираюсь, но ответ сам по себе не является правильным или неправильным, это зависит от вопроса. Это могло бы иметь больше смысла, если бы объект, содержащий ответы, знал, какой из них правильный.

2. Мой допускает несколько возможных правильных ответов и позволяет изменять порядок элементов массива на лету … Но я понимаю вашу точку зрения

3. Вы могли бы еще больше сократить объем кода, используя структуру ruby. Определения классов для Question и Answer могут быть заменены одиночными строками Question = Struct.new(:text, :answers) и Answer = Struct.new(:text, :correct) , соответственно.

Ответ №2:

это мой код, все в порядке или слишком неаккуратно

 class Question
  attr_accessor :prompt, :answer
  def initialize(prompt, answer)
    @prompt = prompt
    @answer = answer
  end
end

p1 =
 "1. What does the == operator do?n
 (c) checks for equalityn
 (d) draws the '=' charactern
 Your answer: n"
p2 =
 "1. What does the == operator do?n
 (b) assigns a value to a variable.n
 (c) checks for equalityn
 (d) draws the '=' charactern
 Your answer: "
p3 =
"3.  the actual parameters are separated byn

(b) colonsn
(c) commasn


Your answer: "

questions = [
  Question.new(p1, "c"),
  Question.new(p2, "a"),
  Question.new(p3, "c"),
]

def run_test(questions)
answer = ""
score = 0
  for question in questions
    puts question.prompt
    
        answer = gets.chomp
    (answer != 'a' amp;amp; answer != 'b' amp;amp; answer != 'c' amp;amp; answer != 'd')
    if answer == question.answer
      score  = 1
      puts "Correct  " =
    else
      puts "Wrong  " 
    end
  end
end

run(questions)
 

Комментарии:

1. Это намного лучше! Ваш исходный код был чрезвычайно процедурным и функционально ориентированным. Здесь у вас есть некоторые признаки ОО — вы абстрагировали как идею вопроса, которая теперь прекрасно инкапсулирует данные викторины, так и концепцию запуска викторины. Теперь обратите внимание, что любое изменение самого теста не требует каких — либо изменений в вашем методе run_test, что значительно повышает удобство обслуживания. Кроме того, вы run_test делаете всего несколько предположений о questions — он ожидает, что это будет массив объектов, отвечающих на prompt и answer . Это отличная база для последующего внедрения полиморфизма

2. Однако давайте сделаем это еще лучше. Во — первых, похоже, что вы происходите из семьи Си-мы редко используем for while циклы и в ruby. Так что вместо for question in questions того, чтобы делать questions.each do |question| то, что гораздо больше похоже на рубин. в данном конкретном случае while используется правильно, но вам это не нужно begin/end : answer = gets.chomp while asnwer != ... тоже сработает. Поскольку мы здесь — здесь есть важное и опасное предположение — вы предполагаете, что на каждый вопрос будет 4 ответа. Попробуйте исправить это и сделать его более гибким.

3. Все данные вопросов / ответов делают ваш код более раздутым, чем он есть на самом деле. Возможно, было бы неплохо разделить данные и код и перенести вопросы в другой файл.