hope

Finished
11class BowlingGame:
22 def __init__(self):
3 pass
4
3 self.rolls = []
4 self.current_frame = 0
5 self.frame_rolls = []
6 self.frames = []
7 self.game_over = False
8
59 def roll(self, pins):
6 pass
7
10 # Edge Case: Game is already over
11 if self.game_over:
12 raise ValueError("Cannot roll after game is over")
13
14 # Edge Case: Invalid pin count (negative)
15 if pins < 0:
16 raise ValueError("Negative roll is invalid")
17
18 # Edge Case: Invalid pin count (more than 10)
19 if pins > 10:
20 raise ValueError("Pin count exceeds pins on the lane")
21
22 # Edge Case: Validation for 10th frame fill balls
23 if self.current_frame == 9: # 10th frame
24 if len(self.frame_rolls) == 0:
25 # First roll in 10th frame - no special validation needed
26 pass
27 elif len(self.frame_rolls) == 1:
28 # Second roll in 10th frame
29 if self.frame_rolls[0] == 10: # First roll was a strike
30 # Second roll can be anything 0-10
31 pass
32 elif self.frame_rolls[0] + pins > 10: # Would exceed 10 pins in frame
33 raise ValueError("Pin count exceeds pins on the lane")
34 elif len(self.frame_rolls) == 2:
35 # Third roll in 10th frame (fill ball)
36 if self.frame_rolls[0] == 10: # First roll was a strike
37 # Second fill ball validation - only validate if first fill ball wasn't a strike
38 if self.frame_rolls[1] != 10 and self.frame_rolls[1] + pins > 10:
39 raise ValueError("invalid fill balls")
40 elif self.frame_rolls[0] + self.frame_rolls[1] == 10: # First two rolls were a spare
41 # Third roll can be anything 0-10
42 pass
43 else:
44 # Open frame - no third roll allowed
45 raise ValueError("Cannot roll after game is over")
46 else: # Regular frames 1-9
47 if len(self.frame_rolls) == 1 and self.frame_rolls[0] != 10:
48 # Edge Case: Invalid pin count when there are not enough pins standing in regular frames
49 if self.frame_rolls[0] + pins > 10:
50 raise ValueError("Pin count exceeds pins on the lane")
51
52 self.frame_rolls.append(pins)
53 self.rolls.append(pins)
54
55 # Handle frame completion
56 if self.current_frame < 9: # Frames 1-9
57 if pins == 10 or len(self.frame_rolls) == 2:
58 self.frames.append(self.frame_rolls[:])
59 self.frame_rolls = []
60 self.current_frame += 1
61 else: # 10th frame
62 # Handle frame completion for 10th frame
63 if len(self.frame_rolls) == 2:
64 # Check if 10th frame is complete (no spare or strike)
65 if self.frame_rolls[0] + self.frame_rolls[1] < 10:
66 self.frames.append(self.frame_rolls[:])
67 self.frame_rolls = []
68 self.game_over = True
69 elif len(self.frame_rolls) == 3:
70 # Frame is complete with fill balls
71 self.frames.append(self.frame_rolls[:])
72 self.frame_rolls = []
73 self.game_over = True
74
875 def score(self):
9 pass
76 # Edge Case: New game should have score of 0
77 if len(self.frames) == 0 and len(self.rolls) == 0:
78 return 0
79
80 # Edge Case: Attempting to score before game is complete
81 if not self.game_over and len(self.frames) < 10:
82 raise IndexError("Score cannot be taken until the end of the game")
83
84 # Edge Case: Attempting to score with incomplete 10th frame
85 if len(self.frames) == 10 and not self.game_over:
86 raise IndexError("Score cannot be taken until the end of the game")
87
88 total = 0
89 roll_index = 0
90
91 for frame_num in range(10):
92 frame = self.frames[frame_num]
93
94 if len(frame) >= 1 and frame[0] == 10: # Strike
95 total += 10
96 # Add next two rolls
97 if frame_num < 9: # Not the 10th frame
98 next_frame = self.frames[frame_num + 1]
99 if len(next_frame) >= 1:
100 total += next_frame[0]
101 if len(next_frame) >= 2:
102 total += next_frame[1]
103 # Edge Case: When next frame is also a strike
104 elif next_frame[0] == 10 and frame_num < 8:
105 third_frame = self.frames[frame_num + 2]
106 if len(third_frame) >= 1:
107 total += third_frame[0]
108 # Edge Case: When we need the second roll from frame after next but it doesn't exist
109 elif next_frame[0] == 10 and frame_num == 8:
110 # In 10th frame, we have all rolls we need
111 if len(next_frame) >= 2:
112 total += next_frame[1]
113 else: # 10th frame
114 if len(frame) >= 3:
115 total += frame[1] + frame[2]
116 elif len(frame) >= 2 and frame[0] + frame[1] == 10: # Spare
117 total += 10
118 # Add next roll
119 if frame_num < 9: # Not the 10th frame
120 next_frame = self.frames[frame_num + 1]
121 if len(next_frame) >= 1:
122 total += next_frame[0]
123 else: # 10th frame
124 if len(frame) >= 3:
125 total += frame[2]
126 else: # Open frame
127 total += sum(frame)
128
129 return total
130
131 # Handled Edge Cases: Game is already over, Invalid pin count (negative), Invalid pin count (more than 10), Invalid pin count when there are not enough pins standing, Determining when the 10th frame is complete, Attempting to score before game is complete, Attempting to score with incomplete 10th frame, When next frame is also a strike, When we need the second roll from frame after next but it doesn't exist
Test NameStatus
test_an_unstarted_game_cannot_be_scored
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_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_the_second_bonus_rolls_after_a_strike_in_the_last_frame_cannot_be_a_strike_if_the_first_one_is_not_a_strike
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_bonus_rolls_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points
Pass
test_two_rolls_in_a_frame_cannot_score_more_than_10_points
Pass

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