Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.ruby > #3971 > unrolled thread

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

Started bySuper Goat <ruby-forum@sgoat.33mail.com>
First post2011-05-05 01:45 -0500
Last post2011-05-09 00:29 -0500
Articles 20 — 8 participants

Back to article view | Back to comp.lang.ruby


Contents

  Lets play a guessing game. (how to code this better?) Super Goat <ruby-forum@sgoat.33mail.com> - 2011-05-05 01:45 -0500
    Re: Lets play a guessing game. (how to code this better?) Stu <stu@rubyprogrammer.net> - 2011-05-05 02:28 -0500
    Re: Lets play a guessing game. (how to code this better?) Josh Cheek <josh.cheek@gmail.com> - 2011-05-05 02:51 -0500
    Re: Lets play a guessing game. (how to code this better?) John Feminella <johnf@bitsbuilder.com> - 2011-05-05 03:10 -0500
      Re: Lets play a guessing game. (how to code this better?) Johannes Held <johannes.held@informatik.uni-erlangen.de> - 2011-05-06 10:51 +0200
        Re: Lets play a guessing game. (how to code this better?) Johnny Morrice <spoon@killersmurf.com> - 2011-05-06 07:01 -0500
          Re: Lets play a guessing game. (how to code this better?) Johnny Morrice <spoon@killersmurf.com> - 2011-05-06 07:04 -0500
          Re: Lets play a guessing game. (how to code this better?) Johannes Held <johannes.held@informatik.uni-erlangen.de> - 2011-05-06 14:13 +0200
            Re: Lets play a guessing game. (how to code this better?) Johnny Morrice <spoon@killersmurf.com> - 2011-05-06 07:23 -0500
    Re: Lets play a guessing game. (how to code this better?) Jesús Gabriel y Galán <jgabrielygalan@gmail.com> - 2011-05-05 03:56 -0500
    Re: Lets play a guessing game. (how to code this better?) Martin Boese <boesemar@gmx.de> - 2011-05-05 10:32 -0500
    Re: Lets play a guessing game. (how to code this better?) Super Goat <ruby-forum@sgoat.33mail.com> - 2011-05-06 01:18 -0500
      Re: Lets play a guessing game. (how to code this better?) Jesús Gabriel y Galán <jgabrielygalan@gmail.com> - 2011-05-06 02:27 -0500
      Re: Lets play a guessing game. (how to code this better?) Josh Cheek <josh.cheek@gmail.com> - 2011-05-06 02:34 -0500
    Re: Lets play a guessing game. (how to code this better?) Super Goat <ruby-forum@sgoat.33mail.com> - 2011-05-08 00:08 -0500
      Re: Lets play a guessing game. (how to code this better?) Josh Cheek <josh.cheek@gmail.com> - 2011-05-08 00:30 -0500
      Re: Lets play a guessing game. (how to code this better?) Stu <stu@rubyprogrammer.net> - 2011-05-08 01:16 -0500
        Re: Lets play a guessing game. (how to code this better?) Stu <stu@rubyprogrammer.net> - 2011-05-08 02:22 -0500
          Re: Lets play a guessing game. (how to code this better?) Super Goat <ruby-forum@sgoat.33mail.com> - 2011-05-08 21:20 -0500
            Re: Lets play a guessing game. (how to code this better?) Stu <stu@rubyprogrammer.net> - 2011-05-09 00:29 -0500

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

FromSuper Goat <ruby-forum@sgoat.33mail.com>
Date2011-05-05 01:45 -0500
SubjectLets play a guessing game. (how to code this better?)
Message-ID<60cd2d7685f4d805fa7b7b953b5667d5@ruby-forum.com>
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/.

[toc] | [next] | [standalone]


#3972

FromStu <stu@rubyprogrammer.net>
Date2011-05-05 02:28 -0500
Message-ID<BANLkTim-F1KCtdmSfjv6sij23cFSd04pkg@mail.gmail.com>
In reply to#3971
Looks good. You don't need the extra call to_i where it is already an integer:

random = rand(100)
choice == 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> 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
>
>
> --
> Posted via http://www.ruby-forum.com/.
>
>

[toc] | [prev] | [next] | [standalone]


#3973

FromJosh Cheek <josh.cheek@gmail.com>
Date2011-05-05 02:51 -0500
Message-ID<BANLkTikk-CX2fSswa=WtzVeayk2F6V2JCg@mail.gmail.com>
In reply to#3971
[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!

[toc] | [prev] | [next] | [standalone]


#3974

FromJohn Feminella <johnf@bitsbuilder.com>
Date2011-05-05 03:10 -0500
Message-ID<BANLkTi=kWUQq1RgFpra6ecCB_YSEhT78aQ@mail.gmail.com>
In reply to#3971
There's a small bug:

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

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,

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

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

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

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:

====
max = 100
====

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> 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
>
>
> --
> Posted via http://www.ruby-forum.com/.
>
>

[toc] | [prev] | [next] | [standalone]


#4028

FromJohannes Held <johannes.held@informatik.uni-erlangen.de>
Date2011-05-06 10:51 +0200
Message-ID<92hr2kFplbU1@mid.dfncis.de>
In reply to#3974
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

[toc] | [prev] | [next] | [standalone]


#4032

FromJohnny Morrice <spoon@killersmurf.com>
Date2011-05-06 07:01 -0500
Message-ID<20110506130036.138b5255@beastie>
In reply to#4028
> 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

[toc] | [prev] | [next] | [standalone]


#4033

FromJohnny Morrice <spoon@killersmurf.com>
Date2011-05-06 07:04 -0500
Message-ID<20110506130346.19c395b4@beastie>
In reply to#4032
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)

