jackson

Finished
11class BowlingGame:
22 def __init__(self):
3 pass
4
3 self.rolls = []
4 self.current_frame = 0
5 self.frame_rolls = []
6
57 def roll(self, pins):
6 pass
7
8 # Edge Case: Invalid pin count (negative or more than 10)
9 if pins < 0 or pins > 10:
10 raise ValueError("Pins must be between 0 and 10")
11
12 # Edge Case: Game already has 10 complete frames
13 if self.current_frame >= 10 and not self._needs_fill_balls():
14 raise ValueError("Cannot roll after game is complete")
15
16 # Edge Case: Adding too many pins in a frame (except in fill balls)
17 if len(self.frame_rolls) == 1:
18 if self.current_frame == 9:
19 # 10th frame special handling
20 if self.frame_rolls[0] == 10:
21 # After a strike, any pins are allowed for first fill ball
22 pass
23 elif self.frame_rolls[0] + pins > 10:
24 raise ValueError("Cannot knock down more than 10 pins in a frame")
25 elif self.frame_rolls[0] + pins > 10:
26 raise ValueError("Cannot knock down more than 10 pins in a frame")
27
28 # No validation needed for fill balls in 10th frame
29 # Each fill ball can be 0-10 regardless of previous rolls
30
31 self.rolls.append(pins)
32 self.frame_rolls.append(pins)
33
34 # Determine if frame is complete
35 frame_complete = False
36 if self.current_frame < 9: # Frames 1-9
37 if self.frame_rolls[0] == 10 or len(self.frame_rolls) == 2: # Strike or two rolls
38 frame_complete = True
39 else: # 10th frame
40 if len(self.frame_rolls) == 3: # Three rolls in 10th frame
41 frame_complete = True
42 elif len(self.frame_rolls) == 2: # Two rolls in 10th frame
43 # If not a strike or spare, frame is complete
44 if self.frame_rolls[0] != 10 and sum(self.frame_rolls) < 10:
45 frame_complete = True
46 # If it's a strike or spare, need one more roll (fill ball)
47 elif self.frame_rolls[0] == 10 or sum(self.frame_rolls) == 10:
48 frame_complete = False
49
50 if frame_complete:
51 self.current_frame += 1
52 self.frame_rolls = []
53
854 def score(self):
9 pass
55 # Edge Case: No rolls yet - return 0
56 if len(self.rolls) == 0:
57 return 0
58
59 # Edge Case: Game not yet complete
60 if self.current_frame < 10 or self._needs_fill_balls():
61 raise ValueError("Game is not yet complete")
62
63 total_score = 0
64 roll_index = 0
65
66 for frame in range(10):
67 if self._is_strike(roll_index): # Strike
68 # Edge Case: Incomplete game data for strike calculation
69 if roll_index + 2 >= len(self.rolls):
70 raise ValueError("Game is not yet complete")
71 total_score += 10 + self.rolls[roll_index + 1] + self.rolls[roll_index + 2]
72 roll_index += 1
73 elif self._is_spare(roll_index): # Spare
74 # Edge Case: Incomplete game data for spare calculation
75 if roll_index + 2 >= len(self.rolls):
76 raise ValueError("Game is not yet complete")
77 total_score += 10 + self.rolls[roll_index + 2]
78 roll_index += 2
79 else: # Open frame
80 total_score += self.rolls[roll_index] + self.rolls[roll_index + 1]
81 roll_index += 2
82
83 return total_score
84
85 def _is_strike(self, roll_index):
86 return self.rolls[roll_index] == 10
87
88 def _is_spare(self, roll_index):
89 # Handle either an index or a list of two rolls
90 if isinstance(roll_index, int):
91 return self.rolls[roll_index] + self.rolls[roll_index + 1] == 10
92 else: # It's a list
93 return sum(roll_index) == 10
94
95 def _needs_fill_balls(self):
96 # Edge Case: Check if 10th frame needs fill balls but hasn't received them
97 if self.current_frame < 9: # Not in 10th frame yet
98 return False
99 if self.current_frame == 9 and len(self.frame_rolls) == 0: # Just started 10th frame
100 return False
101
102 # In 10th frame, check if we need more rolls
103 if len(self.frame_rolls) == 1: # Only first roll in 10th frame
104 return True # Always need at least one more
105 elif len(self.frame_rolls) == 2: # Two rolls in 10th frame
106 # If it's a strike or spare, need one more (fill ball)
107 return self.frame_rolls[0] == 10 or sum(self.frame_rolls) == 10
108 else: # Already have 3 rolls in 10th frame
109 return False
110
111# Handled Edge Cases: Invalid pin count, game already complete, too many pins in frame, incomplete game for scoring, strike calculation with insufficient data, spare calculation with insufficient data, 10th frame fill ball requirements
Test NameStatus
test_an_unstarted_game_cannot_be_scored
Fail
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_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.