Severin Newsom wrote:
> def check
> answer = gets.chomp.downcase
> if (answer == c_answer)
>   score = score + 1
> else
>   puts 'The correct answer was ' + c_answer + '.'
> end
> end
> puts 'Which is the slowest class?'
> puts 'A - Pyro'
> puts 'B - Demoman'
> puts 'C - Heavy'
> puts 'D - Soldier'
> c_answer = 'c'
> check
> 
> I understand the problem (mostly)

I think you'd find it helpful if you post the actual error you get when 
you run this program:

quiz.rb:3:in `check': undefined local variable or method `c_answer' for 
main:Object (NameError)
  from quiz.rb:15

This basically tells you the problem: ruby cannot find anything called 
"c_answer". This is because c_answer is a local variable - but methods 
cannot access local variables defined outside them. Every method defined 
with 'def' starts with a clean slate as far as local variables are 
concerned. There are very good reasons for this which I won't go into 
here.

So basically, you either make c_answer a global variable like $c_answer 
(bad practice), or pass it in as an argument to the method (good 
practice).

def check(c_answer)
answer = gets.chomp.downcase
if (answer == c_answer)
  score = score + 1
else
  puts 'The correct answer was ' + c_answer + '.'
end
end
puts 'Which is the slowest class?'
puts 'A - Pyro'
puts 'B - Demoman'
puts 'C - Heavy'
puts 'D - Soldier'
check('c')

This moves you along, but if you enter a right answer you get a new 
error:

quiz.rb:4:in `check': undefined method `+' for nil:NilClass 
(NoMethodError)
  from quiz.rb:14

This is the same problem, in this case 'score' is not accessible inside 
the method. However because you have an assignment to score (score = 
...) a local variable is automatically brought into existence with value 
'nil', even though the assignment hasn't actually executed yet. This is 
why you get a potentially confusing error message. "Undefined method... 
for nil" means you tried to execute nil.something (nil.+ in this case)

Again you have a number of options:

1. Have a global variable $score (bad practice, makes it hard to re-use 
code, non-thread-safe etc)

2. Pass in the old score, and return the new score. This is a 
"functional" programming style, meaning that your function doesn't 
actually modify any state, but just returns new calculated values.

def check(c_answer, score)
  answer = gets.chomp.downcase
  if (answer == c_answer)
    score = score + 1
  else
    puts 'The correct answer was ' + c_answer + '.'
  end
  return score
end

score = 0

puts 'Which is the slowest class?'
puts 'A - Pyro'
puts 'B - Demoman'
puts 'C - Heavy'
puts 'D - Soldier'
score = check('c', score)

puts "Your score is #{score}"

3. Build a class which holds the state for your quiz session. This is 
the "object oriented" style.

class QuizSession
  attr_accessor :score
  def initialize
    @score = 0
  end
  def check(c_answer)
    answer = gets.chomp.downcase
    if (answer == c_answer)
      @score = @score + 1
    else
      puts 'The correct answer was ' + c_answer + '.'
    end
  end
end

session = QuizSession.new

puts 'Which is the slowest class?'
puts 'A - Pyro'
puts 'B - Demoman'
puts 'C - Heavy'
puts 'D - Soldier'
session.check('c')

puts "Your score is #{session.score}"

I have presented these options making the minimum changes to your 
existing code.

You can think of ways of extending the QuizSession object - for example 
loading the list of questions from a file, and including the ability to 
iterate through the questions-and-answers.

At the moment, QuizSession is just a score counter and answer checker, 
but that in itself is a useful function, and a good example of 
encapsulation (except that it uses 'puts' and so has some user-interface 
built in as well)

You could consider making the user interface a separate object, so that 
you could plug in a CLI Q&A session, a TK Q&A session, a web-based Q&A 
session etc.

HTH,

Brian.
-- 
Posted via http://www.ruby-forum.com/.