patternrubyMinor
Simple Blackjack program
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"
#
```
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:
Second, you don't need those semicolons. If you don't need something, in Ruby usually it's considered good style to avoid it.
Your
It iterates over
Never use
attr_reader :score, :funds, :bet, :handSecond, 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
endYour
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
endIt 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 endNever use
than. Either use ?:, or indent.Code Snippets
attr_reader :score, :funds, :bet, :handdef reset
@hand = []
@score = 0
@bet = 0
endclass 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
endif @score + FACEVALUE <= BLACKJACK then @score += FACEVALUE endContext
StackExchange Code Review Q#141658, answer score: 2
Revisions (0)
No revisions yet.