Created
June 24, 2015 16:17
-
-
Save ambethia/b2e2e1a62b825967271f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'net/http' | |
require 'json' | |
require 'cgi' | |
class Card | |
SUITS = [ | |
"Diamonds", | |
"Hearts", | |
"Clubs", | |
"Spades" | |
] | |
VALUES = { | |
"Ace" => 11, | |
"Two" => 2, | |
"Three" => 3, | |
"Four" => 4, | |
"Five" => 5, | |
"Six" => 6, | |
"Seven" => 7, | |
"Eight" => 8, | |
"Nine" => 9, | |
"Ten" => 10, | |
"Jack" => 10, | |
"Queen" => 10, | |
"King" => 10 | |
} | |
attr :suit | |
attr :value | |
def initialize(value, suit) | |
@value = value | |
@suit = suit | |
end | |
def display_name | |
"#{value} of #{suit}" # => "2 of diamonds" | |
end | |
def points | |
VALUES[@value] | |
end | |
end | |
class Deck | |
attr :cards | |
def initialize(data = []) | |
@cards = [] | |
if data.empty? | |
Card::SUITS.each do |suit| | |
Card::VALUES.keys.each do |value| | |
@cards << Card.new(value, suit) | |
end | |
end | |
shuffle! | |
else | |
data.each do |card| | |
@cards << Card.new(card["value"], card["suit"]) | |
end | |
end | |
end | |
def shuffle! | |
@cards.shuffle! | |
end | |
def draw! | |
@cards.shift | |
end | |
end | |
class BlackjackLocal | |
attr :name | |
def initialize(player_name) | |
@name = player_name | |
@deck = Deck.new | |
@over = false | |
@player = [] | |
@dealer = [] | |
2.times do |variable| | |
@player << @deck.draw! | |
@dealer << @deck.draw! | |
end | |
end | |
def hit! | |
return false if winner | |
@player << @deck.draw! | |
end | |
def stay! | |
return false if winner | |
while dealer_score < 16 | |
@dealer << @deck.draw! | |
end | |
@over = true | |
end | |
def winner | |
if dealer_score > 21 || | |
(player_score > dealer_score && | |
player_score <= 21) && | |
@over | |
return "player" | |
elsif player_score > 21 || | |
(dealer_score == player_score || | |
dealer_score > player_score && | |
dealer_score <= 21) && | |
@over | |
return "dealer" | |
end | |
end | |
def player_score | |
@player.inject(0) { |total, card| total + card.points } | |
end | |
def dealer_score | |
@dealer.inject(0) { |total, card| total + card.points } | |
end | |
def player_hand | |
@player.map(&:display_name) | |
end | |
def dealer_hand | |
@dealer.map(&:display_name) | |
end | |
end | |
class BlackjackRemote | |
API_HOST = 'pure-forest-blackjack.herokuapp.com' | |
attr :name, :winner, :player_hand, :player_score, :dealer_hand, :dealer_score | |
def initialize(player_name) | |
@http = Net::HTTP.new(API_HOST) | |
res = @http.post('/games', "game[name]=#{CGI.escape(player_name)}") | |
set_game parse(res) | |
end | |
def hit! | |
set_game parse(@http.patch("/games/#{@id}/hit", '')) | |
end | |
def stay! | |
set_game parse(@http.patch("/games/#{@id}/stay", '')) | |
end | |
private | |
def set_game(game) | |
# @id = game["id"] | |
# @name = game["name"] | |
# @dealer_hand = game["dealer_hand"] | |
# @dealer_score = game["dealer_score"] | |
# @player_hand = game["player_hand"] | |
# @player_score = game["player_score"] | |
# @winner = game["winner"] | |
game.each do |key, value| | |
instance_variable_set "@#{key}", value | |
end | |
end | |
def parse(response) | |
JSON.parse(response.body) | |
end | |
end | |
class Game | |
def initialize(game_class) | |
print "What's your name, bone daddy? " | |
@blackjack = game_class.new(gets.chomp) | |
puts @blackjack.inspect | |
until @blackjack.winner | |
puts "\n\n------" | |
play | |
end | |
show_hand(true) | |
winner = @blackjack.winner == "player" ? @blackjack.name : "The dealer" | |
puts "#{winner} wins!" | |
end | |
def play | |
show_hand | |
get_player_move | |
end | |
def show_hand(reveal = false) | |
puts "#{@blackjack.name}'s hand contains:" | |
@blackjack.player_hand.each do |card| | |
puts " " + card | |
end | |
puts "#{@blackjack.name}'s hand is worth #{@blackjack.player_score}." | |
puts "\n\n" | |
if reveal | |
puts "The dealer reaveals his hand:" | |
@blackjack.dealer_hand.each do |card| | |
puts " " + card | |
end | |
puts "The dealers's hand is worth #{@blackjack.dealer_score}." | |
else | |
puts "The dealer reaveals one of his #{@blackjack.dealer_hand.count} cards:" | |
puts " " + @blackjack.dealer_hand.first | |
end | |
puts "\n\n" | |
end | |
def get_player_move | |
print "#{@blackjack.name}, do you want to [h]it or [s]tay? " | |
play = gets.chomp | |
case play | |
when /^h/i | |
@blackjack.hit! | |
when /^s/i | |
@blackjack.stay! | |
else | |
puts "Wat?" | |
get_player_move | |
end | |
end | |
end | |
game_class = ["--remote", "-r"].include?(ARGV[0]) ? BlackjackRemote : BlackjackLocal | |
ARGV.clear | |
Game.new(game_class) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There's actually a bug in the winner logic; if the player opens with 21 and the dealer has less than 21, they don't win immediately.