HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyMinor

Simple Blackjack program

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
simpleprogramblackjack

Problem

I created this Blackjack program as a first attempt at Ruby. Would appreciate a code review to see if I am doing things the Ruby way (is there a better way to get user input?), using OOP correctly and anything else you want to point out.

```
class Card

def initialize(suit, face_value)
@suit = suit
@face_value = face_value
end

def get_value
card_value = [@suit, @face_value]
end
end

class Deck

def initialize(number_of_decks = 1)
@deck = create_deck(number_of_decks)
end

def draw(number_of_cards = 1)
drawn_cards = []
number_of_cards.times do
drawn_cards 0
@bet += amount
@funds -= amount
break
elsif amount > @funds
puts "Sadly, you don't have enough funds to place this bet. Please enter a lower bet."
else
puts "You cannot place a zero or negative bet."
end
rescue
puts "Please enter a valid whole amount."
end
end
end

def update_funds(amount)
@funds += amount
end

def calculate_score
@score = 0
ace_in_hand = false

@hand.each do |h|
face_value = h.get_value[1]
if face_value.is_a? Integer
@score += face_value
elsif face_value != :Ace
@score += FACEVALUE
else
# Its an ace so could be 11 or 1?! However, only one ace could be counted as 11 (as 11 + 11 = 22 and would lose). Record if there is an ace in the hand and add one to the score.
@score += 1
ace_in_hand = true
end
end

if ace_in_hand
if @score + FACEVALUE BLACKJACK && player.score > BLACKJACK
puts "\nNo one wins!\n"
elsif player.score BLACKJACK
puts "\nDealer wins\n"
elsif dealer.score BLACKJACK
puts "\n**Player wins!**\n"
#

Solution

First suggestion:

attr_reader :score, :funds, :bet, :hand


Second, you don't need those semicolons. If you don't need something, in Ruby usually it's considered good style to avoid it.

def reset
    @hand = []
    @score = 0
    @bet = 0
  end


Your Card class uses really awkward way to access it's members. You return an array holding the data - but your object already hold all this data. What's the point? Just make those readable, and pass the Card object around. While we at this class, it could also have methods to check if it's a face or a pip. This would make code using it neater, by hiding face_value.is_a? Integer where it belongs. Finally, adding value method to it, would really simplify score calculating code:

class Card
  attr_reader :suit, :face_value

  def initialize(suit, face)
    @suit, @face_value = suit, face_value
  end

  def pip?
    face_value.is_a? Integer
  end
  # def face? 
  # def ace?
  def value
    return 1 if ace?
    face? ? FACE_VALUE : face_value
  end
end

# ...

@score = @hand.map(&:value).inject(&:+)

if @hand.any?(&:ace?) && @score + FACEVALUE <= BLACKJACK
  @score += FACEVALUE
end


It iterates over @hand twice, but readability seems well worth it, and hands probably aren't too big arrays.

if @score + FACEVALUE <= BLACKJACK then @score += FACEVALUE end


Never use than. Either use ?:, or indent.

Code Snippets

attr_reader :score, :funds, :bet, :hand
def reset
    @hand = []
    @score = 0
    @bet = 0
  end
class Card
  attr_reader :suit, :face_value

  def initialize(suit, face)
    @suit, @face_value = suit, face_value
  end

  def pip?
    face_value.is_a? Integer
  end
  # def face? 
  # def ace?
  def value
    return 1 if ace?
    face? ? FACE_VALUE : face_value
  end
end

# ...

@score = @hand.map(&:value).inject(&:+)

if @hand.any?(&:ace?) && @score + FACEVALUE <= BLACKJACK
  @score += FACEVALUE
end
if @score + FACEVALUE <= BLACKJACK then @score += FACEVALUE end

Context

StackExchange Code Review Q#141658, answer score: 2

Revisions (0)

No revisions yet.