ボウリング、得意ですか?
ちなみに俺はめちゃくちゃ苦手である。そもそも、人生の中でも数えるほどしかプレイした事がない。なぜなら、俺の生まれた地である秋田県鹿角市にはボウリング場がないから(唯一、八幡平の湯瀬ホテルには設置されていると聞いたような気がする)。オラこんな村〜イヤだ〜♪
「龍が如く」シリーズではけっこうやり込んでるんだけどね・・・。今日も今日とて、PS4の「龍が如く極」でスプリットゲームに勤しんでいたら、ふと大学時代に友人とボウリングに行った時のことを思い出した。投げ方すらよくわかっていない俺が、1投目でガーターを出して、2投目で10本倒すというようなこと(断じて狙ってやってるわけではない)を3フレームぐらい繰り返していると、友人から「もったいねーな!!」みたいなことを言われた。
当時の俺はルールすら知らないので、「もったいない」の意味すら全然理解していなかった。
この世に俺よりボウリングに疎い人間がいるかは分からないが、念のために説明しておくと、ストライク(フレーム1投目で10ピン倒す)の場合、その後の2投以内に倒したピンの数がフレームの得点に加算される。スペア(フレーム2投目で10ピン倒す)の場合はその後の1投で倒したピンの数が加算される。
つまり、スペアを出した次の1投がガーター(0本)の場合、せっかくのボーナスが加算されない。なので0→10、0→10、0→10みたいなピンの倒し方は一番「もったいない」組み合わせというわけだ。
そんなことを思い出しながら、また皆で遊びに行きてぇな・・・とセンチを感じると同時に、このボウリングスコアの算出のプログラミングはアルゴリズムのエクササイズとして丁度いいんじゃないかと思いつき、さっそく、コントローラーを置いて、PCに向かっていたわけである。
まず、プログラムの要件定義を簡単にすると、
・入力値として倒したピンの数を打ち込める。
・各フレームの得点と、最終スコアが表示される。
この前提でいきたい。
「各フレームの得点」が表示されるというのがちょっとした肝だ。最終スコア(合計得点)だけ出すなら、たぶんそんなに複雑にならないが、フレーム毎に得点を出そうとするとちょっとだけ面倒くさい。
まず、基本的には各フレーム2投以内に倒したピンの数が得点になるが、先に触れたように、ストライクとスペアを出した場合、フレームの得点が確定するのは次の1投か2投目の後になる。例えば、1フレーム目でストライクを出した場合、得点が確定するのは、2フレーム目の2投目か、3フレーム目の1投目(2フレーム目もストライクだった場合)だ。この辺をどう組み立てるかが要点になってくるな。
いろいろ悩みながら、作成したフローチャートがこちら
各フレームのスコアは配列型の変数score[]に入れて管理する。例えば3フレーム目のスコアはscore[3]。同様に、ストライクやスペアを出した場合には、そのフレームにボーナスフラグb_flagを与えて、これも配列に入れて管理することにした。5フレームがストライクだったらb_flag[5] = 2。7フレームがスペアだったらb_flag[7] = 1ってわけ。後の投球でボーナス点を加算する度にフラグを1減らしていく。
投げる度に過去のフレームのフラグ値をチェックする必要があるが、パターンを考えると、nフレーム1投目は最大でも(n-2)フレームまでをチェックして、2投目は(n-1)フレーム目だけチェックすればいい。((n-1)フレームの2投目でb_flag=2(=ストライク)が立つことはありえないから。)
10フレーム目だけ、3回投げる可能性があるのでちょっと特殊だが、まぁこれも最大2投目までに立っているフラグで後の分岐は特定できるので、そんなに難しくない。
このフローチャートを元に、あとはコードを打つべし!
打つべし!
打つべし!
分岐が多くて面倒くさいが、一つ一つの処理はシンプルなのでけっこう短かったな。ちなみに、実用的な視点でいくと、例えばxの値が10以下であることとか、x+yが10以下であることとかを制限したり、あるいは入力時にエラーを返すようなバリデーション機能は必須なんだろうけど、今回は面倒なので省いております。
全部ストライクだったらこんな感じ
理論上の最高得点(300点)は合っている。が、これだけでは内部分岐が正しく動いているとは限らない・・・とは言え、テストデータ作っていちいち検算するのめんどくせぇ・・・
そこで!
人に実際にボウリング場でプレーしてもらって、そこのスコアとプログラムのコンソール結果が合っていれば合格と言う、雑なブラックボックステストで今回はOKにしたいと思う。
ボウリングをプレーして頂くのはもちろんこの方である。
元・東城会直系堂島組舎弟頭補佐、桐生一馬さん。
1人で遊ぶ伝説の龍。
動作テストのためだけに10フレーム投げてくれる伝説の龍。
(いくぜ・・・)
テストのため、ミスやガーター、スペア、ストライクを適度に織り交ぜるよう注文を受ける伝説の龍。
律儀に応える伝説の龍。
そしてついに10フレーム目終了。
俺のプログラムが示した最終スコアは
スコア146
(低っ・・・)
ボウリング場のモニターのスコアは
スコア146
おお・・・!雑なテストだけど、とりあえずは合格ってことでいいんじゃないか?
今回はこんな感じ。お疲れ様でした。