Konoha

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 ValueError: If game is already over
22 ValueError: If frame rules are violated
23 """
24 # Edge Case: Game already over
25 if self.game_over:
26 raise ValueError("game is already over")
27
28 # Edge Case: Invalid pin count
29 if pins < 0:
30 raise ValueError("pins cannot be negative")
31
32 # Edge Case: Too many pins
33 if pins > 10:
34 raise ValueError("pin count exceeds pins on the lane")
35
36 # Edge Case: Tenth frame special cases
37 if self.current_frame == 10:
38 return self._handle_tenth_frame(pins)
39
40 self.frame_rolls.append(pins)
41 self.rolls.append(pins)
42
43 # Edge Case: Strike in frames 1-9
44 if len(self.frame_rolls) == 1 and pins == 10:
45 self.frames.append(self.frame_rolls)
46 self.frame_rolls = []
47 self.current_frame += 1
48 # Edge Case: Two rolls completed in frame
49 elif len(self.frame_rolls) == 2:
50 # Edge Case: Invalid frame total
51 frame_total = sum(self.frame_rolls)
52 if frame_total > 10:
53 raise ValueError("pin count exceeds pins on the lane")
54 self.frames.append(self.frame_rolls)
55 self.frame_rolls = []
56 self.current_frame += 1
57
58 # Edge Case: Game completion after 10 frames
59 if self.current_frame > 10:
60 self.game_over = True
61
62 def _handle_tenth_frame(self, pins):
63 """
64 Handle special rules for the tenth frame.
65
66 Args:
67 pins (int): Number of pins knocked down
68 """
69 self.frame_rolls.append(pins)
70 self.rolls.append(pins)
71
72 # Edge Case: First roll in tenth frame
73 if len(self.frame_rolls) == 1:
74 # If first roll is not a strike, continue normally
75 return
76
77 # Edge Case: Two rolls in tenth frame
78 if len(self.frame_rolls) == 2:
79 frame_total = sum(self.frame_rolls)
80 # Edge Case: Invalid frame total
81 if frame_total > 10 and self.frame_rolls[0] != 10:
82 raise ValueError("pin count exceeds pins on the lane")
83 # Edge Case: Open frame or spare - game over
84 if frame_total < 10 or (frame_total == 10 and self.frame_rolls[0] != 10):
85 self.frames.append(self.frame_rolls)
86 self.game_over = True
87 # Edge Case: Strike needs third roll
88 elif self.frame_rolls[0] == 10:
89 return
90
91 # Edge Case: Third roll in tenth frame
92 if len(self.frame_rolls) == 3:
93 # Edge Case: Invalid combinations
94 if self.frame_rolls[0] != 10: # First wasn't strike
95 if sum(self.frame_rolls[0:2]) != 10: # Second wasn't spare
96 raise ValueError("invalid fill balls")
97 self.frames.append(self.frame_rolls)
98 self.game_over = True
99
8100 def score(self):
9 pass
101 """
102 Calculate the total score for the game.
103
104 Returns:
105 int: Total score for the game
106
107 Raises:
108 ValueError: If game is not yet complete
109 """
110 # Edge Case: Game not complete
111 if not self.game_over:
112 raise ValueError("game is not yet complete")
113
114 total_score = 0
115 roll_index = 0
116
117 # Edge Case: Score calculation for frames 1-9
118 for frame_num in range(9): # First 9 frames
119 if roll_index >= len(self.rolls):
120 break
121
122 # Strike
123 if self.rolls[roll_index] == 10:
124 # Edge Case: Ensure enough rolls for strike bonus
125 if roll_index + 2 >= len(self.rolls):
126 raise ValueError("game is not yet complete")
127 total_score += 10 + self.rolls[roll_index + 1] + self.rolls[roll_index + 2]
128 roll_index += 1
129 else:
130 frame_score = self.rolls[roll_index] + self.rolls[roll_index + 1]
131 # Spare
132 if frame_score == 10:
133 # Edge Case: Ensure enough rolls for spare bonus
134 if roll_index + 2 >= len(self.rolls):
135 raise ValueError("game is not yet complete")
136 total_score += 10 + self.rolls[roll_index + 2]
137 # Open frame
138 else:
139 total_score += frame_score
140 roll_index += 2
141
142 # Edge Case: Score calculation for tenth frame
143 # Add the remaining rolls (tenth frame)
144 while roll_index < len(self.rolls):
145 total_score += self.rolls[roll_index]
146 roll_index += 1
147
148 return total_score
149
150 # Handled Edge Cases: Game already over, invalid pin count, too many pins, tenth frame special cases, strike in frames 1-9, two rolls completed in frame, game completion after 10 frames, first roll in tenth frame, two rolls in tenth frame, invalid frame total, open frame or spare - game over, strike needs third roll, third roll in tenth frame, invalid combinations, game not complete, score calculation for frames 1-9, ensure enough rolls for strike bonus, spare, open frame, ensure enough rolls for spare bonus, score calculation for tenth frame
Test NameStatus
test_a_spare_in_the_last_frame_gets_a_one_roll_bonus_that_is_counted_once
Fail
test_a_strike_with_the_one_roll_bonus_after_a_spare_in_the_last_frame_does_not_get_a_bonus
Fail
test_bonus_roll_for_a_spare_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
Fail
test_cannot_roll_after_bonus_roll_for_spare
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_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_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_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_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.