 |
|
 |
|
中高生のための 今から始めるプログラミング
07. 駒が置けるか判定する その2 |
最終更新日:2004/02/11
|
|
|
1 縦•横•斜めの範囲
|
|
駒があるかないかの判定は前章でしました。次は、2つ目のルール、「そこに置いた自分の駒と他の位置の自分の駒で、縦、横、あるいは斜めから相手の駒を挟めること。」です。ここで言う縦•横•斜めとは、一体どこまでのことを言っているのかというと、例えば右図のピンク色に着色されている位置に駒を置いたとすると、その周りの水色の範囲のことです。ここでは左、下方向にはさめる駒がありますから、置けることになります。さて、これだけ範囲があるのですから、いっぺんに全て探すとなるとかなり大変になってしまいます。探す方向を、置く位置から見て、右、左、上、下、右上、左上、右下、左下の8つに分けて考えましょう。
|
|
2 右方向だけ探す
|
|
さっきから「挟める」と言っていますが、「挟める」とは一体どういうことなのでしょう。「挟める」ということにも、ひとつのルールがあります。それは、
|
|
|
1.隣に相手の駒があること。
2.その方向に自分の駒があること。
3.1の駒と2の駒の間に空きマスがないこと。
|
|
|
です。右図では、1段目が正しい例ですが、2段目3段目では挟めるとは言いません。これは当然のことにも思えますが、実際プログラミングするとこの3つのルールが非常に重要になります。いっぺんに8方向について考えると頭がこんがらがるので、ここでは右方向のみについて説明します。まず、pieces(y,x) の右隣、つまり pieces(y,x+1) の値を調べ、相手の色(値)なら次に進み、それ以外なら挟めないので処理を終えます。次は pieces(y,x+2) の値を調べ、自分の色(値)ならその時点で挟めることになるので、戻り値を 1 にして処理を終えます。空きマスなら挟めないので、そこで処理を終えます。相手の色(値)ならまだまだ挟める可能性があるので、今度は pieces(y,x+3) の値を同じように調べ、また相手の色(値)だったら pieces(y,x+4) の値を…と繰り返していきます。ずっと相手の色(値)だった場合は、最終的には壁に当たりますが(つまり横位置が 7 を超える)、そうなればそれ以上は自分の色(値)がある可能性はないので、処理を終了します。すると、ここでは戻り値が 1 になるか、前の値を引き継ぐかのどちらかになります。少し長くなりましたが、これをソースにしてみましょう。
|
|
|
!---------------- ▽置けるかどうか判定 ----------------
4000 external function check(x,y)
4100 !他の駒があるかないか
4110 if pieces(y,x)=0 then
4120 let check=1
4130 else
4140 let check=0
4149 end if
4200 !挟めるか挟めないか
4300 !隣の色を調べる
4310 if pieces(y,x+1)<>-p then
4390 goto 4899 !処理を終了
4399 end if
4400 !その方向にある自分の駒を探す
4410 let i=2
4420 do while x+i<=7 !壁に当たるまで続ける
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 !(相手の駒の場合は何もせず次に進むので省略)
4790 let i=i+1
4799 loop
4899 !処理を終了する場合、ここに飛ぶ。
4999 end function
!---------------- △置けるかどうか判定 ----------------
|
|
|
挟めるか挟めないかの判定では、挟めない場合は前の戻り値を引き継ぎます。こうすると都合がよいのですが、それは後で説明します。前の戻り値を引き継ぐということは、4120行目で戻り値を 1 だと決め付けてしまうと、4200以降で挟めない判定の時に不具合が起きてしまいます(前の値を引き継ぐため、挟めない時でも 1 を返してしまう)。そこで、4100-4149 行目を、次のように書き換えます。
|
|
|
!---------------- ▽置けるかどうか判定 ----------------
4000 external function check(x,y)
4050 let check=0
4100 !他の駒があるかないか
4110 if pieces(y,x)<>0 then
4140 goto 4999
4149 end if
......
4999 end function
!---------------- △置けるかどうか判定 ----------------
|
|
|
|
|
3 はみ出しを防止する
|
|
実行してみて、盤面の一番右のマスをクリックしてみてください。次のようなエラーが出るはずです。
|
|
|
EXTYPE 2001
添字が範囲外
|
|
|
これは、一番最初に隣の色を調べた時に、あるはずのない pieces(y,8) から値を引き出そうとしたために起こったものです。確かに、自分の駒を探している時は壁に当たったか判定しましたが、隣の色を探す段階ではまだ判定していませんでした。そこで、次のようにソースを書き換えましょう。
|
|
|
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
|
|
|
4420行目にあった do を4220行目に移動し、それに伴なって i の初期値を 1 にしました。また、2ついっぺんに実行されると困るので、select case文を用いて場合分けしています。
|
|
|
ここまでのソースをダウンロード
|
|
|
|
|
 |
|
 |