diff --git a/blackjack.rb b/blackjack.rb index b6dcda9..79bf291 100644 --- a/blackjack.rb +++ b/blackjack.rb @@ -14,9 +14,13 @@ def value end def to_s - "#{@value}-#{suit}" + "#{@value}#{suit.to_s.chr.capitalize}" end + # def inspect + # "#{@value}#{suit.to_s.chr.capitalize}" + # end + end @@ -47,6 +51,7 @@ class Hand def initialize @cards = [] end + def hit!(deck) @cards << deck.cards.shift end @@ -55,16 +60,16 @@ def value cards.inject(0) {|sum, card| sum += card.value } end - def play_as_dealer(deck) - if value < 16 + def play_as_dealer(deck,player_value) + if value < 16 || value < player_value hit!(deck) - play_as_dealer(deck) + play_as_dealer(deck,player_value) end end end class Game - attr_reader :player_hand, :dealer_hand + attr_reader :player_hand, :dealer_hand, :deck def initialize @deck = Deck.new @player_hand = Hand.new @@ -73,13 +78,28 @@ def initialize 2.times { @dealer_hand.hit!(@deck) } end + def show(hand,all) + str_cards = "" + if all == true + hand.cards.each { |card| str_cards += "#{card.to_s} " } + else + str_cards += "XX #{hand.cards[1].to_s}" + end + str_cards + end + def hit @player_hand.hit!(@deck) + @player_hand.value > 21 ? stand : "Player: #{show(@player_hand,true)} value: #{@player_hand.value}" end def stand - @dealer_hand.play_as_dealer(@deck) - @winner = determine_winner(@player_hand.value, @dealer_hand.value) + if @player_hand.value > 21 + @winner = determine_winner(@player_hand.value, @dealer_hand.value) + else + @dealer_hand.play_as_dealer(@deck,@player_hand.value) + @winner = determine_winner(@player_hand.value, @dealer_hand.value) + end end def status @@ -91,19 +111,19 @@ def status end def determine_winner(player_value, dealer_value) - return :dealer if player_value > 21 - return :player if dealer_value > 21 + return "Dealer Won! Player: #{show(@player_hand,true)} value: #{@player_hand.value}, Dealer: #{show(@dealer_hand,true)} value: #{@dealer_hand.value}" if player_value > 21 + return "Player Won! Player: #{show(@player_hand,true)} value: #{@player_hand.value}, Dealer: #{show(@dealer_hand,true)} value: #{@dealer_hand.value}" if dealer_value > 21 if player_value == dealer_value - :push + "Push Player: #{show(@player_hand,true)} value: #{@player_hand.value}, Dealer: #{show(@dealer_hand,true)} value: #{@dealer_hand.value}" elsif player_value > dealer_value - :player + "Player Won! Player: #{show(@player_hand,true)} value: #{@player_hand.value}, Dealer: #{show(@dealer_hand,true)} value: #{@dealer_hand.value}" else - :dealer + "Dealer Won! Player: #{show(@player_hand,true)} value: #{@player_hand.value}, Dealer: #{show(@dealer_hand,true)} value: #{@dealer_hand.value}" end end def inspect - status + "Player: #{show(@player_hand,true)} value: #{@player_hand.value}, Dealer: #{show(@dealer_hand,false)} value: #{@dealer_hand.cards[1].value}" end end @@ -135,7 +155,7 @@ def inspect it "should be formatted nicely" do card = Card.new(:diamonds, "A") - card.to_s.should eq("A-diamonds") + card.to_s.should eq("AD") end end @@ -156,7 +176,7 @@ def inspect describe Hand do it "should calculate the value correctly" do - deck = mock(:deck, :cards => [Card.new(:clubs, 4), Card.new(:diamonds, 10)]) + deck = double(:deck, :cards => [Card.new(:clubs, 4), Card.new(:diamonds, 10)]) hand = Hand.new 2.times { hand.hit!(deck) } hand.value.should eq(14) @@ -167,7 +187,7 @@ def inspect diamond7 = Card.new(:diamonds, 7) clubK = Card.new(:clubs, "K") - deck = mock(:deck, :cards => [club4, diamond7, clubK]) + deck = double(:deck, :cards => [club4, diamond7, clubK]) hand = Hand.new 2.times { hand.hit!(deck) } hand.cards.should eq([club4, diamond7]) @@ -175,29 +195,45 @@ def inspect end describe "#play_as_dealer" do - it "should hit blow 16" do - deck = mock(:deck, :cards => [Card.new(:clubs, 4), Card.new(:diamonds, 4), Card.new(:clubs, 2), Card.new(:hearts, 6)]) + it "should hit below 16" do + deck = double(:deck, :cards => [Card.new(:clubs, 4), Card.new(:diamonds, 4), Card.new(:clubs, 2), Card.new(:hearts, 6)]) hand = Hand.new + player_value = 16 2.times { hand.hit!(deck) } - hand.play_as_dealer(deck) + hand.play_as_dealer(deck,player_value) hand.value.should eq(16) end - it "should not hit above" do - deck = mock(:deck, :cards => [Card.new(:clubs, 8), Card.new(:diamonds, 9)]) + it "should not hit above player value" do + deck = double(:deck, :cards => [Card.new(:clubs, 8), + Card.new(:diamonds, 9), + Card.new(:hearts, 2)]) hand = Hand.new + player_value = 17 2.times { hand.hit!(deck) } - hand.play_as_dealer(deck) + hand.play_as_dealer(deck,player_value) hand.value.should eq(17) end it "should stop on 21" do - deck = mock(:deck, :cards => [Card.new(:clubs, 4), + deck = double(:deck, :cards => [Card.new(:clubs, 4), Card.new(:diamonds, 7), Card.new(:clubs, "K")]) hand = Hand.new 2.times { hand.hit!(deck) } - hand.play_as_dealer(deck) + player_value = 20 + hand.play_as_dealer(deck,player_value) hand.value.should eq(21) end + it "should hit below player value" do + deck = double(:deck, :cards => [Card.new(:clubs, 8), + Card.new(:diamonds, 8), + Card.new(:spades, 2), + Card.new(:hearts, 4)]) + hand = Hand.new + player_value = 17 + 2.times { hand.hit!(deck) } + hand.play_as_dealer(deck,player_value) + hand.value.should eq(18) + end end end @@ -225,18 +261,69 @@ def inspect game.status[:winner].should_not be_nil end + it "should stand if player value is greater than 21" do + game = Game.new + next_player_value = game.player_hand.value + game.deck.cards[0].value + while next_player_value <=21 + game.hit + next_player_value = game.player_hand.value + game.deck.cards[0].value + end + expect(game.hit[0...6]).to eq("Dealer") + end + + describe "#show" do + + it "should show the players hand" do + game = Game.new + player_cards = game.player_hand.cards + str_cards = "" + player_cards.each {|card| str_cards += "#{card.to_s} " } + expect(game.show(game.player_hand,true)).to eq(str_cards) + end + + it "should show the dealers first card until stand" do + game = Game.new + dealer_cards = game.dealer_hand.cards + expect(game.show(game.dealer_hand,false)).to eq("XX #{dealer_cards[1].to_s}") + end + + it "should show the players cards and dealers cards on stand" do + game = Game.new + result = game.stand + if game.dealer_hand.value > 21 + expect(result).to eq("Player Won! Player: #{game.show(game.player_hand,true)} value: #{game.player_hand.value}, Dealer: #{game.show(game.dealer_hand,true)} value: #{game.dealer_hand.value}") + elsif game.player_hand.value > game.dealer_hand.value + expect(result).to eq("Player Won! Player: #{game.show(game.player_hand,true)} value: #{game.player_hand.value}, Dealer: #{game.show(game.dealer_hand,true)} value: #{game.dealer_hand.value}") + elsif game.player_hand.value == game.dealer_hand.value + expect(result).to eq("Push Player: #{game.show(game.player_hand,true)} value: #{game.player_hand.value}, Dealer: #{game.show(game.dealer_hand,true)} value: #{game.dealer_hand.value}") + else + expect(result).to eq("Dealer Won! Player: #{game.show(game.player_hand,true)} value: #{game.player_hand.value}, Dealer: #{game.show(game.dealer_hand,true)} value: #{game.dealer_hand.value}") + end + end + + it "should show the players cards on hit" do + game = Game.new + result = game.hit + if game.player_hand.value > 21 + expect(result).to eq("Dealer Won! Player: #{game.show(game.player_hand,true)} value: #{game.player_hand.value}, Dealer: #{game.show(game.dealer_hand,true)} value: #{game.dealer_hand.value}") + else + expect(result).to eq("Player: #{game.show(game.player_hand,true)} value: #{game.player_hand.value}") + end + end + end + describe "#determine_winner" do it "should have dealer win when player busts" do - Game.new.determine_winner(22, 15).should eq(:dealer) + Game.new.determine_winner(22, 15)[0...6].should eq("Dealer") end it "should player win if dealer busts" do - Game.new.determine_winner(18, 22).should eq(:player) + Game.new.determine_winner(18, 22)[0...6].should eq("Player") end it "should have player win if player > dealer" do - Game.new.determine_winner(18, 16).should eq(:player) + Game.new.determine_winner(18, 16)[0...6].should eq("Player") end it "should have push if tie" do - Game.new.determine_winner(16, 16).should eq(:push) + Game.new.determine_winner(16, 16)[0...4].should eq("Push") end end end