harrison

Finished
11class BowlingGame:
22 def __init__(self):
3 pass
4
3 """
4 Initialize a new bowling game.
5 """
6 self.rolls = []
7 self.current_frame = 1
8 self.frame_rolls = []
9 self.frames = []
10 self.game_over = False
11
512 def roll(self, pins):
6 pass
7
13 """
14 Record a roll in the game.
15
16 Args:
17 pins (int): Number of pins knocked down in this roll
18
19 Raises:
20 ValueError: If pins is negative or greater than 10
21 IndexError: If game is already over
22 """
23 # Edge Case: Game is already over
24 if self.game_over:
25 raise ValueError("Game is already over")
26
27 # Edge Case: Invalid number of pins
28 if pins < 0:
29 raise ValueError("Pins must be between 0 and 10")
30
31 # Edge Case: Too many pins for a single roll
32 if pins > 10:
33 raise ValueError("Pin count exceeds pins on the lane")
34
35 # Edge Case: Too many pins in a frame (not considering special 10th frame cases yet)
36 if len(self.frame_rolls) > 0 and self.current_frame < 10:
37 if self.frame_rolls[0] + pins > 10:
38 raise ValueError("Cannot knock down more than 10 pins in a frame")
39
40 self.rolls.append(pins)
41 self.frame_rolls.append(pins)
42
43 # Handle frame completion
44 if self.current_frame < 10:
45 # Regular frames (1-9)
46 if len(self.frame_rolls) == 2 or pins == 10: # Strike or two rolls
47 self.frames.append(self.frame_rolls[:])
48 self.frame_rolls = []
49 self.current_frame += 1
50 else:
51 # 10th frame special handling
52 # Edge Case: Invalid fill balls in 10th frame
53 if len(self.frame_rolls) == 3:
54 # Check if the third roll is valid
55 # If first roll was a strike, second roll can be 0-10
56 # If first two rolls are a spare or strike, third roll can be 0-10
57 # Otherwise, third roll shouldn't happen
58 if not ((self.frame_rolls[0] == 10) or
59 (len(self.frame_rolls) >= 2 and sum(self.frame_rolls[:2]) == 10)):
60 raise ValueError("invalid fill balls")
61
62 # Edge Case: Too many pins in fill balls
63 if len(self.frame_rolls) == 3 and self.frame_rolls[0] == 10:
64 # First was a strike, check second and third
65 if self.frame_rolls[1] < 10 and self.frame_rolls[1] + self.frame_rolls[2] > 10:
66 raise ValueError("Pin count exceeds pins on the lane")
67
68 self.frames.append(self.frame_rolls[:])
69 self.frame_rolls = []
70 self.game_over = True
71 elif len(self.frame_rolls) == 2:
72 # Check if we need a third roll
73 if sum(self.frame_rolls) < 10:
74 # No strike or spare, frame is complete
75 self.frames.append(self.frame_rolls[:])
76 self.frame_rolls = []
77 self.game_over = True
78 elif len(self.frame_rolls) == 1 and self.frame_rolls[0] < 10:
79 # First roll wasn't a strike, need a second roll
80 pass
81
82 # Edge Case: Too many pins in 10th frame
83 if self.current_frame == 10 and len(self.frame_rolls) >= 2:
84 if self.frame_rolls[0] < 10 and sum(self.frame_rolls[:2]) > 10:
85 raise ValueError("Pin count exceeds pins on the lane")
86
887 def score(self):
9 pass
88 """
89 Calculate the total score for the game.
90
91 Returns:
92 int: The total score for the game
93
94 Raises:
95 IndexError: If the game is not yet complete
96 """
97 # Edge Case: Game not complete
98 if not self.game_over and (len(self.frames) < 10 or
99 (len(self.frames) == 10 and len(self.frame_rolls) > 0)):
100 raise ValueError("Game is not yet complete")
101
102 total_score = 0
103 roll_index = 0
104
105 # Score first 9 frames
106 for frame_num in range(9):
107 if roll_index >= len(self.rolls):
108 break
109
110 # Strike
111 if self.rolls[roll_index] == 10:
112 total_score += 10 + self.rolls[roll_index + 1] + self.rolls[roll_index + 2]
113 roll_index += 1
114 # Spare
115 elif self.rolls[roll_index] + self.rolls[roll_index + 1] == 10:
116 total_score += 10 + self.rolls[roll_index + 2]
117 roll_index += 2
118 # Open frame
119 else:
120 total_score += self.rolls[roll_index] + self.rolls[roll_index + 1]
121 roll_index += 2
122
123 # Score 10th frame
124 # Edge Case: Incomplete 10th frame
125 if roll_index < len(self.rolls):
126 for i in range(roll_index, len(self.rolls)):
127 total_score += self.rolls[i]
128
129 return total_score
130 # Handled Edge Cases: Game is already over, invalid number of pins, too many pins for a single roll,
131 # too many pins in a frame, invalid fill balls in 10th frame, too many pins in fill balls,
132 # too many pins in 10th frame, game not complete, incomplete 10th frame
Test NameStatus
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_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.