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 << @deck.pop() end return drawn_cards end def size @deck.size end private def create_deck(number_of_decks) suite = [:Spades, :Clubs, :Hearts, :Diamonds] face_value = (2..10).to_a face_value << :Jack << :Queen << :King << :Ace deck = [] number_of_decks.times do suite.each do |s| face_value.each do |v| card = Card.new(s, v) deck << card end end end deck.shuffle! return deck end end class Player attr_reader :score attr_reader :funds attr_reader :bet attr_reader :hand def initialize @hand = []; @score = 0; @bet = 0; @funds = 1000; end def reset @hand = []; @score = 0; @bet = 0; end def hand(cards) @hand += cards calculate_score end def place_bet amount = 0 while true begin amount = Integer(gets) if amount <= @funds && amount > 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 then @score += FACEVALUE end end end def print_hand hand_as_string = "" @hand.each do |card| card_value = card.get_value hand_as_string += "#{card_value[0]}, #{card_value[1]} | " end return hand_as_string end end def determine_winner(player, dealer) amount = 0 if dealer.score > BLACKJACK && player.score > BLACKJACK puts "\n**No one wins!**\n" elsif player.score < dealer.score && dealer.score <= BLACKJACK || player.score > BLACKJACK puts "\n***Dealer wins***\n" elsif dealer.score < player.score && player.score <= BLACKJACK || dealer.score > BLACKJACK puts "\n****Player wins!****\n" # increase funds to player and check for blackjack if player.score == BLACKJACK && player.hand.size == 2 amount = player.bet + player.bet * 1.5 else amount = player.bet * 2 end else puts "\nIt's a draw!\n" # return funds to player amount = player.bet end player.update_funds(amount) end # define blackjack winning score and value of face card BLACKJACK = 21; FACEVALUE = 10; DEALER_STANDS_AT = 17; puts "Welcome to blackjack!" puts "You currently have $1000 in funds. Blackjack pays 3:2" puts "How many decks should we use? (Integer between 1 and 10)" number_of_decks = -1 while number_of_decks == -1 begin number_of_decks = Integer(gets) if number_of_decks <= 0 || number_of_decks > 10 number_of_decks = -1 puts "The number of decks must be between 1 and 10." end rescue puts "Please enter a valid integer" end end keep_playing = true # Create the players and dealer player = Player.new dealer = Player.new while keep_playing # Create a new deck deck = Deck.new(number_of_decks) # Reset the players and dealers score and hand, and the players bet player.reset dealer.reset # Ask player to place bet puts "How much would you like to bet?" player.place_bet # Deal two cards to each player and one card to the dealer player.hand(deck.draw(2)) dealer.hand(deck.draw) puts "\nYour current hand is: #{player.print_hand} \nYour score is: #{player.score}\n." puts "The dealer's hand is: #{dealer.print_hand}\nThe dealers score is: #{dealer.score}\n" # Deal the dealers second card (that is unknown to the player) dealer.hand(deck.draw) if dealer.score != BLACKJACK # until player is not bust or stands until player.score > BLACKJACK do puts "\nDo you want to hit (h) or stand (s)?" players_move = String(gets) case players_move[0].downcase when "s" # stand break when "h" # hit puts "\nYou decided to hit!\n" player.hand(deck.draw) puts "\nYour hand is #{player.print_hand}\nYour score is: #{player.score}." else puts "Unknow input. Please try again.\n" end end puts "\nYour move has ended, resolving the dealers hand.\n" # Resolve the dealers hand (keep drawing cards until bust or >=17 reached) while dealer.score <= DEALER_STANDS_AT dealer.hand(deck.draw) end puts "\nThe dealer's hand is #{dealer.print_hand} \nThe dealers score is: #{dealer.score}" end # Determine the winner(s) and resolve any ties and settle all the bets determine_winner(player, dealer) puts "At the end of the game your funds stand at $#{player.funds}." # Ask if player wants to play again? while true puts "Do you want to play again? (Y/N)" play_again = String(gets) case play_again[0].downcase when "y" break when "n" keep_playing = false break end end end