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 the number of pins is invalid or game is already over.
21 """
22 # Edge Case: Game is already over
23 if self.game_over:
24 raise ValueError("game is already over")
25
26 # Edge Case: Invalid number of pins (negative or more than 10)
27 if pins < 0 or pins > 10:
28 raise ValueError("invalid number of pins")
29
30 # Edge Case: Too many pins in a frame
31 if len(self.frame_rolls) == 1:
32 # For tenth frame, we allow up to 10 pins on second roll regardless of first
33 if self.current_frame == 10:
34 # Special case for tenth frame - if first roll was 10 (strike), second can be up to 10
35 if self.frame_rolls[0] == 10:
36 pass # Second roll can be anything up to 10
37 # If first roll wasn't 10, sum must not exceed 10
38 elif self.frame_rolls[0] + pins > 10:
39 raise ValueError("invalid number of pins")
40 # For other frames, sum of two rolls cannot exceed 10
41 elif self.frame_rolls[0] + pins > 10:
42 raise ValueError("invalid number of pins")
43
44 self.frame_rolls.append(pins)
45 self.rolls.append(pins)
46
47 # Handle frame completion
48 if self.current_frame < 10:
49 # Regular frames (1-9)
50 if pins == 10 or len(self.frame_rolls) == 2:
51 self.frames.append(self.frame_rolls[:])
52 self.frame_rolls = []
53 self.current_frame += 1
54 else:
55 # Tenth frame
56 # Strike case: need two more rolls
57 if len(self.frames) == 9 and len(self.frame_rolls) == 3:
58 # Third roll in tenth frame
59 self.frames.append(self.frame_rolls[:])
60 self.frame_rolls = []
61 self.game_over = True
62 elif len(self.frames) == 9 and len(self.frame_rolls) == 2:
63 # Second roll in tenth frame
64 # If it's a strike or spare, we need one more roll
65 if self.frame_rolls[0] == 10 or sum(self.frame_rolls) == 10:
66 # Need one more roll for fill ball
67 pass
68 else:
69 # Open frame, game over
70 self.frames.append(self.frame_rolls[:])
71 self.frame_rolls = []
72 self.game_over = True
73 elif len(self.frames) == 10:
74 # This means we already completed the tenth frame
75 self.game_over = True
76
877 def score(self):
9 pass
78 """
79 Calculate the total score for the game.
80
81 Returns:
82 int: The total score of the game.
83
84 Raises:
85 ValueError: If the game is not yet complete.
86 """
87 # Edge Case: Game is not complete
88 if not self.game_over and (len(self.frames) < 10 or
89 (len(self.frames) == 10 and len(self.frame_rolls) > 0)):
90 raise ValueError("game is not yet complete")
91
92 total_score = 0
93 roll_index = 0
94
95 # Score first 9 frames
96 for frame_index in range(9):
97 if roll_index >= len(self.rolls):
98 raise ValueError("game is not yet complete")
99
100 # Strike
101 if self.rolls[roll_index] == 10:
102 # Edge Case: Not enough rolls to calculate strike bonus
103 if roll_index + 2 >= len(self.rolls):
104 raise ValueError("game is not yet complete")
105 total_score += 10 + self.rolls[roll_index + 1] + self.rolls[roll_index + 2]
106 roll_index += 1
107 else:
108 frame_score = self.rolls[roll_index] + self.rolls[roll_index + 1]
109 # Spare
110 if frame_score == 10:
111 # Edge Case: Not enough rolls to calculate spare bonus
112 if roll_index + 2 >= len(self.rolls):
113 raise ValueError("game is not yet complete")
114 total_score += 10 + self.rolls[roll_index + 2]
115 else:
116 # Open frame
117 total_score += frame_score
118 roll_index += 2
119
120 # Score tenth frame
121 if len(self.frames) < 10:
122 raise ValueError("game is not yet complete")
123
124 tenth_frame = self.frames[9]
125
126 # Edge Case: Tenth frame has invalid number of rolls
127 if len(tenth_frame) < 2 or len(tenth_frame) > 3:
128 raise ValueError("game is not yet complete")
129
130 total_score += sum(tenth_frame)
131
132 return total_score
133
134 # Handled Edge Cases: Game already over, invalid pins count, too many pins in frame,
135 # incomplete game when scoring, insufficient rolls for strike/spare bonus,
136 # invalid tenth frame rolls
Test NameStatus
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_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.