A.2.1

Finished
11class BowlingGame:
22 def __init__(self):
3 pass
4
3 """
4 Initialize a new bowling game.
5 """
6 self.rolls = []
7
58 def roll(self, pins):
6 pass
7
9 """
10 Record a roll in the game.
11
12 Args:
13 pins (int): Number of pins knocked down in this roll
14
15 Raises:
16 ValueError: If pins is negative or greater than 10
17 IndexError: If game is already over
18 """
19 # Edge Case: Invalid pin count (negative or more than 10)
20 if pins < 0 or pins > 10:
21 raise ValueError("Pins must be between 0 and 10")
22
23 # Edge Case: Game already completed
24 if self.is_game_complete():
25 raise IndexError("Game is already complete")
26
27 # Edge Case: Too many pins in a frame (except for fill balls in 10th frame)
28 if not self.is_in_fill_balls():
29 if len(self.rolls) % 2 == 1 and self.rolls[-1] != 10: # Second roll of frame, and first wasn't a strike
30 if self.rolls[-1] + pins > 10:
31 raise ValueError("Cannot knock down more than 10 pins in a frame")
32
33 self.rolls.append(pins)
34
35 def is_in_fill_balls(self):
36 """Check if we're in the fill balls phase of the 10th frame"""
37 # Count how many frames we've completed
38 roll_index = 0
39 frames_completed = 0
40
41 # Count frames 1-9
42 while frames_completed < 9 and roll_index < len(self.rolls):
43 if self.rolls[roll_index] == 10: # Strike - one roll frame
44 roll_index += 1
45 else: # Open frame or spare - two roll frame
46 if roll_index + 1 < len(self.rolls):
47 roll_index += 2
48 else:
49 break # Incomplete frame
50 frames_completed += 1
51
52 # If we haven't completed 9 frames, we're not in 10th frame yet
53 if frames_completed < 9:
54 return False
55
56 # We're in 10th frame, check if we need fill balls
57 tenth_frame_rolls = self.rolls[roll_index:]
58
59 # If we have fewer than 2 rolls, we're not in fill balls yet
60 if len(tenth_frame_rolls) < 2:
61 return False
62
63 # If first two rolls don't make a strike or spare, no fill balls needed
64 if tenth_frame_rolls[0] != 10 and sum(tenth_frame_rolls[:2]) < 10:
65 return False
66
67 # If we have exactly 2 rolls and they make a strike or spare, we need fill balls
68 if len(tenth_frame_rolls) == 2:
69 if tenth_frame_rolls[0] == 10 or sum(tenth_frame_rolls[:2]) == 10:
70 return True
71 else:
72 return False
73
74 # If we have 3 rolls, we're done with fill balls
75 if len(tenth_frame_rolls) >= 3:
76 return False
77
78 return False
79
80 def is_game_complete(self):
81 """Check if the game is complete"""
82 # Count how many frames we've completed
83 roll_index = 0
84 frames_completed = 0
85
86 # Count frames 1-9
87 while frames_completed < 9 and roll_index < len(self.rolls):
88 if self.rolls[roll_index] == 10: # Strike - one roll frame
89 roll_index += 1
90 else: # Open frame or spare - two roll frame
91 if roll_index + 1 < len(self.rolls):
92 roll_index += 2
93 else:
94 break # Incomplete frame
95 frames_completed += 1
96
97 # If we haven't completed 9 frames, game is not complete
98 if frames_completed < 9:
99 return False
100
101 # Check 10th frame completion
102 tenth_frame_rolls = self.rolls[roll_index:]
103
104 # If we have 3 rolls in 10th frame, we're done
105 if len(tenth_frame_rolls) == 3:
106 return True
107
108 # If we have 2 rolls in 10th frame
109 if len(tenth_frame_rolls) == 2:
110 # If first roll was a strike, we need 1 more roll (fill ball)
111 if tenth_frame_rolls[0] == 10:
112 return False # Need 1 more fill ball
113 # If it's a spare, we need 1 more roll (fill ball)
114 elif sum(tenth_frame_rolls) == 10:
115 return False # Need 1 fill ball
116 else:
117 return True # Open frame, game complete
118
119 # If we have 1 roll in 10th frame
120 if len(tenth_frame_rolls) == 1:
121 # If it's a strike, we need 2 more rolls (fill balls)
122 if tenth_frame_rolls[0] == 10:
123 return False # Need 2 fill balls
124 else:
125 return False # Need second roll
126
127 return False
128
8129 def score(self):
9 pass
130 """
131 Calculate the total score for the game.
132
133 Returns:
134 int: The total score for the game
135
136 Raises:
137 IndexError: If the game is not yet complete
138 """
139 # Edge Case: Game not complete
140 if not self.is_game_complete():
141 raise IndexError("Game is not yet complete")
142
143 total_score = 0
144 roll_index = 0
145
146 # Score frames 1-10
147 for frame in range(10):
148 if roll_index >= len(self.rolls):
149 break
150
151 # Check for strike (first roll of frame is 10)
152 if self.rolls[roll_index] == 10:
153 # Strike: 10 + next two rolls
154 frame_score = 10
155 if roll_index + 1 < len(self.rolls):
156 frame_score += self.rolls[roll_index + 1]
157 if roll_index + 2 < len(self.rolls):
158 frame_score += self.rolls[roll_index + 2]
159 roll_index += 1
160 else:
161 # Open frame or spare
162 frame_score = self.rolls[roll_index] + self.rolls[roll_index + 1]
163 # Check for spare
164 if frame_score == 10:
165 # Spare: 10 + next roll
166 if roll_index + 2 < len(self.rolls):
167 frame_score += self.rolls[roll_index + 2]
168 roll_index += 2
169
170 total_score += frame_score
171
172 return total_score
Test NameStatus
test_the_second_bonus_rolls_after_a_strike_in_the_last_frame_cannot_be_a_strike_if_the_first_one_is_not_a_strike
Fail
test_two_bonus_rolls_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points
Fail
test_a_roll_cannot_score_more_than_10_points
Pass
test_a_spare_followed_by_zeros_is_worth_ten_points
Pass
test_a_spare_in_the_last_frame_gets_a_one_roll_bonus_that_is_counted_once
Pass
test_a_strike_earns_ten_points_in_a_frame_with_a_single_roll
Pass
test_a_strike_in_the_last_frame_gets_a_two_roll_bonus_that_is_counted_once
Pass
test_a_strike_with_the_one_roll_bonus_after_a_spare_in_the_last_frame_does_not_get_a_bonus
Pass
test_all_strikes_is_a_perfect_game
Pass
test_an_incomplete_game_cannot_be_scored
Pass
test_an_unstarted_game_cannot_be_scored
Pass
test_bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points
Pass
test_bonus_roll_for_a_spare_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
Pass
test_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
Pass
test_both_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
Pass
test_cannot_roll_after_bonus_roll_for_spare
Pass
test_cannot_roll_after_bonus_rolls_for_strike
Pass
test_cannot_roll_if_game_already_has_ten_frames
Pass
test_consecutive_spares_each_get_a_one_roll_bonus
Pass
test_consecutive_strikes_each_get_the_two_roll_bonus
Pass
test_last_two_strikes_followed_by_only_last_bonus_with_non_strike_points
Pass
test_points_scored_in_the_roll_after_a_spare_are_counted_twice
Pass
test_points_scored_in_the_two_rolls_after_a_strike_are_counted_twice_as_a_bonus
Pass
test_rolling_a_spare_with_the_two_roll_bonus_does_not_get_a_bonus_roll
Pass
test_rolls_cannot_score_negative_points
Pass
test_second_bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points
Pass
test_should_be_able_to_score_a_game_with_all_zeros
Pass
test_should_be_able_to_score_a_game_with_no_strikes_or_spares
Pass
test_strikes_with_the_two_roll_bonus_do_not_get_bonus_rolls
Pass
test_two_bonus_rolls_after_a_strike_in_the_last_frame_can_score_more_than_10_points_if_one_is_a_strike
Pass
test_two_rolls_in_a_frame_cannot_score_more_than_10_points
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.