Tag Archives: Breakable Toys

My Rails Learning Journey – “Breakable Toy” #1 – Blackjack – 24 Dec 2013

Last week at the local Ruby on Rails meetup – RoRo Sydney – Harry Curotta (@hiharryhere) gave a talk called "Rollercoaster on Rails: 1 year post career change". It was a great talk to hear for a person with hopes to cross the chasm from beginner to capable Rubyist . To hear that someone else has made it and how long it took them.

Harry talked about the idea of making some "breakable toys", some throw-away code that only really exists for the purpose of learning and experimentation. I had already had the same idea 2 weeks before but the term "breakable toys" sums the idea up perfectly and I am stealing it. Thanks Harry.

So it was Christmas eve and I have some time off work to sit down and code!! I woke up half dreaming / half daydreaming about writing a Blackjack program. A perfect breakable toy to help me learn. At the start of 2013 I took a Java course (that I really struggled with) and the main project was to write a BlackJack program. So there was the benefit of haviong talked through a similar object model to the one I will need but also I never really grasped the concepts of classes and object orientation. I understood the idea but I couldn't apply it.

I lay there thinking through the problem for what felt like a couple of hours until I was literally aching to get out of bed and code it. I think I am hooked on this stuff. It makes me feel so great to be so into programming because it might be the hardest thing I have ever attempted and I feel like, through perserverance, I am finally starting to crack it!

I decided to start with the first object. Simple. What do I need? I need a deck of cards. I quickly realised that it would be far simpler to switch my thinking from Rails to Ruby (which may not be true to an experienced programmer but I wanted to focus on the logic) and ignore the web framework for now. Just get the logic working. So I spent the day with Sublime Text 2 and BASH building the beginnings of my BlackJack app.

The first cut was quite procedural, not at all object oriented.

rank = Array(1..13)
suits = ["Hearts", "Diamonds", "Spades", "Clubs"]
deck = Array.new(52)
counter = 0

suits.each do |s|
  rank.each do |n|
    if n == 1
      cardname = "Ace"
      cardvalue = 11
    elsif n == 11
      cardname = "Jack"
      cardvalue = 10
    elsif n == 12
      cardname = "Queen"
      cardvalue = 10
    elsif n == 13
      cardname = "King"
      cardvalue = 10
    else
      cardname = n.to_s
      cardvalue = n
    end  
    deck[counter] = {:rank => (n.to_s), :suit => s, :cardname => cardname, :cardvalue => cardvalue}     
    counter +=1
  end
end
deck.shuffle!

So I decided to try and build some classes and make it a bit more "OO". I set it up for a future with multiple decks and added the ability to deal a hand and take additional cards. All of a sudden it is 1am on Christmas day and time to go to bed. On another date I might have stayed up all night. (Note: There is a commented out easier way to build the deck but I was playing around so I've left in an alternative that I think allows for changes in the number of ranks if I was using a different style of playing cards or in a different game altogether.)

DECKSIZE = 52

class Card
  RANKS = %w(2 3 4 5 6 7 8 9 10 J Q K A)
  SUITS = %w(Spade Heart Club Diamond)

  attr_accessor :rank, :suit
  def initialize(id)
    self.rank = RANKS[id % 13]
    #easier way to generate suits
    #self.suit = SUITS[id % 4]
    if id < DECKSIZE / SUITS.length
      self.suit = SUITS[0]
    elsif id < DECKSIZE / SUITS.length*2
      self.suit = SUITS[1]
    elsif id < DECKSIZE / SUITS.length*3
      self.suit = SUITS[2]
    else
      self.suit = SUITS[3]   
    end
  end
end

class Deck
  attr_accessor :cards
  def initialize
    # shuffle array and init each Card
    puts "Creating & Shuffling the Deck"
    self.cards = (0..(DECKSIZE-1)).to_a.shuffle.map { |id| Card.new(id) }
    #unshuffled
    #self.cards = (0..(DECKSIZE-1)).to_a.shuffle.map { |id| Card.new(id) }
  end
end

class Hand
  attr_accessor :cards
  def initialize(deck)
    # start with 2 cards from the deck
    self.cards = (0..1).to_a.map { |id| deck.cards.pop }
  end

  def hand_total
    puts "Hand Total"
    total = 0
    self.cards.each do |c|
      puts "C.RANK is #{c.rank}"
      #puts c.rank.to_i
      if c.rank == "A" 
        total += 11
      elsif c.rank == "J" || c.rank == "Q" || c.rank == "K"
        total += 10 
      else
        total += c.rank.to_i
      end
    end 
    puts "The hand total so far is #{total}"
  end
end

#BEGIN THE GAME ... Create & Shuffle the deck
deck1 = Deck.new
#Deal a starting hand
hand1 = Hand.new(deck1)
#Show the running total
hand1.hand_total
#Take another card
hand1.cards.push(deck1.cards.pop)
hand1.hand_total

There are probably a million ways to make this code better but I went to bed feeling pleased that I had made some progress today.