[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Cards Class

Peter Marsh

4/23/2007 9:17:00 PM

Hi, I'm an utter newbie to Ruby (and OOP!) and I thought I'd share my
very first project. It's nothing special - just a simple class that
simulates a deck of cards, but I'd like to get your comments to see if
there's anything I can do better (enjoy!):

class Deck
@@Cards =
['Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King','Ace']
@@Suits = ['Spades','Hearts','Diamonds','Clubs']

def initialize
@top_card = -1
@deck = []
52.times do |card|
@deck << card
end
end

def draw
@top_card = @top_card + 1
if @top_card < 52
@deck[@top_card]
else
raise 'There are only 52 cards in a deck!'
end
end

def shuffle
@top_card = -1
@deck = @deck.sort_by {rand}
end

def suit
@@Suits[@top_card/13]
end

def face
factor = @top_card/13
index = @top_card - 13*factor
@@Cards[index]
end

def set_card(card)
@top_card=card
end

end

--
Posted via http://www.ruby-....

8 Answers

Joseph Seaton

4/23/2007 10:01:00 PM

0

Nice work! I'm an utter newbie (probably more of one than you) but
since you asked for comments...

Peter Marsh wrote:
> Hi, I'm an utter newbie to Ruby (and OOP!) and I thought I'd share my
> very first project. It's nothing special - just a simple class that
> simulates a deck of cards, but I'd like to get your comments to see if
> there's anything I can do better (enjoy!):
>
> class Deck
> @@Cards =
> ['Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King','Ace']
> @@Suits = ['Spades','Hearts','Diamonds','Clubs']
>
> def initialize
> @top_card = -1
> @deck = []
> 52.times do |card|
> @deck << card
> end
>
@deck = (0..52).to_a
> end
>
> def draw
> @top_card = @top_card + 1
>
@top_card += 1
> if @top_card < 52
> @deck[@top_card]
> else
> raise 'There are only 52 cards in a deck!'
> end
> end
>
> def shuffle
> @top_card = -1
> @deck = @deck.sort_by {rand}
> end
>
Nice trick there by the way, I'll have to remember that one
> def suit
> @@Suits[@top_card/13]
> end
>
> def face
> factor = @top_card/13
> index = @top_card - 13*factor
> @@Cards[index]
> end
>
> def set_card(card)
> @top_card=card
> end
>
>
attr_writer :top_card would be simpler
> end
>
>
I look forward to reading your code when you nolonger consider yourself
a ruby newbie

Joe

Robert Dober

4/24/2007 8:15:00 AM

0

On 4/23/07, Peter Marsh <evil_grunger@hotmail.com> wrote:
> Hi, I'm an utter newbie to Ruby (and OOP!) and I thought I'd share my
> very first project. It's nothing special - just a simple class that
> simulates a deck of cards, but I'd like to get your comments to see if
> there's anything I can do better (enjoy!):
This is indeed not a bad attempt at all, however ;)
>
> class Deck
> @@Cards =
> ['Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King','Ace']
> @@Suits = ['Spades','Hearts','Diamonds','Club']
Personally I dislike class variables (I prefer class instance
variables even if the make the code more clumpsy (clumpsier?)) but
here it seems to me that constants would be in order, the name of the
cards and suits are constant in the domain after all.

