2018/08/29(水)21:26
【Excelプログラミング講座】10 未解決バグに挑戦!(その1)
【Excelプログラミング講座】第10回です。
この講座では、エクセル野球シミュレーション「ダイナミックベースボール」のゲームプログラムを材料として、エクセルVBAでのプログラミングを解説していきます。
▼ダイナミック・ベースボールのページ
過去記事をまとめたサイト↓
▼エクセルプログラミング講座
前回は、デバッグの手順について。
(1)再現を試みる
(2)原因を突き止める
(3)プログラムを修正する
(4)動作確認
という話をしました。
今回は、前回の続きです。
未解決だったバグの改善に挑みます!
前回参照したブログのコメント欄に寄せられたバグ報告のうち、未解決だったバグがあります。
【エラー内容】
・サヨナラ勝ちの場合、ホームランの時はその打者に打点と安打がカウントされるが、サヨナラヒットの時には、打者に打点、打数、安打が反映されない。
この連載もついに第10回を迎えたので、最後の大仕事として、このバグの改善に挑みます!
なお、リンク先のコメント欄を見てもらうと分かると思いますが、僕は「打点のカウント」だけされるところまで改善できたものの、その後の対処ができずに、投げ出していました。
ブログ記事を書きながらプログラム構造をだいぶ読み返すことが出来たので、今こそ再挑戦です。
【エラー報告を受けた直後の思考と対応】
・ホームランの時は、例えば
Call SeisekiB(Range("H6"), 16)
Call SeisekiP(Range("O6"), 20)
ScoreIn
のように、成績反映 が、ScoreIn(得点処理)より先になっているのに比べて、他のケースが逆になっているからだと思う。
・プログラムコード表示画面において、Ctrlキーを押しながらFキーを押して「検索」画面を表示し、「ScoreIn」を検索して、怪しいところの順番を変えて、対処しよう。
バグの原因を予測し、プログラム処理の順序に着目して、順序を入れ替えることで解決できるという見通しを持っています。
その基本方針自体はいいと思うのですが・・・。
さて、バグ改善をする前に、このバグに関係するプログラムコードの情報を確認しておきます。
打者成績のワークシートにおけるそれぞれのデータの場所(セルの番地)です。
以下の画像は、セルの番地を示す番号を、打点や安打数などの数字としてそれぞれ入力したものです。
すなわち、本塁打=14(左から14番目の場所)
打点=16
盗塁数=18
安打数=20
打数=22
がそれぞれのデータの位置情報です。
上の写真では「V6」というセルの番地が選択されていますが、これをプログラム上で表記すると、「V」というのは左から22番目なので、こういう指定の仕方をするわけです。「V」という列番号を数字で表したのが「22」です。
つまり、プログラムコードにおける
Call SeisekiB(Range("H6"), 16)
は、打点に対応しています。
同様に、
Call SeisekiB(Range("H6"), 20)
なら安打数。
Call SeisekiB(Range("H6"), 22)
なら打席数です。
さて、打点の場合はうまく順序を入れ替えたものの、安打数と打数のカウントについては僕は以前あきらめています。
その理由は、
「打数と安打数のカウントが今の仕様だとサヨナラで途中終了する場所と完全に離れているので、打数と安打数がカウントできない」
というものでした。
プログラムを書いたときには、ヒットを判定する分岐(サブルーチン)に飛んで、そのままサヨナラヒットで試合終了する場合を想定できていなかったということです。
こうなるとなかなか難しいものがあります。
しかし、落ち着いて考えれば何とかなるかもしれません。
難しいケースは、小分けにして考えなければいけません。
一気に解決を図るのではなく、小分けにして各個撃破を狙います。
まず、「打数」のカウント。
「打数のカウント」は、新打者がバッターになってすぐにカウントするぐらい前の方に持ってくればよさそうですが・・・実は打数にカウントされない例外的な場合があるので、それに気をつけないといけません。例外的な場合とは、「送りバント」の場合です。
野球に詳しい方はご存じですが、送りバントに成功した場合、打数にも安打数にも記録されません。
つまり、ユーザーがいつ「バント」ボタンを押すかどうか分からないので、打数のカウントを最初に行ってしまうわけにはいかなかったのです。
実際のプログラムを見てみましょう。
バントの場合のサブルーチンは、「Module3」の場所にあります。
「Module3」の「バント」のプログラムを見ると、セーフティバントの時のみ、打数と安打数を反映する記述があります。
~~~~~~~~~~~~~~~~~~~~~~~~
BantSafe:
MsgBox ("1塁送球~セーフ!!"), , "バント!"
Call SeisekiB(Range("H6"), 22)
Call SeisekiB(Range("H6"), 20)
'※バント後自分が生きたら、特別にヒットとみなす。
(略)
GoTo Nextbatter
Exit Sub
BantOut:
MsgBox ("1塁送球~アウト!!"), , "バント!"
If Dice2 = 3 Then
Call SeisekiB(Range("H6"), 22)
'※セーフティバントのとき、打数をカウントする。
End If
~~~~~~~~~~~~~~~~~~~~~~~~
バントのところはできればいじりたくないですが・・・
そうなると、「打数と安打数のカウントが今の仕様だとサヨナラで途中終了する場所と完全に離れているので、打数と安打数がカウントできない」の罠にはまってしまいます。
そこで・・・
逆転の発想で、打数と安打数のカウントを最後の最後から最初の最初に移し、バントの場合のみ例外的にカウントを戻す、というやり方で、なんとか実現したいと思います。
長くなりましたので、この続きは、また次回!
次回には、バグが直っているかな~??
P.S.今回この連載講座の更新が約30分遅れましたことをお詫びします。
(予定では水曜21時の予定だったのですが、、、21:30になってしまいました。)