Skip to content

Instantly share code, notes, and snippets.

@Kallin
Created August 8, 2024 20:55
Show Gist options
  • Select an option

  • Save Kallin/518b39d57c6bb4021bb199680b781c83 to your computer and use it in GitHub Desktop.

Select an option

Save Kallin/518b39d57c6bb4021bb199680b781c83 to your computer and use it in GitHub Desktop.
bowling.rb
FRAME_COUNT = 5
class Frame
PIN_COUNT = 10
def initialize(final_frame = false)
@rolls = RollList.new
@final_frame = final_frame
reset_pins
end
def reset_pins
@pins_remaining = PIN_COUNT
end
def add_roll(roll)
@rolls.add_roll(roll)
@pins_remaining -= roll.pins_hit
if @final_frame && @pins_remaining == 0 && @rolls.count < 3
reset_pins
end
end
# Both these methods assume a non-final frame.
def strike?
@pins_remaining == 0 && @rolls.count == 1
end
def spare?
@pins_remaining == 0 && @rolls.count == 2
end
def pins_remaining
@pins_remaining
end
def options
# 10,10,10
# 10,10,4
# 10,5,5
# 4,2
end
def complete?
if @final_frame
(@pins_remaining > 0 && @rolls.count == 2) || @rolls.count == 3
else # This goes against object calisthenics
@pins_remaining == 0 || @rolls.count == 2
end
end
end
class FrameList
def initialize
@frames = []
end
def add_frame
@frames << Frame.new(count == FRAME_COUNT - 1)
end
def last
@frames.last
end
def count
@frames.count
end
def frames
# this isn't allowed I guess, but doing for now to make progress on scoring
@frames
end
end
class BowlingGame
def initialize()
@scoring_strategy = DefaultScoringStrategy.new
@frame_list = FrameList.new
@frame_list.add_frame
@current_score = 0
@last_two_rolls = [nil, nil]
end
# list of frames
def roll(roll)
current_frame.add_roll(roll)
puts "we're in frame #{@frame_list.count}"
puts "we hit #{roll.pins_hit} pins!"
@last_two_rolls.unshift
if current_frame.strike?
puts "Strike"
@last_two_rolls << 'X'
elsif current_frame.spare?
puts "Spare!"
@last_two_rolls << '/'
else
@last_two_rolls << roll.pins_hit
end
if @last_two_rolls.include? 'X'
@current_score = @current_score + (roll.pins_hit * 2)
elsif @last_two_rolls.last == '/'
@current_score = @current_score + (roll.pins_hit * 2)
else
@current_score = @current_score + roll.pins_hit
end
puts "current score is #{@current_score}"
@frame_list.add_frame if current_frame.complete? && @frame_list.count < FRAME_COUNT
# puts "we're in frame #{count}"
# puts "we rolled a 5, X, or /"
# puts "current score is 123"
end
def current_frame
@frame_list.last
end
def is_finished
@frame_list.count == FRAME_COUNT && current_frame.complete?
end
def pins_remaining
current_frame.pins_remaining
end
def scores
# return an array with what happened in each frame, as well as total score at end of that frame
scores = []
end
end
class DefaultScoringStrategy
end
class GameRenderer
def initialize(game)
@game = game
end
def draw
# numbers = (1..10).to_a
# puts numbers.join("\t")
# array_of_pipes = Array.new(10, '|')
# puts array_of_pipes.join("\t")
end
end
class RollList
def initialize
@rolls = []
end
def sum
@rolls.sum { |roll| roll.pins_hit }
end
def count
@rolls.count
end
def add_roll(roll)
@rolls << roll
end
end
class Roll
def initialize(pins_hit)
@pins_hit = pins_hit
end
def pins_hit
@pins_hit
end
end
class RandomPlayer
def initialize(game)
@game = game
end
def play_until_complete
until @game.is_finished
roll
end
end
def roll
puts "Pins remaining: #{@game.pins_remaining}"
pins_hit = (0..@game.pins_remaining).to_a.sample
roll = Roll.new(pins_hit)
@game.roll(roll)
end
end
game = BowlingGame.new
player = RandomPlayer.new(game)
player.play_until_complete
renderer = GameRenderer.new(game)
renderer.draw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment