joseph

Finished
11class BowlingGame:
22 def __init__(self):
3 pass
3 self.rolls = []
4 self.current_frame = 1
5 self.frame_rolls = []
6 self.frames = []
7 self.game_over = False
48
59 def roll(self, pins):
6 pass
7
10 # Edge Case: Game is already over
11 if self.game_over:
12 raise ValueError("Game is already complete")
13
14 # Edge Case: Invalid pin count (negative or more than 10)
15 if pins < 0 or pins > 10:
16 raise ValueError("Pins must be between 0 and 10")
17
18 # Edge Case: Too many pins knocked down in a frame
19 if len(self.frame_rolls) == 1 and self.frame_rolls[0] != 10:
20 if self.frame_rolls[0] + pins > 10:
21 raise ValueError("Cannot knock down more than 10 pins in a frame")
22
23 self.frame_rolls.append(pins)
24 self.rolls.append(pins)
25
26 # Handle frame completion
27 if self.current_frame < 10:
28 # Regular frames
29 if self.frame_rolls[0] == 10 or len(self.frame_rolls) == 2:
30 self.frames.append(self.frame_rolls[:])
31 self.frame_rolls = []
32 self.current_frame += 1
33 else:
34 # 10th frame - handle strikes, spares, and open frames correctly
35 if len(self.frame_rolls) == 2:
36 # Check if frame is complete (open frame) or needs fill ball (spare/strike)
37 if self.frame_rolls[0] == 10: # Strike - need 2 fill balls
38 pass # Continue to third roll
39 elif sum(self.frame_rolls) == 10: # Spare - need 1 fill ball
40 pass # Continue to third roll
41 else: # Open frame - complete
42 self.frames.append(self.frame_rolls[:])
43 self.game_over = True
44 elif len(self.frame_rolls) == 3:
45 # Always complete after 3 rolls in 10th frame
46 self.frames.append(self.frame_rolls[:])
47 self.game_over = True
48
849 def score(self):
9 pass
50 # Edge Case: Game is not yet complete
51 if not self.game_over and (len(self.frames) < 9 or (len(self.frames) == 9 and len(self.frame_rolls) > 0 and not (len(self.frame_rolls) == 2 and self.frame_rolls[0] == 10) and not (len(self.frame_rolls) == 2 and sum(self.frame_rolls) == 10))):
52 raise ValueError("Game is not yet complete")
53
54 # Edge Case: Game is not yet complete (10th frame incomplete)
55 if not self.game_over and len(self.frames) < 10:
56 raise ValueError("Game is not yet complete")
57
58 total = 0
59 roll_index = 0
60
61 for frame_num in range(10):
62 if frame_num < len(self.frames):
63 frame = self.frames[frame_num]
64
65 if len(frame) >= 1 and frame[0] == 10: # Strike
66 total += 10
67 # Add next two rolls
68 if frame_num == 9: # 10th frame
69 if len(frame) >= 2:
70 total += frame[1]
71 if len(frame) >= 3:
72 total += frame[2]
73 else: # Regular frame
74 next_rolls = []
75 next_frame_index = frame_num + 1
76
77 # Collect next rolls from subsequent frames
78 while len(next_rolls) < 2 and next_frame_index < len(self.frames):
79 next_frame = self.frames[next_frame_index]
80 for roll in next_frame:
81 next_rolls.append(roll)
82 if len(next_rolls) == 2:
83 break
84 next_frame_index += 1
85
86 for roll in next_rolls:
87 total += roll
88 elif sum(frame[:2]) == 10: # Spare
89 total += 10
90 # Add next roll
91 if frame_num == 9: # 10th frame
92 if len(frame) >= 3:
93 total += frame[2]
94 else: # Regular frame
95 next_frame_index = frame_num + 1
96 if next_frame_index < len(self.frames):
97 next_frame = self.frames[next_frame_index]
98 if len(next_frame) >= 1:
99 total += next_frame[0]
100 else: # Open frame
101 total += sum(frame[:2])
102
103 return total
104
105 # Handled Edge Cases: Game already over, invalid pin count, too many pins in frame, game not complete for scoring
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.