質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

1972閲覧

ボウリングのスコアのアルゴリズムについて

eme

総合スコア27

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/04/11 02:22

編集2018/04/12 01:18

python

1def bowling(a): 2 score = 0 3 for i in range(0,len(a)-1): 4 score += a[i] #倒したピンの数を総計する 5 for j in range(1,len(a)-1): 6 if a[j-1] != 0 and a[j] == 10:#ストライクをだす 7 score += (a[j+1]+a[j+2]) 8 elif a[j-1]==0 and a[j]==10:#スペアをだす(一投目がガーター) 9 score += (a[j+1]) 10 elif a[j-1]+a[j]==10 and a[j-1]!=0 and a[j]!=0:#スペアをだす(上以外) 11 score += a[j+1] 12 print(score) 13 14def test1(): 15 print(bowling([10,8,2,10,0,10,10,6,4,10,8,2,10,9,1,10]))

ボウリングのスコアを計算するアルゴリズムを作成しました。
しかし、例としてtest1を実行したところ、200点のところが190点として出力されました。スペアは次の1投のスコアを、ストライクは次の2投分のスコアを加算することはわかるのですが、どうかご指導ください。

追記

python

1def bowling(a): 2 score=0#トータルスコア 3 flame=1#フレーム(1−10) 4 throw=1#フレーム内の投球回数(1or2) 5 for n in range(0,len(a)-1): 6 score += a[n] 7 if flame != 10: 8 if throw == 1 and a[n] == 10:#ストライクの時 9 score += (a[n+1] + a[n+2])#後ろの2投分をスコアに加算 10 flame += 1#フレームを一つ進める(この時投球回数は増やさない) 11 if throw == 2 and a[n]+a[n-1] == 10:#スペアの時 12 score += a[n+1]#後ろ1投分をスコアに加算する 13 flame += 1#フレームを一つ進める 14 throw = 1#投球回数を1に戻す 15 if throw >= 3:#1フレーム2投までなので、次のフレーム(1)に移る 16 flame += 1 17 throw = 1 18 throw += 1 19 else: 20 throw += 1 21 print(score)

として書きなおしましたが、まだうまくいきません...

python

1# -*- coding: utf-8 -*- 2def bowling(a): 3 score=0#トータルスコア 4 flame=1#フレーム(1−10) 5 throw=1#フレーム内の投球回数(1or2) 6 for n in range(0,len(a)): 7 print(throw) 8 score += a[n]v8 9 if flame != 10: 10 if throw == 1 and a[n] == 10:#ストライクの時 11 score += (a[n+1] + a[n+2])#後ろの2投分をスコアに加算 12 flame += 1#フレームを一つ進める(この時投球回数は増やさない) 13 elif throw == 1 and a[n] != 10: 14 throw += 1 15 elif throw == 2 and a[n]+a[n-1] == 10:#スペアの時 16 score += a[n+1]#後ろ1投分をスコアに加算する 17 flame += 1#フレームを一つ進める 18 throw = 1#投球回数を1に戻す 19 elif throw >= 3:#1フレーム2投までなので、次のフレーム(1)に移る 20 flame += 1 21 throw = 1 22 else: 23 throw += 1 24 else: 25 throw += 1 26 print(score)

途中経過を示します。おそらく、throw==2の時の処理を完成させれば、うまくいくと思われます。(一応、bowling([10,8,2,10,0,10,10,6,4,10,8,2,10,9,1,10]))の時はうまく計算ができました。別の配列で失敗しましたが...
(printで吐き出す方法を教えてくれた方どうもありがとうございました。)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2018/04/11 02:45

絶対にスペアかストライクを取る前提なのでしょうか?
eme

2018/04/11 03:01

そのような前提は一応ありません。test1()では、ストライクとスペアを取ることにしていますが...
fuzzball

2018/04/11 06:06

ループ毎に flame throw a[n] 加算後のscore を表示させてみてはどうでしょうか?
eme

2018/04/11 07:20

わかりましたやって見ます。別件があるのでしばしお待ちを...
guest

回答3

0

