為一場保齡球比賽計分。
保齡球是一種遊戲,玩家滾動沉重的球,擊倒排成三角形的球瓶。 請寫程式記錄一場保齡球比賽的分數。
一場比賽由 10 格組成。 每一格由一次或兩次投球組成,每格開始時有 10 個球瓶立著。 每一格的計分方式有三種情況。
開放格是指該格得分低於 10 分。 此時該格的分數就是擊倒的球瓶數。
補中是指第二次投球擊倒全部十個球瓶。 補中的總分是 10 加上下一次投球擊倒的球瓶數。
全倒是指第一次投球就擊倒全部十個球瓶。 全倒的總分是 10 加上接下來兩次投球擊倒的球瓶數。 如果全倒之後緊接著又出現一次全倒,就必須再投一次球,才能確定第一次全倒的分數。
以下是一個三格的例子:
| 第 1 格 | 第 2 格 | 第 3 格 |
|---|---|---|
| X(全倒) | 5/(補中) | 9 0(開放格) |
第 1 格是 (10 + 5 + 5) = 20
第 2 格是 (5 + 5 + 9) = 19
第 3 格是 (9 + 0) = 9
這表示目前的累計總分是 48。
比賽中的第 10 格是特殊情況。 如果有人投出補中或全倒,就能分別獲得一次或兩次加球。 加球的存在是為了計算第 10 格的總分。 在加球時投出全倒或補中,並不會讓玩家獲得更多加球。 第 10 格的總分就是擊倒的球瓶總數。
若第 10 格是 X1/(一次全倒和一次補中),總分是 20。
若第 10 格是 XXX(三次全倒),總分是 30。
請寫程式記錄一場保齡球比賽的分數。 它應該支援兩種操作:
roll(pins : int)。
引數是擊倒的球瓶數。score() : int 只會在比賽完全結束時呼叫。
它會回傳該場比賽的總分。有時候,你需要拋出例外。這麼做時,你應該一律附上有意義的錯誤訊息,指出錯誤的來源是什麼。這能讓你的程式碼更容易閱讀,對除錯也有很大的幫助。如果你知道錯誤的來源會是某個特定類型,可以選擇拋出其中一種內建錯誤類型,但仍然應該附上有意義的訊息。
這個練習特別要求你使用 raise 敘述,在未遵守計分或投球規則時「拋出」錯誤。只有同時raise了exception並附上訊息,測試才會通過。
若要拋出帶有訊息的ValueError,請把訊息寫成exception類型的引數:
# example when a bonus is attempted with an open frame
raise IndexError("cannot throw bonus with an open tenth frame")
# example when fill balls are invalid
raise ValueError("invalid fill balls")