Reputation: 21
Is there an easier way of doing this instead of inserting each element into the array manually
stack_of_cards << Card.new("A", "Spades", 1)
stack_of_cards << Card.new("2", "Spades", 2)
stack_of_cards << Card.new("3", "Spades", 3)
stack_of_cards << Card.new("4", "Spades", 4)
stack_of_cards << Card.new("5", "Spades", 5)
stack_of_cards << Card.new("6", "Spades", 6)
stack_of_cards << Card.new("7", "Spades", 7)
stack_of_cards << Card.new("8", "Spades", 8)
stack_of_cards << Card.new("9", "Spades", 9)
stack_of_cards << Card.new("10", "Spades", 10)
stack_of_cards << Card.new("J", "Spades", 11)
stack_of_cards << Card.new("Q", "Spades", 12)
stack_of_cards << Card.new("K", "Spades", 13)
stack_of_cards << Card.new("A", "Hearts", 1)
stack_of_cards << Card.new("2", "Hearts", 2)
stack_of_cards << Card.new("3", "Hearts", 3)
stack_of_cards << Card.new("4", "Hearts", 4)
stack_of_cards << Card.new("5", "Hearts", 5)
stack_of_cards << Card.new("6", "Hearts", 6)
stack_of_cards << Card.new("7", "Hearts", 7)
stack_of_cards << Card.new("8", "Hearts", 8)
stack_of_cards << Card.new("9", "Hearts", 9)
stack_of_cards << Card.new("10", "Hearts", 10)
stack_of_cards << Card.new("J", "Hearts", 11)
stack_of_cards << Card.new("Q", "Hearts", 12)
stack_of_cards << Card.new("K", "Hearts", 13)
stack_of_cards << Card.new("A", "Diamonds", 1)
stack_of_cards << Card.new("2", "Diamonds", 2)
stack_of_cards << Card.new("3", "Diamonds", 3)
stack_of_cards << Card.new("4", "Diamonds", 4)
stack_of_cards << Card.new("5", "Diamonds", 5)
stack_of_cards << Card.new("6", "Diamonds", 6)
stack_of_cards << Card.new("7", "Diamonds", 7)
stack_of_cards << Card.new("8", "Diamonds", 8)
stack_of_cards << Card.new("9", "Diamonds", 9)
stack_of_cards << Card.new("10", "Diamonds", 10)
stack_of_cards << Card.new("J", "Diamonds", 11)
stack_of_cards << Card.new("Q", "Diamonds", 12)
stack_of_cards << Card.new("K", "Diamonds", 13)
stack_of_cards << Card.new("A", "Clubs", 1)
stack_of_cards << Card.new("2", "Clubs", 2)
stack_of_cards << Card.new("3", "Clubs", 3)
stack_of_cards << Card.new("4", "Clubs", 4)
stack_of_cards << Card.new("5", "Clubs", 5)
stack_of_cards << Card.new("6", "Clubs", 6)
stack_of_cards << Card.new("7", "Clubs", 7)
stack_of_cards << Card.new("8", "Clubs", 8)
stack_of_cards << Card.new("9", "Clubs", 9)
stack_of_cards << Card.new("10", "Clubs", 10)
stack_of_cards << Card.new("J", "Clubs", 11)
stack_of_cards << Card.new("Q", "Clubs", 12)
stack_of_cards << Card.new("K", "Clubs", 13)
Upvotes: 2
Views: 6036
Reputation: 383
Here are two ways to make a card deck in Ruby.
...easier, but may be tougher if you need to compare cards against each other (courtesy code project from Tealeaf Academy)
values = ["A", 2, 3, 4, 5, 6, 7, 8, 9, 10, "J", "Q", "K" ]
suits = [ "hearts", "spades", "clubs", "diamonds" ]
deck = values.product(suits)
=> [["A", "hearts"], ["A", "spades"], ["A", "clubs"], ["A", "diamonds"] #etc...
You can also add on .shuffle or .shuffle! to the deck
deck = values.product(suits).shuffle
=> [[9, "diamonds"], [2, "clubs"], [7, "spades"], [4, "clubs"] #etc...
...so you can easily sort or compare cards via "scores" (courtesy @amaseda at General Assembly DC)
def deck_o_cards
values = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
suits = ['hearts', 'diamonds', 'clubs', 'spades']
deck = []
values.each_with_index do |v, i|
suits.each do |s|
deck.push({
score: i,
value: v,
suit: s,
})
end
end
return deck.shuffle
end
=> [{:score=>8, :value=>10, :suit=>"hearts"}, {:score=>4, :value=>6, :suit=>"diamonds"}, #etc...
Upvotes: 0
Reputation: 334
Card = Struct.new(:name, :suit,:number)
stack_of_cards = []
%w{'Spades Hearts Diamonds Clubs'}.each do |suit|
%w{'A 2 3 4 5 6 7 8 9 10 J Q K'}.each_with_index do |name, i|
stack_of_cards << Card.new(name, suit, i+1)
end
end
p stack_of_cards
Upvotes: 0
Reputation: 14125
David A. Black's The Well Grounded Rubyist uses deck initialization as a way to demonstrate the cycle
method. I think the resulting code is clever, and very simple:
class Card
SUITS = %w{ clubs diamonds hearts spades }
RANKS=%w{2345678910JQKA}
class Deck
attr_reader :cards
def initialize(n=1)
@cards = [] SUITS.cycle(n) do |s|
RANKS.cycle(1) do |r| @cards << "#{r} of #{s}"
end
end
end
end
end
Also, the Ruby Quiz #1: The Solitaire Cipher involved using a deck of cards to encode a message. Check out the solutions. You'll see a few different ways used to tackle this problem.
Upvotes: 0
Reputation: 369536
First off: why do you represent the rank and the value of a card separately? Is there ever an instance where, say, a Jack does not have the value 11? For example, why do you have
Card.new("7", "Spades", 7)
instead of just
Card.new(7, "Spades")
and is there ever an instance where you would have
Card.new("7", "Spades", 42)
If not, then those two should be packaged together into an object.
Also, why are the suits represented as strings and not as Suit
s or at least as symbols?
I'd probably do something like this:
Rank = Struct.new(:rank, :value) do
def to_s; rank end
alias_method :inspect, :to_s
end
Card = Struct.new(:rank, :suit) do
def to_s; "#{rank} of #{suit.capitalize}" end
alias_method :inspect, :to_s
end
ranks = %w[Ace 2 3 4 5 6 7 8 9 10 Jack Queen King].map.with_index {|rank, value|
Rank.new(rank, value + 1)
}
suits = [:spades, :hearts, :diamonds, :clubs]
deck = suits.product(ranks).map {|suit, rank| Card.new(rank, suit) }
Upvotes: 1
Reputation: 24010
Building on Mark Rushakoff solution and using Ruby 1.9
Card = Struct.new(:rank, :suit,:rank_id)
ranks = %w{A 2 3 4 5 6 7 8 9 10 J Q K}
suits = %w{Spades Hearts Diamonds Clubs}
stack_of_cards = suits.each_with_object([]) do |suit,res|
ranks.size.times do |i|
res << Card.new(ranks[i], suit,i + 1)
end
end
puts stack_of_cards.inspect
Upvotes: 0
Reputation: 258358
Just loop over both ranks and suits.
ranks = %w{A 2 3 4 5 6 7 8 9 10 J Q K}
suits = %w{Spades Hearts Diamonds Clubs}
suits.each do |suit|
ranks.size.times do |i|
stack_of_cards << Card.new( ranks[i], suit, i+1 )
end
end
Upvotes: 6
Reputation: 370357
Yes, there is: Create an array of faces and an array of suits then iterate over them in a nested loop. Also change the Card
class so that you don't need to specify the face as a string an integer as that is redundant. It's most convenient if you only need to specify the int parameter.
This way the code would look like this:
faces = 1..13
suits = %w(Spades Hearts Diamonds Clubs)
cards = suits.flat_map do |suit|
faces.map |face_int_value|
Card.new(suit, face_int_value)
end
end
Or in ruby before 1.9.2:
faces = 1..13
suits = %w(Spades Hearts Diamonds Clubs)
cards = suits.map do |suit|
faces.map |face_int_value|
Card.new(suit, face_int_value)
end
end.flatten
Upvotes: 2