Lets play a guessing game. (how to code this better?)

Discussion in 'Ruby' started by Super Goat, May 5, 2011.

  1. Super Goat

    Super Goat Guest

    I am a new Rubyist. I told my friend that I was learning Ruby. He asked
    me how that was going and then gave me a little challenge. His
    challenge, "Write a text game that guesses numbers 0-100". My reply,
    "you mean it picks a number at random, and you guess the number, it
    tells you higher or lower until you get it?". Up to this point I had not
    coded anything in Ruby on my own (aside from the examples in the book)
    and I saw this as a great first challenge. So here is what I got. It
    took me some time. I ran into trouble because I forgot to take into
    consideration the Class of the variables and couldn't figure out why the
    loops weren't working.
    My question to you all... how could I have done this better or do you
    seeing anything that is wrong. Attached is the code. Thanks for the
    feedback.

    Attachments:
    http://www.ruby-forum.com/attachment/6168/100guess.rb


    --
    Posted via http://www.ruby-forum.com/.
     
    Super Goat, May 5, 2011
    #1
    1. Advertising

  2. Super Goat

    Stu Guest

    Looks good. You don't need the extra call to_i where it is already an integ=
    er:

    random =3D rand(100)
    choice =3D=3D random

    Both expressions are fine without any castiing.

    small nit pick. ruby is on my machine in /usr/local/bin ... to make
    this portable use:

    #!/usr/bin/env ruby

    I suggest your next task is to break everything down to methods. When
    you get comfortable with the concept of methods make your user input
    more strict as to only acquire a number. You did a very good job,
    Keep it going.

    ~Stu

    On Thu, May 5, 2011 at 1:45 AM, Super Goat <ruby-forum@sgoat.33mail.com> wr=
    ote:
    > I am a new Rubyist. I told my friend that I was learning Ruby. He asked
    > me how that was going and then gave me a little challenge. His
    > challenge, "Write a text game that guesses numbers 0-100". My reply,
    > "you mean it picks a number at random, and you guess the number, it
    > tells you higher or lower until you get it?". Up to this point I had not
    > coded anything in Ruby on my own (aside from the examples in the book)
    > and I saw this as a great first challenge. So here is what I got. It
    > took me some time. I ran into trouble because I forgot to take into
    > consideration the Class of the variables and couldn't figure out why the
    > loops weren't working.
    > My question to you all... how could I have done this better or do you
    > seeing anything that is wrong. =A0Attached is the code. Thanks for the
    > feedback.
    >
    > Attachments:
    > http://www.ruby-forum.com/attachment/6168/100guess.rb
    >
    >
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >
     
    Stu, May 5, 2011
    #2
    1. Advertising

  3. Super Goat

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Thu, May 5, 2011 at 1:45 AM, Super Goat <ruby-forum@sgoat.33mail.com>wrote:

    > I am a new Rubyist. I told my friend that I was learning Ruby. He asked
    > me how that was going and then gave me a little challenge. His
    > challenge, "Write a text game that guesses numbers 0-100". My reply,
    > "you mean it picks a number at random, and you guess the number, it
    > tells you higher or lower until you get it?". Up to this point I had not
    > coded anything in Ruby on my own (aside from the examples in the book)
    > and I saw this as a great first challenge. So here is what I got. It
    > took me some time. I ran into trouble because I forgot to take into
    > consideration the Class of the variables and couldn't figure out why the
    > loops weren't working.
    > My question to you all... how could I have done this better or do you
    > seeing anything that is wrong. Attached is the code. Thanks for the
    > feedback.
    >
    > Attachments:
    > http://www.ruby-forum.com/attachment/6168/100guess.rb
    >
    >

    Hi, Super Goat :)

    Congratulations on your first program! Hope you're enjoying Ruby.
    Here are some thoughts, that might be helpful:

    * On line1 your shebang is `#!/usr/bin/ruby`, but the best shebang is
    `#!/usr/bin/env ruby` because Ruby can be located in lots of different
    places, but env is always (I think) located in /usr/bin/env, and it is smart
    enough to figure out where your real Ruby is and then invoke it.

    * On line 4, you have `rand(100).to_i`, rand already returns an integer when
    you pass it a parameter, so you don't need to use to_i on it (
    http://www.ruby-doc.org/core/classes/Kernel.html#M001388)

    * For that variable, I would have probably named it "target" rather than
    "random", I think this clearer.

    * On line 11, `if choice > random.to_i` again you are converting it to an
    integer, but it is already an integer. (not harmful, but redundant and thus
    confusing as it makes reader say "wait, I thought it was an integer already,
    what did I miss?")

    * Lines 13-14 look like this:
    if choice > random.to_i
    puts "\nIncorrect, please choose a lower number."
    else puts "\nIncorrect, please choose a higher number."
    end

    Your indenting is off, the if/else/end should be at the same level, and for
    multiline conditionals, the code would go between them, so it should look
    like this:

    if choice > target
    puts "\nIncorrect, please choose a lower number."
    else
    puts "\nIncorrect, please choose a higher number."
    end

    I would personally probably save space by putting the conditional into the
    string like this:
    puts "\nIncorrect, please choose a #{if choice > target then 'higher' else
    'lower' end} number"

    I'm not sure whether many other Rubyists would do that or not, but I like it
    much better.

    * On line 16, you have gets.chomp.to_i The chomp here is unnecessary,
    because to_i will disregard anything after the digit.

    ---

    Anyway, nice job. Keep it up, after you get comfortable with the language,
    you can play with gems, which is where all the fun stuff is!
     
    Josh Cheek, May 5, 2011
    #3
  4. There's a small bug:

    =3D=3D=3D=3D
    puts "Choose a number between 0 and 100"
    random =3D rand(100).to_i
    =3D=3D=3D=3D

    This actually produces numbers between 0 and 99 inclusive, not 0 and
    100. Also the name "random" doesn't describe the point of the variable
    in the program, which is to serve as the answer. So it might be better
    to call it "answer", for instance. Finally, `rand(100)` already
    produces an integer, so you don't need the .to_i method.

    Also, for this condition,

    =3D=3D=3D=3D
    until choice <=3D 100 and choice >=3D 0
    =3D=3D=3D=3D

    a more succinct way of writing this is to check if it's included in
    the range 0..100:

    =3D=3D=3D=3D
    until (0..100).include? choice
    =3D=3D=3D=3D

    Next, notice that "100" appears a lot, so it might be better to
    describe what that number is -- it's the maximum value that your
    random number can take on. So, w emight write:

    =3D=3D=3D=3D
    max =3D 100
    =3D=3D=3D=3D

    and then use `max` everywhere instead of the `100` literal.

    Otherwise, looks good overall for your first attempt at this, minus a
    few rough spots. For another challenge, you might try writing a
    program that can guess a number between 0 and 100 in as few guesses as
    possible (hint: it should take around 7 guesses).

    ~ jf
    --
    John Feminella
    Principal Consultant, BitsBuilder
    LI: http://www.linkedin.com/in/johnxf
    SO: http://stackoverflow.com/users/75170/



    On Thu, May 5, 2011 at 02:45, Super Goat <ruby-forum@sgoat.33mail.com> wrot=
    e:
    > I am a new Rubyist. I told my friend that I was learning Ruby. He asked
    > me how that was going and then gave me a little challenge. His
    > challenge, "Write a text game that guesses numbers 0-100". My reply,
    > "you mean it picks a number at random, and you guess the number, it
    > tells you higher or lower until you get it?". Up to this point I had not
    > coded anything in Ruby on my own (aside from the examples in the book)
    > and I saw this as a great first challenge. So here is what I got. It
    > took me some time. I ran into trouble because I forgot to take into
    > consideration the Class of the variables and couldn't figure out why the
    > loops weren't working.
    > My question to you all... how could I have done this better or do you
    > seeing anything that is wrong. =C2=A0Attached is the code. Thanks for the
    > feedback.
    >
    > Attachments:
    > http://www.ruby-forum.com/attachment/6168/100guess.rb
    >
    >
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >
     
    John Feminella, May 5, 2011
    #4
  5. On Thu, May 5, 2011 at 8:45 AM, Super Goat <ruby-forum@sgoat.33mail.com> wr=
    ote:
    > I am a new Rubyist. I told my friend that I was learning Ruby. He asked
    > me how that was going and then gave me a little challenge. His
    > challenge, "Write a text game that guesses numbers 0-100". My reply,
    > "you mean it picks a number at random, and you guess the number, it
    > tells you higher or lower until you get it?". Up to this point I had not
    > coded anything in Ruby on my own (aside from the examples in the book)
    > and I saw this as a great first challenge. So here is what I got. It
    > took me some time. I ran into trouble because I forgot to take into
    > consideration the Class of the variables and couldn't figure out why the
    > loops weren't working.
    > My question to you all... how could I have done this better or do you
    > seeing anything that is wrong. =A0Attached is the code. Thanks for the
    > feedback.
    >
    > Attachments:
    > http://www.ruby-forum.com/attachment/6168/100guess.rb


    Apart from the other comments, I would like to point out that the
    check about the choice being a valid number (between 0 and 100) is
    made only for the first choice. After the first incorrect choice, you
    already inside the second loop, and don't check again.
    My advice is to create a method that contains that logic: outputting a
    prompt, getting the input from the user and validating it, the code
    would get much cleaner:

    def get_valid_input
    # the prompt and validation logic here
    end

    target =3D rand(100)
    until (choice =3D get_valid_input) =3D=3D target
    puts "Wrong, my number is #{choice < target ? 'higher' : 'lower'}"
    end

    Or something like that.

    Jesus.
     
    Jesús Gabriel y Galán, May 5, 2011
    #5
  6. Super Goat

    Martin Boese Guest

    On Thu, 5 May 2011 15:45:52 +0900
    Super Goat <ruby-forum@sgoat.33mail.com> wrote:

    > I am a new Rubyist. I told my friend that I was learning Ruby. He
    > asked me how that was going and then gave me a little challenge. His
    > challenge, "Write a text game that guesses numbers 0-100". My reply,
    > "you mean it picks a number at random, and you guess the number, it
    > tells you higher or lower until you get it?". Up to this point I had
    > not coded anything in Ruby on my own (aside from the examples in the
    > book) and I saw this as a great first challenge. So here is what I
    > got. It took me some time. I ran into trouble because I forgot to
    > take into consideration the Class of the variables and couldn't
    > figure out why the loops weren't working.
    > My question to you all... how could I have done this better or do you
    > seeing anything that is wrong. Attached is the code. Thanks for the
    > feedback.


    Hey, ruby-quiz is back?!
    This is how I would have done it... One loop, break-out once you got the
    number. Maybe it helps.. Cheers, Martin


    magic = rand(101).to_i
    puts "Guess the magic number!"

    loop do
    print "Choose 0-100> "
    n = gets.to_i
    if !(0..100).include?(n)
    puts "0-100!"
    next
    end
    puts "Higher!" if n<magic
    puts "Lower!" if n>magic
    break if n==magic
    end

    puts "You won: #{magic} is the number!"

    >
    > Attachments:
    > http://www.ruby-forum.com/attachment/6168/100guess.rb
    >
    >
     
    Martin Boese, May 5, 2011
    #6
  7. Super Goat

    Super Goat Guest

    Thanks everyone for taking the time to reply!

    The reason I had 'rand(100).to_i' and 'random.to_i' is because in IRB it
    told me it was a Fixnum. Also, I had just figured out why my operators
    weren't working so I wanted everything to be an integer. Obviously, in
    retrospect, I see now that I didn't have to do it that way.

    After I submitted to Ruby-Forum I did notice that when I was checking to
    see if the input was within range that it would only do this at the
    beginning. Putting that code in was an afterthought. I also thought
    that I should really check to see if it was a number but I didn't know
    how to do that.

    I was unaware that I didn't need the chomp in 'gets.chomp.to_i'.

    I am still trying to wrap my head around Methods. I get it, but don't
    know how to put down the code. Even when I look at Jesus's example I am
    a bit confused but I have a feeling that using Methods is a very Rubyist
    thing and the way Ruby was intended to be written.

    I really like Martin's example.

    I am going to try to use a Method and make this work and see if I can
    figure out how to reject any input that isn't a number (probably isn't
    hard just don't know how yet).

    I want to thank everyone again for their help. I definitely feel
    welcomed and will be back.

    Goat

    --
    Posted via http://www.ruby-forum.com/.
     
    Super Goat, May 6, 2011
    #7
  8. On Fri, May 6, 2011 at 8:18 AM, Super Goat <ruby-forum@sgoat.33mail.com> wr=
    ote:
    > I am still trying to wrap my head around Methods. =A0I get it, but don't
    > know how to put down the code. =A0Even when I look at Jesus's example I a=

    m
    > a bit confused but I have a feeling that using Methods is a very Rubyist
    > thing and the way Ruby was intended to be written.


    A method is just a block of code with a name that can be invoked from
    other points in the code.
    It can receive parameters, which are like local variables within the method=
     
    Jesús Gabriel y Galán, May 6, 2011
    #8
  9. Super Goat

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Fri, May 6, 2011 at 1:18 AM, Super Goat <ruby-forum@sgoat.33mail.com>wrote:

    > Thanks everyone for taking the time to reply!
    >
    > The reason I had 'rand(100).to_i' and 'random.to_i' is because in IRB it
    > told me it was a Fixnum. Also, I had just figured out why my operators
    > weren't working so I wanted everything to be an integer. Obviously, in
    > retrospect, I see now that I didn't have to do it that way.
    >
    >

    In OOP, classes can inherit functionality from other classes. There are
    several kinds of Integers, Fixnum is one of them, Bignum is another (okay,
    actually, those are the only two).

    1.class # => Fixnum
    1.kind_of? Integer # => true
    Fixnum.ancestors # => [Fixnum, Integer, Numeric, Comparable, Object,
    Kernel, BasicObject]

    n = 10**1000
    n.class # => Bignum
    n.kind_of? Integer # => true
    Bignum.ancestors # => [Bignum, Integer, Numeric, Comparable, Object,
    Kernel, BasicObject]
     
    Josh Cheek, May 6, 2011
    #9
  10. On 05.05.2011 10:10, John Feminella wrote:
    > For another challenge, you might try writing a program that can guess
    > a number between 0 and 100 in as few guesses as possible (hint: it
    > should take around 7 guesses).

    Ah, that's a nice challenge.
    You could even try to solve it with the functional pradigm. In this
    case: recursion!

    http://pastie.org/1870939

    --
    Johannes
     
    Johannes Held, May 6, 2011
    #10
  11. > You could even try to solve it with the functional pradigm.

    That's not functional enough for me ;)

    In case the syntax gets chewed: http://pastie.org/1871414

    # Z combinator defines explicit recursion
    Z = lambda { |f| (lambda {|x| f.call(lambda {|*ys|
    x.call(x).call(*ys)})}).call(lambda {|x| f.call(lambda {|*ys|
    x.call(x).call(*ys)})})}

    # The guess combinator holds a reference to itself in the 'again'
    variable Guess = lambda do |again|
    lambda do |magic|
    print "Choose 0-100> "
    n = gets.to_i
    if !(0..100).include?(n)
    puts "0-100!"
    next
    end
    puts "Higher!" if n<magic
    puts "Lower!" if n>magic
    if n==magic
    puts "You won: #{magic} is the number!"
    else
    again.call magic
    end
    end
    end

    magic = rand(101).to_i
    puts "Guess the magic number!"

    Z.call(Guess).call(magic)

    Clearly this is the most obvious solution.

    Cheers,
    Johnny
     
    Johnny Morrice, May 6, 2011
    #11
  12. Actually I left a bug in that due to side effects. (When will lazy
    functional ruby be out?)

    Here you go:

    # I have defined the combinators as constants to reflect the TRUTH and
    PURITY of COMPUTER SCIENCE

    # Z combinator defines explicit recursion
    Z = lambda { |f| (lambda {|x| f.call(lambda {|*ys|
    x.call(x).call(*ys)})}).call(lambda {|x| f.call(lambda {|*ys|
    x.call(x).call(*ys)})})}

    # The guess combinator holds a reference to itself in the 'again'
    variable Guess = lambda do |again|
    lambda do |magic|
    print "Choose 0-100> "
    n = gets.to_i
    if (0..100).include?(n)
    puts "Higher!" if n<magic
    puts "Lower!" if n>magic
    if n==magic
    puts "You won: #{magic} is the number!"
    else
    again.call magic
    end
    else
    puts "0-100!"
    again.call magic
    end
    end
    end

    magic = rand(101).to_i
    puts "Guess the magic number!"

    Z.call(Guess).call(magic)
     
    Johnny Morrice, May 6, 2011
    #12
  13. On 06.05.2011 14:01, Johnny Morrice wrote:
    > That's not functional enough for me;)

    And now, the OP is frightenend of functional programming … ;-)

    You may provide functional code for the machine-solver, too.

    --
    Johannes
     
    Johannes Held, May 6, 2011
    #13
  14. > And now, the OP is frightenend of functional programming =E2=80=A6 ;-)

    Good point. =20

    Please OP, for the love of all things computery do not code
    like me.
     
    Johnny Morrice, May 6, 2011
    #14
  15. Super Goat

    Super Goat Guest

    Thanks again for everyones input and thanks to Jesus for explaining and
    providing examples for using a method in my code.

    >And now, the OP is frightenend of functional programming

    No, this sounds like fun. I'll work my way there eventually.

    So attached is my updated version.

    As you can see I also added a # of 'guesses' variable that counts the
    number of attempts and then exits when you hit the max. That took me a
    little while to figure out, but I am pleased that I got it.

    I was thinking of asking if the player would like to play again and then
    figuring out how to restart the whole thing but I wasn't sure how to do
    this. How can I make prompt to "Play again?" and when answered "Yes"
    restart, whether the person wins or loses (or if "No" just exits)? Or
    is the way my code is written make this impossible?

    Attachments:
    http://www.ruby-forum.com/attachment/6181/meth_100guess.rb


    --
    Posted via http://www.ruby-forum.com/.
     
    Super Goat, May 8, 2011
    #15
  16. Super Goat

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Sun, May 8, 2011 at 12:08 AM, Super Goat <ruby-forum@sgoat.33mail.com>wrote:

    >
    > Attachments:
    > http://www.ruby-forum.com/attachment/6181/meth_100guess.rb
    >
    >


    > attempts = "0".to_i


    In the same way you have string literals (the "0"), you also have integer
    literals (just 0).
    0 == "0".to_i # => true

    So just make it `attempts = 0`, same for flag.



    > flag = "8".to_i


    This seems to record the maximum number of times you can guess. I would call
    it something like "max_attempts", "flag" is not a descriptive name.



    On Sun, May 8, 2011 at 12:08 AM, Super Goat <ruby-forum@sgoat.33mail.com>wrote:

    >
    > I was thinking of asking if the player would like to play again and then
    > figuring out how to restart the whole thing but I wasn't sure how to do
    > this. How can I make prompt to "Play again?" and when answered "Yes"
    > restart, whether the person wins or loses (or if "No" just exits)? Or
    > is the way my code is written make this impossible?
    >
    >

    Right now there is no mechanism to get back to the beginning where variables
    are set and such. What if you had a method that did everything involved with
    a game, then you could play a game by calling that method. That would allow
    you to just have a little piece of code that is responsible for handling
    whether you should play another game or not.

    def play_game
    # ...
    end

    def play_again?
    # prompt user, return true or false
    end

    play_game
    play_game while play_again?
    puts "goodbye!"
     
    Josh Cheek, May 8, 2011
    #16
  17. Super Goat

    Stu Guest

    On Sun, May 8, 2011 at 12:08 AM, Super Goat <ruby-forum@sgoat.33mail.com> w=
    rote:

    >
    > I was thinking of asking if the player would like to play again and then
    > figuring out how to restart the whole thing but I wasn't sure how to do
    > this. How can I make prompt to "Play again?" and when answered "Yes"
    > restart, whether the person wins or loses (or if "No" just exits)? =A0Or
    > is the way my code is written make this impossible?
    >
    > Attachments:
    > http://www.ruby-forum.com/attachment/6181/meth_100guess.rb
    >
    >
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >


    You can do it with more methods. In fact you should break as much down
    as possible. The concept is to keep every method as small as possible.
    Does one thing and does it well. Ruby allows you to add ? at the end
    of a method name which should return true/false so you could almost
    have it kind of tell a story.

    Ruby is also liberal with it's parens and has implied return statements.

    so for a contrived example a traditional language would look like this:

    def add_num( first_num, second_num)
    answer =3D (first_num + second_num)
    return( answer)
    end

    x =3D add_num( 42, 100)

    where in ruby it could look like this:

    def add_num first_num, second_num
    first_num + second_num
    end

    x =3D add_num 42, 100

    methods always return a value (this is contrast to functions which do
    one thing and do it well but may only return success or error) Ruby
    has only methods.

    Methods give the user the ability to reuse code using the example above:

    x =3D add_num 42, 100
    y =3D add_num( x, 16)
    z =3D add_num( y, x)
    puts z
    =3D> 300

    using good names for your methods make it easier for others to read
    them as well as making them easier to read years later if you ever
    have to revisit.

    Method definitions start with the def keyword, the method name, then
    there are optional arguments which are variables passed as copies into
    the scope of the method. The method body can contain the same code
    logic you have which reads much like a fall through shell script right
    now. Every method closes with the end keyword.

    The last statement returns regardless in ruby.

    My personal preference in style is to keep the parens in the
    definition but only use the return when I need to force it:

    def add_num( first_num, second_num)
    first_num + second_num
    end

    Once you have normalized the script in pure methods we can then begin
    to talk about how user created methods can relate to user created
    classes and start talking about object oriented programming.

    ~Stu
     
    Stu, May 8, 2011
    #17
  18. Super Goat

    Stu Guest

    I also wanted to add that you can embed methods directly into the
    argument area.

    following my previous example:

    x = add_num( 42, 100)
    add_num( x, add_num(16, x))
    => 300

    in this case add_num(16, x) is evaluating 16+142 before sending it through.

    My last piece of advice when you begin to figure out names for your
    variables and methods is to separate as much of the game logic as you
    can from the peripheral data. This will make it easier to change
    things in the long run if you need.

    puts "\nLets play a guessing game! You have 8 guesses before you lose."
    target = rand(101) #creates a random number from 0 - 100
    attempts = "0".to_i #
    flag = "8".to_i

    can be rewritten like so

    max_user_attempts = 8
    @attempt_counter = 0
    directions = "\nLets play a guessing game! You have
    #{max_user_attempts.to_s} guesses before you lose."
    winning_response = rand(101)

    def game_loop
    print directions
    #.. start loop and call many methods
    end

    If you want to change max_user_attempts later you have just one place
    to change it. or better yet create a method that ask the user if they
    want 'easy', 'medium', 'hard', 'elite' and set it based on the user
    response. ( good way to learn about hashes though you can program it
    other ways. Make easy infinite for responses so you can have the
    chance to test the functionality of your game without really playing
    it. sneaking in an easter egg cheat to reveal winning_response is also
    a good way for testing =)

    Last note. notice the @ in front of attempt_counter. This allows for
    methods to see the variable outside their own scope. it's optional if
    you want to use it but allows for direct manipulation:

    def increment_attempt
    @attempt_counter += 1
    end

    vs a more generic approach:

    counter = 0
    def inc_counter( arg)
    arg += 1
    end
    counter = inc_counter( counter)

    I hope I haven't confused you. I do not want to make it
    overcomplicated or obfuscate it so please ask many questions. Methods(
    and functions) are a very important concept to grok in every
    programming language in every paradigm.

    ~Stu
     
    Stu, May 8, 2011
    #18
  19. Super Goat

    Super Goat Guest

    Josh Cheek wrote in post #997327:
    >> attempts = "0".to_i

    >
    > In the same way you have string literals (the "0"), you also have
    > integer
    > literals (just 0).
    > 0 == "0".to_i # => true
    >
    > So just make it `attempts = 0`, same for flag.


    Josh: I originally had the variables like that way you described but I
    changed it because I was getting an error when I tried to add 1
    'attempts += 1'. I just now changed it back and of course there was no
    error so I must have mistyped something. Who knows now but thanks for
    pointing that out.

    >
    > On Sun, May 8, 2011 at 12:08 AM, Super Goat
    > <ruby-forum@sgoat.33mail.com>wrote:
    >
    >>
    >> I was thinking of asking if the player would like to play again and then
    >> figuring out how to restart the whole thing but I wasn't sure how to do
    >> this. How can I make prompt to "Play again?" and when answered "Yes"
    >> restart, whether the person wins or loses (or if "No" just exits)? Or
    >> is the way my code is written make this impossible?
    >>
    >>

    > Right now there is no mechanism to get back to the beginning where
    > variables
    > are set and such. What if you had a method that did everything involved
    > with
    > a game, then you could play a game by calling that method. That would
    > allow
    > you to just have a little piece of code that is responsible for handling
    > whether you should play another game or not.
    >
    > def play_game
    > # ...
    > end
    >
    > def play_again?
    > # prompt user, return true or false
    > end
    >
    > play_game
    > play_game while play_again?
    > puts "goodbye!"


    I like this idea and will give this a go on my next version.
    Thanks again for your insight.

    ==============================

    Stu wrote in post #997331:
    > On Sun, May 8, 2011 at 12:08 AM, Super Goat
    > <ruby-forum@sgoat.33mail.com> wrote:
    >
    >>
    >> --
    >> Posted via http://www.ruby-forum.com/.
    >>
    >>

    >
    > Every method closes with the end keyword.
    >
    > The last statement returns regardless in ruby.
    >


    Can you explain these two lines more thoroughly and when you say 'the
    last statement returns', where does it return to.

    Sorry for my ignorance, this is my first true attempt to learn a
    language (I took 2 classes C++ 15 years ago in highschool)



    Stu wrote in post #997333:
    > My last piece of advice when you begin to figure out names for your
    > variables and methods is to separate as much of the game logic as you
    > can from the peripheral data. This will make it easier to change
    > things in the long run if you need.
    >
    > puts "\nLets play a guessing game! You have 8 guesses before you lose."
    > target = rand(101) #creates a random number from 0 - 100
    > attempts = "0".to_i #
    > flag = "8".to_i
    >
    > can be rewritten like so
    >
    > max_user_attempts = 8
    > @attempt_counter = 0
    > directions = "\nLets play a guessing game! You have
    > #{max_user_attempts.to_s} guesses before you lose."
    > winning_response = rand(101)
    >
    > def game_loop
    > print directions
    > #.. start loop and call many methods
    > end


    Stu, this make complete sense. I probably would have read this or
    sortof figured this out eventually but now I will really consider it as
    I start to code each project.

    > Last note. notice the @ in front of attempt_counter. This allows for
    > methods to see the variable outside their own scope. it's optional if
    > you want to use it but allows for direct manipulation:
    >
    > def increment_attempt
    > @attempt_counter += 1
    > end
    >


    So can I just refer to increment_attempt each time i want the
    @attempt_counter to increase by one? for instance, replacing the way i
    did it here.

    until (choice = get_valid_input) == target
    puts "\nWrong, my number is #{choice < target ? 'higher' : 'lower'}"
    attempts += 1

    with

    until (choice = get_valid_input) == target
    puts "\nWrong, my number is #{choice < target ? 'higher' : 'lower'}"
    @attempt_counter

    and if there were any other places where I would want to increase the
    attempts just refer to @attempt_counter again?

    > I hope I haven't confused you. I do not want to make it
    > overcomplicated or obfuscate it so please ask many questions. Methods(
    > and functions) are a very important concept to grok in every
    > programming language in every paradigm.
    >
    > ~Stu


    Not at all Stu. I think you are really helping me establish some solid
    Ruby coding processes and techniques. (I'm sure a lot of this applies to
    more than just Ruby) One thing I have learned, which may sound obvious
    but I never realized, is that there are so many ways to code something
    and get the same end result. That coding can even be someones style.
    Thanks for taking your time to explain everything.


    Goat

    --
    Posted via http://www.ruby-forum.com/.
     
    Super Goat, May 9, 2011
    #19
  20. Super Goat

    Stu Guest

    Hi Goat,

    The basic skeletal structure of a ruby method is so:

    def method_name( arg1, arg2, *args) # and so on
    #.. method body
    return #.. or implicit return( i.e. the keyword is optional)
    end

    In traditional languages you have a return keyword which returns a
    value to the caller. In ruby everything is a caller and everything is
    a sender. This is another paradigm you'll come to understand the more
    you work with ruby.

    very contrived example:

    def return_42( )
    return( 42)
    end

    is equivalent to

    def return_42
    42
    end

    Here is another conceptual example with my style please try it in irb.

    I will create a adder method and then create a square method using the
    the previous methods in effort to show you how methods can be reused:

    def adder( x,y)
    x + y
    end

    def square_num( x)
    y = 0
    count = 0

    while count != x
    y+=adder( x,0)
    count += 1
    end

    return( y)
    end

    irb session:
    >> square_num( 3)

    => 9
    >> adder( 1, 4)

    => 5
    >> square_num( adder( 3, 1))

    => 16
    >> adder( square_num( 3), square_num( 5))

    => 34

    starting with the adder method I did not use a return statement. I
    could have rewritten the last line as return( x+y) but I didn't. It's
    up to you to figure out if it's more readable with or without it.
    Either way if I write this code:

    var = adder( 41, 100) # the variable 'var' will be populated with the
    return value from the function adder.

    The square_num( ) method reuses the adder method in a conditional
    while loop. Though contrived for this example it's a good way to
    understand methods to be composed for reuse. When you get to get to
    OOPS programming there is a concept of composite objects. The concept
    is the same but in a less linear fashion.

    You'll also notice I used the return statement in the square_num( )
    method. I did this because I personally feel the freestanding variable
    'y' looks awkward and less readable. Others opinion on the subject may
    vary. It's up to you to decide what works best and use those
    conventions.

    A more succinct way to write the square_num( ) method would be this:

    def square_ruby_way( x)
    y = 0
    x.times { y+=adder(x,0) }
    y
    end

    The right ruby way( and quickest) with the most most brevity would be
    to use ruby's built in power of operator method:

    def best_ruby_square( x)
    x**2
    end

    The first example of course removes the while loop and follows one of
    ruby's object oriented conventions. I don't want to get to deep into
    it as it is a abstraction of a while loop and begins to expose some of
    ruby's built in iterator design patterns. The times method should be
    saved for another discussion after you get your bearings with method
    creation and definition.

    ~Stu
     
    Stu, May 9, 2011
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. feba
    Replies:
    24
    Views:
    963
    Arnaud Delobelle
    Dec 17, 2008
  2. robic0
    Replies:
    21
    Views:
    310
    robic0
    Mar 9, 2006
  3. erman koseoglu

    vhdl guessing game

    erman koseoglu, Nov 9, 2012, in forum: VHDL
    Replies:
    2
    Views:
    514
    Thomas Stanka
    Nov 13, 2012
  4. Armando Montes De Oca
    Replies:
    19
    Views:
    288
    Armando Montes De Oca
    Jun 6, 2013
  5. Robert Gonda

    Help with guessing game :D

    Robert Gonda, Oct 29, 2013, in forum: Python
    Replies:
    31
    Views:
    301
    Dave Angel
    Oct 30, 2013
Loading...

Share This Page