ベストアンサー

  • 1フレのストライクが検知されない。
  • 前フレ2投目ミス、次フレ1投目ストライク → スペア判定される。
  • 前フレ2投目+次フレ1投目=10 → スペア判定される。
  • 10フレでスペア/ストライク加算されてしまう。

【追記】

スコア加算はフレーム単位でやった方がシンプルな気がします。
ベタ書きすると、

python

1if a[n] == 10: 2 #strike 3 score += a[n] + a[n+1] + a[n+2] 4 n += 1 5elif a[n] + a[n+1] == 10: 6 #spare 7 score += a[n] + a[n+1] + a[n+2] 8 n += 2 9else: 10 score += a[n] + a[n+1] 11 n += 2

こうやって見ると、加算に関してはストライクもスペアも同じ式なのが面白いですね。

投稿2018/04/11 03:00

編集2018/04/12 02:00
fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

eme

2018/04/11 03:30

わかりました。フレームをまたぐエラーが多いので、二次元配列(list)でやって見ます。
fuzzball

2018/04/12 02:02

ちょっとコードを書いてみました。
eme

2018/04/12 12:17

回答ありがとうございます。このように書くとforループにより、nをif文中で変えてもステップが飛ばせないのですが、どうすればよいでしょうか。 def bowling(a): score=0#トータルスコア for n in range(0,len(a)-1): print(score) if a[n] == 10:#ストライクの時 score += (a[n]+ a[n+1] + a[n+2])#後ろの2投分をスコアに加算 n += 2 elif a[n]+a[n+1] == 10:#スペアの時 score += a[n]+a[n+1]+a[n+2]#後ろ1投分をスコアに加算する n += 2 else: score += a[n]+a[n+1] n += 2 print(score)
fuzzball

2018/04/12 12:31

forじゃなくてwhileを使えばいいと思います。 データが必ず10フレまで揃っている保証があるなら、10フレまでいったら終了でもOKかと。
eme

2018/04/12 13:39

ありがとうございました!全て解けました!
guest

0

Python

1for j in range(1, len(a)-1): 2 if a[j-1] != 0 and a[j] == 10

ですから、1フレームがストライクだった時、この条件を満たさないので加算されていないのでは。

ボウリングのスコアは1フレーム目から順番に計算していくしかないので、手順を大きく組み替える必要があると思います。
私は Python だとちょっとわからないので、ざっくり書いてみます。

var S = 0; /* トータルスコア */ var F = 1; /* フレーム */ var T = 1; /* フレーム内投球回 */ /* 投球による倒したピンの数が、a[] に入っている */ for(n = 0; n < a.length-1; n++) { S = S + a[n]; if (F != 10) { if (T == 1 && a[n] == 10) { /* ストライク = フレーム内の1投目で10本倒し */ S = S + a[n+1] + a[n+2]; // 後ろ2投分を加算する F = F + 1; // フレームを一つ進める } else if (T == 2 && a[n]+a[n-1] == 10) { /* スペア = フレーム内の2投目で、1投目と合わせて10本倒し */ S = S + a[n+1]; // 後ろ1投分を加算する F = F + 1; T = 1; } else { T = T + 1; if (T >= 3) { // 1フレーム2投までなので、次のフレームに移る F = F + 1; T = 1; } } } else { /* 10フレームはボーナス加算なしなのでそのまま継続 */ T = T + 1; } }

投稿2018/04/11 02:27

編集2018/04/11 06:19
tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tacsheaven

2018/04/11 06:17

書き直されたコード上で、ストライクのとき、スペアのときは、そのif分の中で処理が終わって、次のループへ進む(continue)をしなければなりません。それをしていないと計算がおかしくなります。 ※150になるかな?
tacsheaven

2018/04/11 06:20

continue をやめて、if ~ elseif ~ else の形にしました。これに合わせて python を記述してみてください
eme

2018/04/11 07:19

ありがとうございます。やって見ます。
guest

0

2通りの方法で記述できました。
tacsheavenさん、fuzzballさん、どうもありがとうございました。

投稿2018/04/12 13:43

編集2018/04/13 04:04
eme

総合スコア27

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問