.
中高生のための
今から始めるプログラミング
08. 駒が置けるか判定する その3
最終更新日:2004/02/11

<<BACK ↑HOME NEXT>>

 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
さて、これで駒が置けるか判定するのは終了です。ためしに実行してみてください。駒が挟める位置にしか置けなくなったと思います。駒が置ける位置が限定されたことで、少しはオセロらしくなったのではないでしょうか。
 
ここまでのソースをダウンロード
 

<<BACK ↑HOME NEXT>>

Copyright (C) 2003-2004 Shohei Ohsawa, Naoya Okada & Fumiya Miyakawa. All rights reserved.