Forum: Ruby Cards Class

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
F62d0be4e8209c45a02d4f595014845a?d=identicon&s=25 Peter Marsh (killswitch)
on 2007-04-23 23:16
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
71b69c059cf0476d53df0593cc9ba471?d=identicon&s=25 Joseph Seaton (Guest)
on 2007-04-24 00:02
(Received via mailing list)
Nice work!  I'm an utter newbie (probably more of one than you) but
since you asked for comments...

Peter Marsh wrote:
>   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
>   end
>
Nice trick there by the way, I'll have to remember that one
>   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
5d042621c7c90a43d2776db19eca2023?d=identicon&s=25 Ken Mitchell (kennyd)
on 2007-04-24 00:03
(Received via mailing list)
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.





On Tue, 2007-04-24 at 06:16 +0900, Peter Marsh wrote:

>   def  initialize
>       @deck[@top_card]
>   def suit
>     @top_card=card
>   end
>
> end
>

--

Thanks,

Ken Mitchell
Wireless Operations Engineer
Farmers Wireless

CONFIDENTIALITY NOTICE: This e-mail and any attachment to it may contain
confidential and legally privileged information. This information is
intended only for the recipient named above. If you are not the intended
recipient, take notice that any disclosure, copying, distribution or
taking of any action based upon this information is prohibited by law.
If you have received this e-mail in error, please return it to the
sender and delete this copy from your system. Thank you.
8dbdbce510486cd57d20f8aadd727528?d=identicon&s=25 Stephen Duncan (Guest)
on 2007-04-24 00:15
(Received via mailing list)
Here's my attempt if you want to compare:
http://jrduncans.googlecode.com/svn/trunk/highcard... (part
of my
implementation of a draw-the-high-card game in several languages as I
was
learning: http://jrduncans.googlecode.com/svn/trunk/highcard/)

-Stephen
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-04-24 10:17
(Received via mailing list)
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 ;)"

>
>   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
E088bb5c80fd3c4fd02c2020cdacbaf0?d=identicon&s=25 Jesús Gabriel y Galán (Guest)
on 2007-04-24 10:46
(Received via mailing list)
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.
F62d0be4e8209c45a02d4f595014845a?d=identicon&s=25 Peter Marsh (killswitch)
on 2007-04-24 17:29
@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.
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-04-24 20:34
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.html#arrays
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-04-24 20:36
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.html#arrays
...which references:
http://phrogz.net/ProgrammingRuby/language.html#ge...
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-04-24 23:14
(Received via mailing list)
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
5d38ab152e1e3e219512a9859fcd93af?d=identicon&s=25 David Chelimsky (Guest)
on 2007-04-25 12:47
(Received via mailing list)
On 4/23/07, Ken Mitchell <kmitchell@farmerswireless.com> wrote:
>     #    Constructs and returns an instance of Deck
>         ........
>     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
This topic is locked and can not be replied to.