[toc] | [prev] | [next] | [standalone]


#4034

FromJohannes Held <johannes.held@informatik.uni-erlangen.de>
Date2011-05-06 14:13 +0200
Message-ID<92i6t4Fnh2U1@mid.dfncis.de>
In reply to#4032
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

[toc] | [prev] | [next] | [standalone]


#4035

FromJohnny Morrice <spoon@killersmurf.com>
Date2011-05-06 07:23 -0500
Message-ID<20110506132330.49a31210@beastie>
In reply to#4034
> And now, the OP is frightenend of functional programming … ;-)

Good point.  

Please OP, for the love of all things computery do not code
like me.

[toc] | [prev] | [next] | [standalone]


#3978

FromJesús Gabriel y Galán <jgabrielygalan@gmail.com>
Date2011-05-05 03:56 -0500
Message-ID<BANLkTimxFoqDRr90Y9=X=oL1STUcvHrC9g@mail.gmail.com>
In reply to#3971
On Thu, May 5, 2011 at 8: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

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 = rand(100)
until (choice = get_valid_input) == target
   puts "Wrong, my number is #{choice < target ? 'higher' : 'lower'}"
end

Or something like that.

Jesus.

[toc] | [prev] | [next] | [standalone]


#3997

FromMartin Boese <boesemar@gmx.de>
Date2011-05-05 10:32 -0500
Message-ID<20110505163204.70927e77@ita-martin>
In reply to#3971
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
> 
> 


[toc] | [prev] | [next] | [standalone]


#4023

FromSuper Goat <ruby-forum@sgoat.33mail.com>
Date2011-05-06 01:18 -0500
Message-ID<b38c8af4585da663e93ac2f2facf10df@ruby-forum.com>
In reply to#3971
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/.

[toc] | [prev] | [next] | [standalone]


#4024

FromJesús Gabriel y Galán <jgabrielygalan@gmail.com>
Date2011-05-06 02:27 -0500
Message-ID<BANLkTikFiLoPK_gLtNSs+n+Vcmdw0G35Uw@mail.gmail.com>
In reply to#4023
On Fri, May 6, 2011 at 8:18 AM, Super Goat <ruby-forum@sgoat.33mail.com> wrote:
> 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.

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

[toc] | [prev] | [next] | [standalone]


#4025

FromJosh Cheek <josh.cheek@gmail.com>
Date2011-05-06 02:34 -0500
Message-ID<BANLkTikvyURgj9-iWYvGRjh7HLOBco2kcQ@mail.gmail.com>
In reply to#4023
[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]

[toc] | [prev] | [next] | [standalone]


#4113

FromSuper Goat <ruby-forum@sgoat.33mail.com>
Date2011-05-08 00:08 -0500
Message-ID<300d3c20c6331d56a96f4ec2018510c7@ruby-forum.com>
In reply to#3971
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/.

[toc] | [prev] | [next] | [standalone]


#4114

FromJosh Cheek <josh.cheek@gmail.com>
Date2011-05-08 00:30 -0500
Message-ID<BANLkTiky_8vPyTKb8E4R-BeFtO-g7xePRg@mail.gmail.com>
In reply to#4113
[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!"

[toc] | [prev] | [next] | [standalone]


#4116

FromStu <stu@rubyprogrammer.net>
Date2011-05-08 01:16 -0500
Message-ID<BANLkTim6YJ1ZQWw28Oh4v5gz+v-T-244Hg@mail.gmail.com>
In reply to#4113
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?
>
> 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 = (first_num + second_num)
  return( answer)
end

x = 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 = 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 = add_num 42, 100
y = add_num( x, 16)
z = add_num( y, x)
puts z
=> 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

[toc] | [prev] | [next] | [standalone]


#4118

FromStu <stu@rubyprogrammer.net>
Date2011-05-08 02:22 -0500
Message-ID<BANLkTikt1dCh8LyK65-JkyMYtj0N8jBWnw@mail.gmail.com>
In reply to#4116
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

[toc] | [prev] | [next] | [standalone]


#4146

FromSuper Goat <ruby-forum@sgoat.33mail.com>
Date2011-05-08 21:20 -0500
Message-ID<bac0bfea865bcd8393da546bc2652938@ruby-forum.com>
In reply to#4118
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/.

[toc] | [prev] | [next] | [standalone]


#4149

FromStu <stu@rubyprogrammer.net>
Date2011-05-09 00:29 -0500
Message-ID<BANLkTi=Gguy=AHfK83_Cx9w80wKhwnYQhg@mail.gmail.com>
In reply to#4146
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

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.ruby


csiph-web