forked from engwebUM/homework-week3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bowling.rb
90 lines (75 loc) · 2.06 KB
/
bowling.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class Bowling
attr_reader :rolls
def initialize
@rolls = Array.new(21)
end
def roll(pins)
raise "game over" if game_over?
raise "impossible play" if pins < 0 || pins > pins_standing
rolls[playing_roll] = pins
if strike_on_regular_frame? || neither_strike_nor_spare_on_last_frame?
rolls[playing_roll] = 0 # then next ball is set from nil to 0
end
end
def score
points = 0
for frame in 0..9
if strike? (frame)
points += 10 + bonus_strike(frame)
elsif spare? (frame)
points += 10 + bonus_spare(frame)
else
points += frame_points(frame)
end
end
points
end
private
def bonus_spare(frame)
rolls[2*frame+2].to_i
end
def bonus_strike(frame)
if frame < 9
rolls[2*frame+2].to_i + if strike? (frame+1)
rolls[2*frame+4].to_i
else
rolls[2*frame+3].to_i
end
else # tenth frame
rolls[2*frame+1].to_i + rolls[2*frame+2].to_i
end
end
def frame_points(frame)
rolls[2*frame].to_i + rolls[2*frame +1].to_i
end
def game_over?
rolls.find_index(nil) == nil
end
def neither_strike_nor_spare_on_last_frame?
(playing_roll > 19) && !(strike?(9) || spare?(9))
end
def pins_standing
if playing_roll <= 18
playing_roll.even? ? pins = 10 : pins = 10 - rolls[playing_roll-1]
else # tenth frame
if spare? (9) # 10 pins on 3rd ball if tenth frame was a spare
pins = 10
else # 2nd and (eventual) 3rd balls both follow this rule in other occasions
rolls[playing_roll-1] == 10 ? pins = 10 : pins = 10 - rolls[playing_roll-1]
end
end
pins
end
def playing_roll
rolls.find_index(nil).to_i
end
def spare? (frame)
!strike?(frame) && ( rolls[2*frame].to_i + rolls[2*frame+1].to_i == 10 )
end
def strike? (frame)
rolls[2*frame].to_i == 10
end
def strike_on_regular_frame?
(playing_roll < 18) && strike?(playing_roll/2) && (!game_over?)
end
end