Skip to content

Instantly share code, notes, and snippets.

@chaupt
Last active July 21, 2017 03:32
Show Gist options
  • Save chaupt/3c79c92e9f7bb2bf2f61b1cd0a0f48b9 to your computer and use it in GitHub Desktop.
Save chaupt/3c79c92e9f7bb2bf2f61b1cd0a0f48b9 to your computer and use it in GitHub Desktop.
#
# Ruby For Kids Project 9: Acey Deucy
# Programmed By: Chris Haupt
# A multiplayer card game where you try to guess whether the next
# card will be between two other cards, placing bets on the results
#
require_relative "game"
require_relative "deck"
require_relative "card"
require_relative "player"
STARTING_NUMBER_OF_CHIPS = 10
MINIMUM_PLAYERS = 2
puts "Welcome to Acey Deucy"
print "Enter number of players: "
player_count = gets
player_count = player_count.to_i
if player_count >= MINIMUM_PLAYERS
# Load up some players
players = []
(0...player_count).each do |index|
print "Enter name for player ##{index + 1}: "
name = gets
name = name.chomp
players << Player.new(name, STARTING_NUMBER_OF_CHIPS)
end
# Initialize a new game
game_engine = Game.new(players)
# Let's see the setup game
game_engine.show_player_chips
# Let's play and see who wins
game_engine.play
else
puts "There should be at least #{MINIMUM_PLAYERS}"
end
class Card
SUITS = %w(Clubs Diamonds Hearts Spades)
RANKS = %w(2 3 4 5 6 7 8 9 10 Jack Queen King Ace)
attr_accessor :rank, :suit
def initialize(rank, suit)
@rank = rank
@suit = suit
end
def to_s
"#{rank} of #{suit}"
end
# returns -1 if card1 is less than, 0 if same as,
# and 1 if larger than card2
def self.compare_rank(card1, card2)
RANKS.index(card1.rank) <=> RANKS.index(card2.rank)
end
def self.create_cards
cards = []
SUITS.each do |suit|
RANKS.each do |rank|
cards << Card.new(rank, suit)
end
end
cards
end
end
class Deck
def initialize(cards)
@cards = cards
end
def shuffle
unless @cards.empty?
@cards.shuffle!
end
end
def deal
unless @cards.empty?
@cards.pop
end
end
def size
@cards.length
end
end
class Game
attr_reader :players, :deck, :bank, :round
ANTE_AMOUNT = 1
def initialize(players)
@players = players
@deck = Deck.new(Card.create_cards)
@deck.shuffle
@bank = 0
@round = 0
end
def remaining_players
players.count {|player| !player.eliminated?}
end
def play
while deck.size > (players.length * 3) && remaining_players > 1 do
new_round
puts "-" * 40
puts "Round #{round}! The dealer has #{bank} chips."
puts "-" * 40
puts "Everyone antes"
ante
puts "The dealer now has #{bank} chips."
deal_cards(2)
sort_cards
puts "---> Current cards:\n"
show_cards
puts "---> Players bet:\n"
players_bet
puts "\n---> Dealer deals one more card\n"
deal_cards(1)
show_cards
puts "---> Determining results\n"
determine_results
puts "\n---> New standings\n"
show_player_chips
puts ""
end
game_over
end
def new_round
@round += 1
players.each do |player|
player.discard_hand
end
end
def ante
players.each do |player|
if not player.eliminated?
@bank = @bank + player.pay(ANTE_AMOUNT)
end
end
end
def deal_cards(num_of_cards)
players.each do |player|
next if player.eliminated?
1.upto(num_of_cards) do
player.take_card(deck.deal)
end
end
end
def sort_cards
players.each do |player|
next if player.eliminated?
player.sort_hand_by_rank
end
end
def players_bet
players.each do |player|
if player.eliminated?
puts "#{player.name} passes. (Out of chips!)"
else
print "#{player.name} can bet between 0 and #{max_bet(player)}: "
bet = gets.to_i
if bet < 0 || bet > max_bet(player)
bet = 0
end
puts "#{player.name} bet #{bet}"
player.bet = bet
end
end
end
def max_bet(player)
[player.chips, bank].min
end
def show_player_chips
players.each do |player|
if player.eliminated?
puts "#{player.name} has been eliminated"
else
puts "#{player.name} has #{player.chips} chips"
end
end
end
def show_cards
players.each do |player|
puts "Player #{player.name}"
if player.eliminated?
puts "Has been eliminated!"
else
player.hand.each do |card|
puts card.to_s
end
end
puts ""
end
end
def determine_results
players.each do |player|
if not player.eliminated?
low_card = player.hand[0]
high_card = player.hand[1]
middle_card = player.hand[2]
if Card.compare_rank(low_card, middle_card) == 0 || Card.compare_rank(high_card,middle_card) == 0
puts "#{player.name} got an exact match, loses twice the bet!"
chips = player.pay(player.bet * 2)
elsif Card.compare_rank(middle_card, low_card) < 0 || Card.compare_rank(middle_card, high_card) > 0
puts "#{player.name} wasn't inbetween loses the bet!"
chips = player.pay(player.bet)
else
puts "#{player.name} wins bet!"
chips = -player.bet
player.win(player.bet)
end
@bank = @bank + chips
if @bank <= 0
puts "Dealer is out of chips, everyone needs to ante up!"
end
while @bank <= 0
ante
end
end
end
end
def game_over
puts "Game Over!"
players.sort! do |player1, player2|
player1.chips <=> player2.chips
end
puts "The winner is #{players.last.name}"
end
end
# Check to see if player has enough chips to play that round, she needs at
# least ANTE + 1, why?
# Write the loops that use next a different way that doesn't require next
# Change the rules so the player's only ante up once at the start of the game
# and again only when the bank is empty. Does that change the outcome of the game?
class Player
attr_accessor :name, :hand, :chips, :bet
def initialize(name, chips)
@name = name
@hand = []
@chips = chips
@bet = nil
end
def discard_hand
@bet = nil
@hand = []
end
def take_card(card)
@hand << card
end
def sort_hand_by_rank
@hand.sort! do |card1, card2|
Card.compare_rank(card1, card2)
end
end
def eliminated?
@chips <= 0
end
def pay(amount)
if amount > @chips
pay = @chips
@chips = 0
else
pay = amount
@chips -= amount
end
pay
end
def win(amount)
@chips += amount
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment