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

<<BACK ↑HOME NEXT>>

 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文を用いて場合分けしています。
 
ここまでのソースをダウンロード
 

<<BACK ↑HOME NEXT>>

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