TopPage > 最終課題に向けて > 演習4-2 オセロの基礎2
オセロの基礎2 †
コマを置ける条件 †
- 自分のターンである
- 置く場所にコマがない
- 置く場所から隣8方向のどこかに相手のコマがある
- 置くと,必ず相手のコマが1コ以上裏返る
- 1は演習4-1で,できました.
- 2も,押したボタンがboardIconかどうかを判断するだけなので,すぐできますね.
- 以降の3,4のプログラムは人それぞれです.
- 難しいと思う人は,ここでその一例をご紹介します.
- できそうな部分で参考をやめて,自分で書いていくのが良いですよ.
課題4・隣8方向の判定 †
- judgeButtonは,これから新しく作る関数の名前です.
- この関数の返り値はBoolean型です.指定マスについて,コマを置けたらtrue,置けないならfalseを返す関数です.
- flagをtrueにする手順は複雑ですが,まずは簡単にこう決めてみます.
- 隣8方向に相手のコマがあるか,ひとつずつ見ていく
- ひとつでもあれば,flagをtrueにする
- ここで,隣8方向の参照のしかたを下図に示します.
図1. 隣8方向の求め方
- indexをx,y成分に分解できれば,buttonArray[y][x]を得るためのyとxの情報が参照できます.
- このy,xをそれぞれ±1することで,ほかのボタンの情報も取ることができますね.
- 効率の良いプログラムを作成するには,指定の位置を(0,0)とおき,iとjを用いた相対的な座標を考えます.
- iとjの二重for文から,自分(i=0,j=0)以外のまわり8コマを順に見ていきます.
- for文の中で,buttonArray[y+i][x+j]のアイコンがyourIconならばflagをtrueにします.
- あとは,端っこのボタンの処理です.端は8方向の範囲が場外に出るため,クリックするとエラーが出ると思います.
- そこで,xとyの範囲を限定する,または,for文の中で増加するiとjの最小値と最大値を限定するといいでしょう.
課題5・ひっくり返す判定 †
- どのタイミングでひっくり返すかは人それぞれですが,ここでは置けるかどうかの判定ついでに一緒にやっちゃいます.
- 課題4の「アイコンがyourIconなら」という条件式に「flipButton()の返り値が0以上なら」を追加してください.
- この2つがいずれも真の場合,flagをtrueにします.
- flipButtonは今から作る新しい関数です.仮引数にindex,j,iの3つを与えましょう.
- 返り値はint型です.この関数は,指定マスと指定方向について,ひっくり返せるコマの個数を返します.
- flipButtonの中身では,flagのような返り値用の変数flipNum = 0;も用意しておきます.
- さて,相手のコマが何個ひっくり返るかを見るには,同じ方向に何個連鎖(連続)してひっくり返るかを調べなければなりません.
- flipButtonには,基準となるボタンの位置(index)と,ひっくり返る可能性のある方向成分(j,i)を渡します.
- これらの情報があれば,どこからどの方向に調べていくかが分かりますね.
図2. 隣8方向の先の求め方
- 隣2マス以上に離れたボタンを調べるには,j,iの値を使います.j,iを,方向の単位ベクトルとして用いましょう.
- (1, 0)→(2, 0)→(3, 0)…
- (-1,-1)→(-2, -2)→(-3, -3)…
- 上記を見ると,どの方向も,j,iを足し続けることで遠いボタンの位置を把握できそうです.
- 実引数のj,i値を,別の変数(dx, dy)を用意して代入してください.
- 増分値dx,dyに固定値j,iを足し続けるようなループ文を作ります.
- ループの中身は,以下の処理の繰り返しになっていればOKです.
- x+dx,y+dyの位置が場外なら,flipNumを0にしてループを抜ける(判定中断)
- この位置のアイコンを取得する
- アイコンの種類を見る
- boardIconなら,flipNumを0にしてループを抜ける(判定中断)
- myIconなら,ループを抜ける(連鎖ストップ)
- yourIconなら,flipNumを1増やす(連鎖が続く)
- dx,dyそれぞれにj,iを足す
- こう書けば,ループを抜けた後のflipNumが,その方向でひっくり返すコマの個数になります.
- 実際のひっくり返す処理は,上記のループから抜けた後(flipNumが1個以上あると確定した後)に書きましょう.
- flipButton内に書く場合は,flipNumが1以上の時にこう書きます.
//dx,dyを初期値にリセット
dx = j;
dy = i;
for(int k = 0; k < flipNum; k++, dx+=j, dy+=i){
//ボタンの位置情報を作る
int msgx = x + dx;
int msgy = y + dy;
//サーバに情報を送る
String msg = "FLIP"+" "+msgx+" "+msgy+" "+myColor;
out.println(msg);
out.flush();
}
- judgeButton内に書く場合は,上記のdx,dyを新しく作成すればOKです.
課題6・置けなくなったの判定 †
- オセロの公式ルールでは,自分のターンで必ず相手のコマをひっくり返します.
- どこに置いてもひっくり返せない場合に,ターンのパスができます.パスに回数制限はありません.
- 今回では,自動でパスを発生させる,いつでもパスができるボタンを作る,という方法がありますね.
- ゲームの終了条件は,全てにコマが埋まるか,両者とも置けなくなった場合です.
- ということはやはり,「これ以上コマを置けなくなった」判定が必要ですね.
- CLICKをするたびに各boardIconのボタンの状況を探りましょう.
- 両者とも置けなくなった時点で,各色のコマ数を数えて勝敗を決めます.
おわりに †
- 以上が提出できる自動オセロプログラミングです.
- 提出作品とする場合は,必ず画像を自分で用意したものにしてください.
- ここから新機能を追加したり,ここで得た知識からほかのゲームの作成を目指せば,高得点につながります(たぶん).
- そのほか,詳細の最終課題ページをよく読んで,余裕のある課題作りを心掛けましょう!
最終課題へ