 |
|
 |
|
中高生のための 今から始めるプログラミング
08. 駒が置けるか判定する その3 |
最終更新日:2004/02/11
|
|
|
1 全ての方向を探す
|
|
さて、前章では右方向だけ探しましたが、今度は全ての方向(右、左、上、下、右上、左上、右下、左下)を探してみましょう。右に進むということは、横位置が 1 増えるということでした。また、左に進むということは、横位置が 1 減るということで、左上に進むということは、横位置が 1 減って縦位置が 1 増えるということです。横、縦位置がいくつ増えるかを tx, ty で表すとすれば、始めに上げた8方向は、
|
|
|
方向 (tx,ty)
右 (+1, 0)
左 (-1, 0)
上 ( 0,+1)
下 ( 0,-1)
右上 (+1,+1)
左上 (-1,+1)
右下 (+1,-1)
左下 (-1,-1)
|
|
|
と表すことができますね。良く見ると、この方向は、(tx,ty) の (0,0) を除いた全ての組合せになっています。ですから、前章で作ったソースを for~next でくくり、(0,0) を除いて実行させれば簡単にできます。つまり、
|
|
|
4150 for ty=-1 to 1
4160 for tx=-1 to 1
4170 if not(tx=0 and ty=0) then
4200 !挟めるか挟めないか
4210 let i=1
4220 do while x+i<=7 !壁に当たるまで続ける
4250 select case i
4300 case 1 !隣の色を調べる
4310 if pieces(y,x+1)<>-p then
4390 goto 4899 !処理を終了
4399 end if
4400 case is>=2 !その方向にある自分の駒を探す
4500 if pieces(y,x+i)=p then !自分の駒の場合
4510 let check=1
4590 goto 4899 !処理を終了
4599 end if
4600 if pieces(y,x+i)=0 then !空きマスの場合
4690 goto 4899 !処理を終了
4699 end if
4700 !(相手の駒の場合は何もせず次に進むので省略)
4749 end select
4790 let i=i+1
4799 loop
4899 !処理を終了する場合、ここに飛ぶ。
4947 end if
4948 next tx
4949 next ty
|
|
|
とすれば全ての方向に関して実行できることになります。もちろん、これはただくくっただけですので、いくらか修正しなければならないところはありますが。
|
|
2 進める方向を書き変える
|
|
前章では右方向についてしか考えなかったので、位置を進めるときに pieces(y,x+i) としていました。しかし、左に進めたい時は (y,x-i) と書かなければいけませんし、左上に進めたい時は pieces(y+i,x-i) などとしなければいけません。これをいちいち書かなければいけないというと、for~nextで囲った意味がなくなってしまいます。しかし、一行で書く方法がきちんとあります。(y,x+i) や、(y+i,x-i) などに見られる +i や -i などは、(+1)*i, (-1)*i とも書くことができます。また、x や y など、何も書いていないときでも x+0*i, y+0*i であると考えれば、これは全て、横、縦位置がいくつ増えるかを表す tx, ty を i に掛けていることになりますね。ですから、(y+ty*i,x+tx*i) と書けば一発です。では、ソースを書き換えましょう。
|
|
|
4150 for ty=-1 to +1
4160 for tx=-1 to +1
4170 if not(tx=0 and ty=0) then
4200 !挟めるか挟めないか
4210 let i=1
4220 do while x+i<=7 !壁に当たるまで続ける
4250 select case i
4300 case 1 !隣の色を調べる
4310 if pieces(y+ty,x+tx)<>-p then
4390 goto 4899 !処理を終了
4399 end if
4400 case is>=2 !その方向にある自分の駒を探す
4500 if pieces(y+ty*i,x+tx*i)=p then !自分の駒の場合
4510 let check=1
4590 goto 4899 !処理を終了
4599 end if
4600 if pieces(y+ty*i,x+tx*i)=0 then !空きマスの場合
4690 goto 4899 !処理を終了
4699 end if
4700 !(相手の駒の場合は何もせず次に進むので省略)
4749 end select
4790 let i=i+1
4799 loop
4899 !処理を終了する場合、ここに飛ぶ。
4947 end if
4948 next tx
4949 next ty
|
|
|
さて、4220行目の do while の後ろにも x+i という書き方が見られますが、これはどう書き換えたら良いでしょう。これは次の項で説明します。
|
|
3 壁の判定を書き変える
|
|
さて、全ての方向について考えるのに伴なって、壁の判定も変わってきます。まず、x+i をどう書きかえるかです。これは、横、縦位置を同時に考えた時、先に壁に当たってしまえば(先に範囲外になってしまえば)その時点で処理は終了です。先に壁に当たるほうは値が大きいほうですから、max(y+ty*i,x+tx*i) です。これが範囲内にあるか判断するわけですから、max(y+ty*i,x+tx*i)<=7 となりますね。また、今度は左(下)に行きすぎて範囲外になる場合もあります。これは min(y+ty*i,x+tx*i)>=0 となります。max ではなく min なのは、小さいほうが先に範囲外になるためです。あとは、これを and でつなげば壁の判定が書き変えられます。
|
|
|
4150 for ty=-1 to +1
4160 for tx=-1 to +1
4170 if not(tx=0 and ty=0) then
4200 !挟めるか挟めないか
4210 let i=1
4220 do while max(y+ty*i,x+tx*i)<=7 and min(y+ty*i,x+tx*i)>=0 !壁に当たるまで続ける
......
4799 loop
4899 !処理を終了する場合、ここに飛ぶ。
4947 end if
4948 next tx
4949 next ty
|
|
|
さて、これで駒が置けるか判定するのは終了です。ためしに実行してみてください。駒が挟める位置にしか置けなくなったと思います。駒が置ける位置が限定されたことで、少しはオセロらしくなったのではないでしょうか。
|
|
|
ここまでのソースをダウンロード
|
|
|
|
|
 |
|
 |