xas

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 = 0 # Number of rolls in the current frame
9 self.game_over = False
10
511 def roll(self, pins):
6 pass
7
12 """
13 Record a roll in the game.
14
15 Args:
16 pins (int): Number of pins knocked down in this roll
17
18 Raises:
19 ValueError: If the number of pins is invalid or game is already over
20 """
21 # Edge Case: Game is already over
22 if self.game_over:
23 raise IndexError("Game is already complete")
24
25 # Edge Case: Invalid number of pins (negative or more than 10)
26 if pins < 0 or pins > 10:
27 raise ValueError("Pins must be between 0 and 10")
28
29 # Edge Case: Too many pins in a frame (except for special tenth frame cases)
30 if self.current_frame < 10:
31 # For frames 1-9, check if this roll exceeds 10 pins in the frame
32 if self.frame_rolls == 1 and (self.rolls[-1] + pins) > 10:
33 raise ValueError("Cannot knock down more than 10 pins in a frame")
34 else:
35 # For frame 10, we need more complex validation
36 if self.frame_rolls == 1 and self.rolls[-1] == 10:
37 # First roll was a strike, second roll can be anything 0-10
38 pass
39 elif self.frame_rolls == 1:
40 # Second roll in frame 10, check if total exceeds 10
41 if (self.rolls[-1] + pins) > 10:
42 raise ValueError("Cannot knock down more than 10 pins in a frame")
43 elif self.frame_rolls == 2:
44 # Third roll in frame 10
45 # If first two rolls were strikes, third can be 0-10
46 # If first was strike and second wasn't, third can be anything
47 # If first wasn't strike but first two made a spare, third can be 0-10
48 # If first two didn't make 10, this shouldn't happen
49 if self.rolls[-2] != 10 and (self.rolls[-2] + self.rolls[-1]) < 10:
50 raise IndexError("Game is already complete")
51
52 # If we're here, we had a spare or strike and can roll a valid third ball
53 if self.rolls[-2] == 10 and self.rolls[-1] == 10:
54 # Two strikes, third roll can be 0-10
55 pass
56 elif self.rolls[-2] == 10 and self.rolls[-1] != 10:
57 # First strike, second not, third can be anything
58 pass
59 elif self.rolls[-2] + self.rolls[-1] == 10:
60 # Spare, third roll can be 0-10
61 pass
62 else:
63 # This shouldn't happen with proper game flow
64 raise IndexError("Game is already complete")
65
66 self.rolls.append(pins)
67 self.frame_rolls += 1
68
69 # Handle frame progression
70 if self.current_frame < 10:
71 # For frames 1-9
72 if self.frame_rolls == 2 or pins == 10: # Strike or second roll
73 self.current_frame += 1
74 self.frame_rolls = 0
75 else:
76 # For frame 10
77 # Determine if the game is over
78 if self.frame_rolls == 2:
79 # Two rolls in frame 10
80 if self.rolls[-2] + self.rolls[-1] < 10: # Open frame
81 self.game_over = True
82 elif self.frame_rolls == 3:
83 # Three rolls in frame 10 - game is definitely over
84 self.game_over = True
85
886 def score(self):
9 pass
87 """
88 Calculate the total score for the game.
89
90 Returns:
91 int: The total score of the game
92
93 Raises:
94 ValueError: If the game is not yet complete
95 """
96 # Edge Case: Game is not complete
97 if not self.game_over and not (self.current_frame == 10 and self.frame_rolls >= 2 and
98 (self.rolls[-2] + self.rolls[-1] == 10 or
99 self.rolls[-2] == 10)):
100 raise IndexError("Game is not yet complete")
101
102 total_score = 0
103 roll_index = 0
104
105 # Score frames 1-9
106 for frame in range(9):
107 # Edge Case: Not enough rolls to score the frame
108 if roll_index >= len(self.rolls):
109 raise IndexError("Game is not yet complete")
110
111 if self.rolls[roll_index] == 10: # Strike
112 # Edge Case: Not enough rolls to calculate strike bonus
113 if roll_index + 2 >= len(self.rolls):
114 raise IndexError("Game is not yet complete")
115 total_score += 10 + self.rolls[roll_index + 1] + self.rolls[roll_index + 2]
116 roll_index += 1
117 else:
118 frame_score = self.rolls[roll_index] + self.rolls[roll_index + 1]
119 if frame_score == 10: # Spare
120 # Edge Case: Not enough rolls to calculate spare bonus
121 if roll_index + 2 >= len(self.rolls):
122 raise IndexError("Game is not yet complete")
123 total_score += 10 + self.rolls[roll_index + 2]
124 else: # Open frame
125 total_score += frame_score
126 roll_index += 2
127
128 # Score frame 10
129 # Edge Case: Not enough rolls for the 10th frame
130 if roll_index >= len(self.rolls):
131 raise IndexError("Game is not yet complete")
132
133 # Handle the 10th frame
134 if roll_index + 1 < len(self.rolls):
135 total_score += self.rolls[roll_index] + self.rolls[roll_index + 1]
136 if roll_index + 2 < len(self.rolls):
137 total_score += self.rolls[roll_index + 2]
138 else:
139 total_score += self.rolls[roll_index]
140
141 return total_score
142
143 # Handled Edge Cases: Game already over, invalid pins, too many pins in frame, game not complete, not enough rolls to score, not enough rolls for 10th frame
Test NameStatus
test_bonus_roll_for_a_spare_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
Fail
test_both_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
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_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_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.