Variables, Arrays and Hashes

I’m trying to make a card game with Ruby. I created a hash of cards and
numeric values which works fine on its own:
example:
deck = Hash.new
deck[“Ah”] = 1
deck[“1h”] = 1
deck[“2h”] = 2
deck[“3h”] = 3
deck[“4h”] = 4
deck[“5h”] = 5
where:
puts deck[“3h”]
properly returns 3.

I wrote some code to output the hash into an array and then shuffle it
which also works. I have code to deal out the cards into new arrays for
each player which works as well. My issue is when I try to call things
like:

 puts player1.first

it will give the appropriate first card in the hand but:

 puts deck[player1.first]

does not return the value of the card. I’ve also tried created place
holder variables without avail:

 x = player1.first
 puts x

gives the proper output of the card in hand but:

 puts deck[x]

comes up a blank line.
Any thoughts?

On Thu, Sep 29, 2011 at 8:40 PM, Rob V. [email protected] wrote:

where:

Any thoughts?
Can you show a complete example in which we can see the error?
Things to check:

  • Are you sure you are putting the keys of the hash in the arrays?
  • What does puts player1.first outputs: “Ah” or 1?

Jesus.

Jesus.

“Jesús Gabriel y Galán” [email protected] wrote in post
#1024250:

On Thu, Sep 29, 2011 at 8:40 PM, Rob V. [email protected] wrote:

where:

Any thoughts?
Can you show a complete example in which we can see the error?
Things to check:

  • Are you sure you are putting the keys of the hash in the arrays?
  • What does puts player1.first outputs: “Ah” or 1?

Jesus.

Jesus.

I gave you an example where it doesn’t work.

“puts deck[player1.first]
does not return the value of the card. I’ve also tried created place
holder variables without avail:”

and I have above that:

" puts player1.first
it will give the appropriate first card in the hand but:"

card in hand meaning the “Ah”.
More specifically
print player1.first
outputs [“ah”] and
puts player1.first
outputs Ah

The [“ah”] was a typo, it was supposed to be [“Ah”] I attached the file.

On Thu, Sep 29, 2011 at 8:54 PM, Rob V. [email protected] wrote:

and I have above that:

" puts player1.first
it will give the appropriate first card in the hand but:"

card in hand meaning the “Ah”.
More specifically
print player1.first
outputs [“ah”] and
puts player1.first
outputs Ah

Sorry, I meant a complete example that we can execute, that fails. We
need to see how you assign cards to player1. From your description I
cannot give any more advice. If print player1.first outputs [“ah”]
including the brackets, I can’t see how puts player1.first would
output only Ah, with the capital A and no brackets or quotes, so I
don’t really understand what you are saying.
It could be that what you have in player1 is a nested array, something
like:

player1 = [[“Ah”]]

but I can’t be sure with your description. So, can you post a
complete, executable snippet of code that we can check?

Jesus.

On Thu, Sep 29, 2011 at 9:53 PM, Rob V. [email protected] wrote:

The [“ah”] was a typo, it was supposed to be [“Ah”] I attached the file.

Attachments:
http://www.ruby-forum.com/attachment/6639/deal.rb

OK, got it. If you add these lines:

p player1
p player1.first

after the 2.times loop, you will see that they print this (p is
outputting the inspect method, it’s like puts player1.inspect):

[[“7d”], [“10c”]]
[“7d”]

So, as I guessed, player1 is a nested array. player1.first is an
array, not the string. The reason is that the take method returns an
array:

irb(main):006:0> a = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):007:0> a.take(1)
=> [1]
irb(main):008:0> b = []
=> []
irb(main):009:0> b.push(a.take(1))
=> [[1]]

You don’t need the nesting. Instead of using take I’d use pop, which
by the way also removes the element (you are doing that with
delete_at):

2.times do
player1.push shuffle.pop
dealer.push shuffle.pop
end

After that change,

p player1
p player1.first
p deck[player1.first]

print:
[“Jh”, “4h”]
“Jh”
10

which is what you want.

Hope this helps,

Jesus.

Another thing you might consider, depending whether your use case
needs something this fancy, is to have a separate Card class that has
constant class arrays (probably of symbols or strings) for Ranks and
Suits (and possibly a Number_Of_Jokers), and instance attributes rank
and suit. That will make it much easier to detect straights, flushes,
straight flushes, n of a kind, etc., and to order cards as needed.
You can then have a Deck class, that iterates over Card.Ranks and
Card.Suits (and possibly Number_Of_Jokers) to fill itself (such as by
populating an array member), which you can then shuffle, deal from,
etc.

The Deck class could just use one standard Card class. However, if
you wanted to build in more flexibility, you could make Card a base
class, maybe even with blank arrays and no jokers. You can inherit
from it to make different Card classes just by changing the Ranks and
Suits arrays and the Number_Of_Jokers. That way you could easily
define Poker_Card, Pinochle_Card, Uno_Card, Tarot_Card, etc., and
thereby make Decks of them without changing Deck at all, preserving
methods like is_empty?, number_of_cards, deal_one_card, shuffle, etc.

This was fresh in my mind from some interview homework. :slight_smile:

-Dave

Thanks. That’s exactly what I needed.