fishlium

Finished
11class BowlingGame:
22 def __init__(self):
3 pass
4
3 """
4 Initialize a new bowling game.
5 """
6 self.rolls = []
7 self.frames = []
8 self.current_frame = []
9 self.frame_count = 0
10 self.game_over = False
11
512 def roll(self, pins):
6 pass
13 """
14 Record a roll in the game.
15
16 Args:
17 pins (int): Number of pins knocked down in this roll
18
719
20 Raises:
21 ValueError: If pins is negative or greater than 10
22 ValueError: If game is already over
23 """
24 # Edge Case: Game is already over
25 if self.game_over:
26 raise ValueError("Cannot roll after game is over")
27
28 # Edge Case: Invalid number of pins
29 if pins < 0 or pins > 10:
30 raise ValueError("Pins must be between 0 and 10")
31
32 # Edge Case: Too many pins in a frame (not considering 10th frame special rules yet)
33 if len(self.current_frame) > 0 and self.frame_count < 10:
34 if self.current_frame[0] + pins > 10:
35 raise ValueError("Invalid roll: pins downed in a frame cannot exceed 10")
36
37 self.current_frame.append(pins)
38 self.rolls.append(pins)
39
40 # Handle frame completion
41 if self.frame_count < 9: # Frames 1-9
42 # Edge Case: Strike (first roll of 10 pins)
43 if len(self.current_frame) == 1 and pins == 10:
44 self.frames.append(self.current_frame)
45 self.current_frame = []
46 self.frame_count += 1
47 # Edge Case: Second roll in a regular frame
48 elif len(self.current_frame) == 2:
49 self.frames.append(self.current_frame)
50 self.current_frame = []
51 self.frame_count += 1
52 else: # 10th frame
53 # Edge Case: 10th frame with strike or spare needs special handling
54 if len(self.current_frame) == 3:
55 self.frames.append(self.current_frame)
56 self.current_frame = []
57 self.frame_count += 1
58 self.game_over = True
59 elif len(self.current_frame) == 2:
60 # If it's not a spare or strike, game is over
61 if self.current_frame[0] + self.current_frame[1] < 10:
62 self.frames.append(self.current_frame)
63 self.current_frame = []
64 self.frame_count += 1
65 self.game_over = True
66 # Otherwise, need one more roll
67 elif len(self.current_frame) == 1 and self.current_frame[0] < 10:
68 # First roll was not a strike, so need a second roll
69 pass
70
871 def score(self):
9 pass
72 """
73 Calculate the total score for the game.
74
75
76 Returns:
77 int: The total score for the game
78
79
80 Raises:
81 ValueError: If the game is not yet complete
82 """
83 # Edge Case: Game not complete
84 if not self.game_over:
85 raise ValueError("Score cannot be taken until the end of the game")
86
87 total_score = 0
88 roll_index = 0
89
90 # Edge Case: Not enough frames
91 if len(self.frames) < 10:
92 raise ValueError("Score cannot be taken until the end of the game")
93
94 # Score first 9 frames
95 for frame_index in range(9):
96 # Edge Case: Frame doesn't have enough rolls
97 if frame_index >= len(self.frames):
98 raise ValueError("Score cannot be taken until the end of the game")
99
100 frame = self.frames[frame_index]
101
102 # Edge Case: Invalid frame
103 if len(frame) == 0:
104 raise ValueError("Invalid frame")
105
106 if len(frame) == 1: # Strike
107 # Edge Case: Not enough rolls for strike bonus
108 if frame_index + 1 >= len(self.frames):
109 raise ValueError("Invalid frame")
110
111 next_frame = self.frames[frame_index + 1]
112
113 # Edge Case: Next frame is invalid
114 if len(next_frame) == 0:
115 raise ValueError("Invalid frame")
116
117 if len(next_frame) >= 2: # Normal case
118 total_score += 10 + next_frame[0] + next_frame[1]
119 elif len(next_frame) == 1: # Next frame is also a strike
120 # Edge Case: Need third roll for bonus calculation
121 if frame_index + 2 >= len(self.frames) or len(self.frames[frame_index + 2]) == 0:
122 raise ValueError("Invalid frame")
123 third_frame = self.frames[frame_index + 2]
124 total_score += 10 + next_frame[0] + third_frame[0]
125 else: # Regular frame (2 rolls)
126 frame_score = frame[0] + frame[1]
127 if frame_score == 10: # Spare
128 # Edge Case: Not enough rolls for spare bonus
129 if frame_index + 1 >= len(self.frames) or len(self.frames[frame_index + 1]) == 0:
130 raise ValueError("Invalid frame")
131 next_roll = self.frames[frame_index + 1][0]
132 total_score += 10 + next_roll
133 else: # Open frame
134 total_score += frame_score
135
136 # Score 10th frame
137 # Edge Case: Missing 10th frame
138 if len(self.frames) < 10:
139 raise ValueError("Score cannot be taken until the end of the game")
140
141 tenth_frame = self.frames[9]
142
143 # Edge Case: Invalid 10th frame
144 if len(tenth_frame) < 2:
145 raise ValueError("Invalid frame")
146
147 if len(tenth_frame) == 2:
148 total_score += tenth_frame[0] + tenth_frame[1]
149 elif len(tenth_frame) == 3:
150 total_score += tenth_frame[0] + tenth_frame[1] + tenth_frame[2]
151
152 return total_score
153
154 # Handled Edge Cases: Game already over, invalid pins, too many pins in frame, strike in regular frame, second roll in regular frame, 10th frame special rules, game not complete, not enough frames, invalid frame, not enough rolls for strike bonus, next frame invalid, need third roll for bonus, not enough rolls for spare bonus, open frame, missing 10th frame, invalid 10th frame
Test NameStatus
test_a_spare_in_the_last_frame_gets_a_one_roll_bonus_that_is_counted_once
Fail
test_a_strike_in_the_last_frame_gets_a_two_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_all_strikes_is_a_perfect_game
Fail
test_both_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
Fail
test_cannot_roll_after_bonus_rolls_for_strike
Fail
test_last_two_strikes_followed_by_only_last_bonus_with_non_strike_points
Fail
test_rolling_a_spare_with_the_two_roll_bonus_does_not_get_a_bonus_roll
Fail
test_second_bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points
Fail
test_strikes_with_the_two_roll_bonus_do_not_get_bonus_rolls
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_can_score_more_than_10_points_if_one_is_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_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_cannot_roll_after_bonus_roll_for_spare
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_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_rolls_cannot_score_negative_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_two_rolls_in_a_frame_cannot_score_more_than_10_points
Pass

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