Cards = %w{ Deuce Three Four Five ...
Suits = %w{ Spades Hearts Diamonds Clubs }
>
> def initialize
> @top_card = -1
> @deck = []
> 52.times do |card|
> @deck << card
> end
I will play my personal Ace of Trumps here
@deck = [*0..51]
> end
>
> def draw
> @top_card = @top_card + 1
@top_card += 1
> if @top_card < 52
> @deck[@top_card]
> else
> raise 'There are only 52 cards in a deck!'
> end
@deck[@top_card] or raise "There are only 42 cards in the deck ;)"

> end
>
> def shuffle
> @top_card = -1
> @deck = @deck.sort_by {rand}
> end
>
> def suit
> @@Suits[@top_card/13]
> end
>
> def face
> factor = @top_card/13
> index = @top_card - 13*factor
> @@Cards[index]
replace the three by
Cards[ @top_card % 13 ]
> end

The above two methods seem wrong to me, is it not
@deck[@top_card]
that you want?
>
> def set_card(card)
> @top_card=card
> end
No idea what that should do? If it were not for this method I would
get rid of @top_card at all in your code and write it as follows

def initialize; shuffle end
def shuffle; @deck = [*0..51].sort_by{ rand } end
def draw; @deck.shift or raise "Error only 42 cards" end
def face; Cards[@deck.first % 13] end
def suit; Suits[@deck.first / 13] end


HTH
Robert

--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

Jesús Gabriel y Galán

4/24/2007 8:47:00 AM

0

On 4/23/07, Peter Marsh <evil_grunger@hotmail.com> wrote:
> Hi, I'm an utter newbie to Ruby (and OOP!) and I thought I'd share my
> very first project. It's nothing special - just a simple class that
> simulates a deck of cards, but I'd like to get your comments to see if
> there's anything I can do better (enjoy!):

Others have commented your code, so I'll just share a Deck class I
made for some little things. It may give you some ideas or maybe
someone else will comment on it. It can contain any object, not just
normal cards. Also I want to implement some shuffle methods that
resembled a human shuffle (with it's fuzziness) apart from the actual
random sorting, but never got to do it, I just implemented a fuzzy cut
in half. Here it is:

require 'emptydeckerror'



class Deck



def initialize

@deck = []

end



def << (item)

@deck << item

self

end



def draw

item = @deck.shift

raise EmptyDeckError, "The deck is empty" if !item

item

end



def cut!(fuzzy = false)

cutpoint = @deck.size / 2 - 1

cutpoint = fuzzy(cutpoint) if fuzzy

half = @deck.slice!(0..cutpoint)

(@deck << half).flatten!

self

end



def randomize!

@deck = @deck.sort_by {rand}

self

end



def to_s

@deck.to_s

end



def empty?

@deck.size == 0

end



protected

def fuzzy(number)

# Deviation: 10% of the deck size (min 1)

deviation = @deck.size / 20

deviation = 1 if deviation == 0

randmax = deviation * 2 + 1

number + rand(randmax) - deviation

end

end

Jesus.

Peter Marsh

4/24/2007 3:29:00 PM

0

@Everyone

Thanks for the positive feedback/ideas :D
Robert Dober wrote:
> On 4/23/07, Peter Marsh <evil_grunger@hotmail.com> wrote:
>> Hi, I'm an utter newbie to Ruby (and OOP!) and I thought I'd share my
>> very first project. It's nothing special - just a simple class that
>> simulates a deck of cards, but I'd like to get your comments to see if
>> there's anything I can do better (enjoy!):
> This is indeed not a bad attempt at all, however ;)
>
> ...
>
> HTH
> Robert

There are a lot of things in your post that're really great and have
helped develop my (still limited) knowledge of Ruby.

I don't quite understand this, however:

> Cards = %w{ Deuce Three Four Five ...
> Suits = %w{ Spades Hearts Diamonds Clubs }

From what I've been able to work out it converts everything between {}
into a string and then sticks that all in an array that Cards or Suits
points to. Is this correct?

Also

> @deck[@top_card] or raise "There are only 42 cards in the deck ;)"

I understand what this means, but I'm unsure how to integrate this into
my code.

Thanks for your help!

P.S. I implimented the whole '@top_card' system so that deck[] would not
have to be refilled with numbers each time it was shuffled - I had
worries about speed but perhaps in this case they were a bit to extreme.

--
Posted via http://www.ruby-....

Gavin Kistner

4/24/2007 6:35:00 PM

0

Peter Marsh wrote:
> I don't quite understand this, however:
>
>> Cards = %w{ Deuce Three Four Five ...
>> Suits = %w{ Spades Hearts Diamonds Clubs }
>
> From what I've been able to work out it converts everything between {}
> into a string and then sticks that all in an array that Cards or Suits
> points to. Is this correct?

http://phrogz.net/ProgrammingRuby/language.h...

--
Posted via http://www.ruby-....

Gavin Kistner

4/24/2007 6:36:00 PM

0

Gavin Kistner wrote:
> Peter Marsh wrote:
>> I don't quite understand this, however:
>>
>>> Cards = %w{ Deuce Three Four Five ...
>>> Suits = %w{ Spades Hearts Diamonds Clubs }
>>
>> From what I've been able to work out it converts everything between {}
>> into a string and then sticks that all in an array that Cards or Suits
>> points to. Is this correct?
>
> http://phrogz.net/ProgrammingRuby/language.h...
...which references:
http://phrogz.net/ProgrammingRuby/language.html#generaldeli...

--
Posted via http://www.ruby-....

Robert Dober

4/24/2007 9:14:00 PM

0

On 4/24/07, Peter Marsh <evil_grunger@hotmail.com> wrote:
> @Everyone
<snip>
> Also
>
> > @deck[@top_card] or raise "There are only 42 cards in the deck ;)"
>
> I understand what this means, but I'm unsure how to integrate this into
> my code.
If I recall correctly your code was something like

if @top_card < 52 then
@deck[@top_card]
else
raise ...
end

if @top_card >=52 @deck[@top_card] evaluates to nil, as cards in the
deck are never false or nil the RHS part of the expression

@deck[@top_card] or raise ...

will be executed iff @top_card >=52.
Otherwise the LHS of the expression will be returned, exactly what you wanted.

This is very concise code, maybe even bad for readability, but worth
learning I guess.

Cheers
Robert

--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

David Chelimsky

4/25/2007 10:47:00 AM

0

On 4/23/07, Ken Mitchell <kmitchell@farmerswireless.com> wrote:
> As a newcomer, you are in a perfect position to learn how to properly
> document your work. Not only "proper" in your eyes, but it is so easy
> to make it compatible with rdoc. For instance:
>
> ##
> # Has properties resembling that of a deck of cards
> #
> Class Deck
>
> ##
> # Constructs and returns an instance of Deck
> #
> def initialize
> .......
> end
>
> ##
> # Does some action to an instance of Deck. Argument foo must be
> of type string.....
> #
> def bar(foo=nil)
> ........
> end
>
> end
>
> Running this through rdoc will quickly create some helpful results,
> especially as your code grows and you begin to reuse as much as
> possible.

Peter - Agile thinking has some interesting ideas about comments that
you should read up on as well before you dive in and comment every
little thing in your code. Essentially, comments are an additional
maintenance burden (you have to change them when you change your
code), and they become a liability if they stray from reality (which
they often do). While there are definitely times when comments are
useful, there are also times when they add very little or no value, in
which case you should prefer well named classes and methods that tell
their own story.

You can find a plethora of varying opinions about this if you google
"code smell comments".

Cheers,
David