Deaf grandma - almost there

From the Chris Pine tutorial for beginners:

···

**
Write a Deaf Grandma program. Whatever you say to grandma (whatever
you type in), she should respond with HUH?! SPEAK UP, SONNY!, unless
you shout it (type in all capitals). If you shout, she can hear you
(or at least she thinks so) and yells back, NO, NOT SINCE 1938! To
make your program really believable, have grandma shout a different
year each time; maybe any year at random between 1930 and 1950. (This
part is optional, and would be much easier if you read the section on
Ruby's random number generator at the end of the methods chapter.)
You can't stop talking to grandma until you shout BYE.
Hint: Don't forget about chomp! 'BYE'with an Enter is not the same as
'BYE' without one!
Hint 2: Try to think about what parts of your program should happen
over and over again. All of those should be in your while loop.

**
Extend your Deaf Grandma program: What if grandma doesn't want you
to leave? When you shout BYE, she could pretend not to hear you.
Change your previous program so that you have to shout BYE three times
in a row. Make sure to test your program: if you shout BYE three
times, but not in a row, you should still be talking to grandma.

My code is below, and my question is:
Why can't I reset the 'byes' count to zero using the 'reset' method I've
defined?
I know it works when I change the 'else reset' to 'else byes = 0'

byes = 0

def didnthear
  puts 'SPEAK UP!'
end

def heard
    year = (rand(21) + 1930).to_s
    puts "I heard ya! Not since " + year
end

def reset
  byes = 0
end

while ( byes < 3 )
  said = gets.chomp

  if said == 'BYE'
    byes += 1
  else
    reset
  end

  if byes >= 3
    break
  end

  if said != said.upcase
    didnthear
  else
    heard
  end
end

puts "heard you 3 times, byeeee"
--
Posted via http://www.ruby-forum.com/.

It doesn't work because of scope. When you set 'byes = 0' in def
reset, you are setting a local variable with scope inside the reset
method. This is not the same as a local variable in the 'main' scope.

One way to fix this by using an 'instance' scope. Even though you
aren't technically in a class instance, at some level of abstraction
the default binding is an instance of a class. So, instead of 'byes'
as a variable, you could use '@byes'.

-Jonathan Nielsen

···

On Tue, May 18, 2010 at 11:04 AM, Stephen Hau <hellostephenhau@gmail.com> wrote:

From the Chris Pine tutorial for beginners:

**
Write a Deaf Grandma program. Whatever you say to grandma (whatever
you type in), she should respond with HUH?! SPEAK UP, SONNY!, unless
you shout it (type in all capitals). If you shout, she can hear you
(or at least she thinks so) and yells back, NO, NOT SINCE 1938! To
make your program really believable, have grandma shout a different
year each time; maybe any year at random between 1930 and 1950. (This
part is optional, and would be much easier if you read the section on
Ruby's random number generator at the end of the methods chapter.)
You can't stop talking to grandma until you shout BYE.
Hint: Don't forget about chomp! 'BYE'with an Enter is not the same as
'BYE' without one!
Hint 2: Try to think about what parts of your program should happen
over and over again. All of those should be in your while loop.

**
Extend your Deaf Grandma program: What if grandma doesn't want you
to leave? When you shout BYE, she could pretend not to hear you.
Change your previous program so that you have to shout BYE three times
in a row. Make sure to test your program: if you shout BYE three
times, but not in a row, you should still be talking to grandma.

My code is below, and my question is:
Why can't I reset the 'byes' count to zero using the 'reset' method I've
defined?
I know it works when I change the 'else reset' to 'else byes = 0'

byes = 0

def didnthear
puts 'SPEAK UP!'
end

def heard
year = (rand(21) + 1930).to_s
puts "I heard ya! Not since " + year
end

def reset
byes = 0
end

while ( byes < 3 )
said = gets.chomp

if said == 'BYE'
byes += 1
else
reset
end

if byes >= 3
break
end

if said != said.upcase
didnthear
else
heard
end
end

puts "heard you 3 times, byeeee"

Jonathan Nielsen wrote:

It doesn't work because of scope. When you set 'byes = 0' in def
reset, you are setting a local variable with scope inside the reset
method. This is not the same as a local variable in the 'main' scope.

One way to fix this by using an 'instance' scope. Even though you
aren't technically in a class instance, at some level of abstraction
the default binding is an instance of a class. So, instead of 'byes'
as a variable, you could use '@byes'.

-Jonathan Nielsen

Thanks Jonathan, that fixed it! I guess I got ahead of myself by using a
method before fully understanding scope. Lesson learnt :slight_smile:

···

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