Skip to content

Instantly share code, notes, and snippets.

@W-Mills
Last active August 27, 2018 18:25
Show Gist options
  • Save W-Mills/8e86f9940fbabeff1d3d93fc328bca49 to your computer and use it in GitHub Desktop.
Save W-Mills/8e86f9940fbabeff1d3d93fc328bca49 to your computer and use it in GitHub Desktop.
Version 1.0.0 of text-based card game twenty one written in Ruby
SUITS = %w[C H D S]
SUITS_HASH = { 'C' => 'Clubs',
'H' => 'Hearts',
'D' => 'Diamonds',
'S' => 'Spades' }
DEALER_STOPS_AT = 17
BUST_IF_OVER = 21
def prompt(msg)
puts "==> #{msg}"
end
def init_deck(dck, suit)
dck = %w[Ace 2 3 4 5 6 7 8 9 10 Jack Queen King]
fresh_deck = suit.map do |suits|
dck.map do |value|
[suits, value]
end
end
fresh_deck.flatten(1)
end
def deal_card(dck)
card = dck.sample
dck.delete_if { |element| element == card }
card
end
def hit_or_stay_validation(hand, player, answer)
loop do
show_hand(hand, player)
prompt "Enter 'h' to hit, 's' to stay."
answer = gets.chomp.downcase
break if answer =~ /[sh]/ && answer.length == 1
prompt "INVALID INPUT. Enter 'h' to hit, 's' to stay."
end
answer
end
def hit_or_stay?(hand, deck, player)
answer = ''
loop do
answer = hit_or_stay_validation(hand, player, answer)
system('clear') || system('cls')
hand << deal_card(deck) if answer[0] == 'h'
if answer[0] == 's'
answer = 'stay'
system('clear') || system('cls')
break
elsif busted?(hand)
answer = 'busted'
break
end
end
answer
end
def cmp_hit_or_stay(hand)
vlu = calculate_hand_value(hand)
if busted?(hand)
return 'busted'
elsif vlu < DEALER_STOPS_AT
return 'hit'
else
return 'stay'
end
end
def busted?(hand)
calculate_hand_value(hand) > BUST_IF_OVER
end
def translate_cards(cards)
translated = cards.map { |suit, num| [num, SUITS_HASH[suit]] }
translated = translated.map { |card| "a #{card[0]} of #{card[1]}" }
joinand(translated, ', ')
end
def joinand(arr, delimiter=', ', word='and')
case arr.size
when 0 then ''
when 1 then arr.first
when 2 then arr.join(" #{word} ")
else
arr[-1] = "#{word} #{arr.last}"
arr.join(delimiter)
end
end
def show_hand(hand, player)
puts
if player == 'You'
prompt "#{player} have: #{translate_cards(hand)}."
prompt "(#{calculate_hand_value(hand)})"
elsif player == 'Dealer'
prompt "#{player} has: #{translate_cards(hand)}."
end
puts
end
def calculate_hand_value(hand)
values = hand.map { |card| card[1] }
sum = 0
values.each do |value|
sum += if value == "Ace"
11
elsif value.to_i == 0
10
else
value.to_i
end
end
sum += correct_for_aces(values, sum)
sum
end
def correct_for_aces(values, sum)
correction = 0
values.select { |value| value == "Ace" }.count.times do
correction -= 10 if sum > BUST_IF_OVER
end
correction
end
def tie_game?(player_hand, computer_hand)
return true if busted?(player_hand) && busted?(computer_hand) ||
player_hand == computer_hand
end
def who_wins(player, player_hand, computer, computer_hand)
plyr_value = calculate_hand_value(player_hand)
comp_value = calculate_hand_value(computer_hand)
return "tie game" if tie_game?(player_hand, computer_hand)
if busted?(player_hand)
computer
elsif busted?(computer_hand)
player
elsif plyr_value > comp_value
player
elsif plyr_value < comp_value
computer
end
end
def display_winner(winner)
if winner == 'You'
prompt "#{winner} win the round!"
elsif winner == 'Dealer'
prompt "#{winner} wins the round!"
else
prompt "It was a tie game."
end
end
def press_enter
prompt 'Press enter to continue...'
gets.chomp
system('clear') || system('cls')
end
def display_score(score)
prompt "SCORE:
Player: #{score[:player]}
Dealer: #{score[:dealer]}
"
end
def increment_score(winner, scoreboard)
if winner == 'You'
scoreboard[:player] += 1
elsif winner == 'Dealer'
scoreboard[:dealer] += 1
end
end
def print_staying_hand(player, hand)
if player == 'Dealer'
# rubocop:disable LineLength
prompt "#{player} stays with a hand value of: #{calculate_hand_value(hand)}."
elsif player == 'You'
prompt "#{player} decided to stay with a hand value of: #{calculate_hand_value(hand)}."
# rubocop:enable LineLength
end
puts
press_enter
end
current_deck = []
player_name = 'You'
computer_name = 'Dealer'
score_count = { player: 0, dealer: 0 }
loop do
system('clear') || system('cls')
player_hand = []
computer_hand = []
current_deck = init_deck(current_deck, SUITS)
puts
2.times { player_hand << deal_card(current_deck) }
computer_hand << deal_card(current_deck)
prompt "Dealer hand: #{translate_cards(computer_hand)} and an unknown card."
computer_hand << deal_card(current_deck)
loop do
player_result = hit_or_stay?(player_hand, current_deck, player_name)
case player_result
when 'busted'
show_hand(player_hand, player_name)
prompt 'YOU BUSTED.'
press_enter
break
when 'stay'
print_staying_hand(player_name, player_hand)
break
end
end
loop do
cmp_play = cmp_hit_or_stay(computer_hand)
case cmp_play
when 'hit'
computer_hand << deal_card(current_deck)
when 'stay'
print_staying_hand(computer_name, computer_hand)
break
when 'busted'
prompt "Dealer BUSTED."
press_enter
break
end
end
winner = who_wins(player_name, player_hand, computer_name, computer_hand)
display_winner(winner)
increment_score(winner, score_count)
display_score(score_count)
press_enter
break if score_count.values.include?(5)
end
prompt "#{score_count.key(5).capitalize} is the grand winner!"
prompt "Thank you for playing 21!"
puts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment