امتیاز یک بازی بولینگ را محاسبه کنید.
بولینگ بازیای است که در آن بازیکنان یک توپ سنگین را میغلتانند تا میلههایی را که به شکل مثلث چیده شدهاند بیندازند. کدی بنویسید که امتیاز یک بازی بولینگ را پیگیری کند.
بازی از ۱۰ «فریم» تشکیل شده است. فریم از یک یا دو پرتاب توپ تشکیل میشود، در حالی که در شروع فریم ۱۰ میله سرپا هستند. برای محاسبهی امتیاز یک فریم سه حالت وجود دارد.
«فریم باز» زمانی است که برای آن فریم امتیازی کمتر از ۱۰ ثبت شود. در این حالت امتیاز فریم برابر با تعداد میلههای افتاده است.
«اسپیر» زمانی است که در پرتاب دوم همهی ده میله افتاده باشند. ارزش کل یک اسپیر برابر است با ۱۰ بهعلاوهی تعداد میلههایی که در پرتاب بعدی میافتند.
«استرایک» زمانی است که در پرتاب اول همهی ده میله افتاده باشند. ارزش کل یک استرایک برابر است با ۱۰ بهعلاوهی تعداد میلههایی که در دو پرتاب بعدی میافتند. اگر بلافاصله پس از یک استرایک، استرایک دوم بیاید، ارزش استرایک اول تا زمانی که توپ یک بار دیگر پرتاب نشود، مشخص نمیشود.
در ادامه یک مثال با سه فریم میبینید:
| فریم ۱ | فریم ۲ | فریم ۳ |
|---|---|---|
| X (استرایک) | 5/ (اسپیر) | 9 0 (فریم باز) |
فریم ۱ برابر است با (۱۰ + ۵ + ۵) = ۲۰
فریم ۲ برابر است با (۵ + ۵ + ۹) = ۱۹
فریم ۳ برابر است با (۹ + ۰) = ۹
یعنی مجموع جاری در این لحظه ۴۸ است.
فریم دهم در بازی یک حالت خاص است. اگر کسی اسپیر یا استرایک بیندازد، به ترتیب یک یا دو «توپ تکمیلی» میگیرد. توپهای تکمیلی برای محاسبهی مجموع فریم دهم وجود دارند. اگر در توپ تکمیلی استرایک یا اسپیر ثبت شود، بازیکن توپهای تکمیلی بیشتری نمیگیرد. ارزش کل فریم دهم برابر است با تعداد کل میلههای افتاده.
برای فریم دهمی با X1/ (یک استرایک و یک اسپیر)، ارزش کل برابر با ۲۰ است.
برای فریم دهمی با XXX (سه استرایک)، ارزش کل برابر با ۳۰ است.
کدی بنویسید که امتیاز یک بازی بولینگ را پیگیری کند. این کد باید از دو عملیات پشتیبانی کند:
roll(pins : int) فراخوانی میشود.
آرگومان آن تعداد میلههای افتاده است.score() : int فقط در انتهای بازی فراخوانی میشود.
این تابع امتیاز کل آن بازی را برمیگرداند.گاهی لازم است یک استثنا ایجاد کنید. وقتی این کار را میکنید، باید همیشه یک پیام خطای معنادار بگنجانید تا نشان دهید منشأ خطا چیست. این کار code شما را خواناتر میکند و به debug کمک چشمگیری میکند. در موقعیتهایی که میدانید منشأ خطا نوع مشخصی خواهد بود، میتوانید یکی از انواع خطای توکار را ایجاد کنید، اما همچنان باید پیامی معنادار بگنجانید.
این تمرین خاص از شما میخواهد که از دستور raise استفاده کنید تا هر وقت قواعد امتیازدهی یا بازی رعایت نمیشوند، یک خطا «پرتاب» کنید. tests تنها در صورتی قبول میشوند که هم exception را raise کنید و هم پیامی همراه آن بگنجانید.
برای ایجاد یک 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")