[[TopPage]] > 最終課題に向けて > 演習4-1 オセロの基礎1

* オセロの基礎 [#rc5dd636]

** はじめに [#lb0ff286]

''まずは,[[最終課題]]を確認してください''.

演習4は&size(24){任意};の課題です.やらなくてもかまいません!~
ここでは,&color(red){%%%「ひとまずオセロを作りたいんだけど,何をしたらいいか分からない!」方向けに解説%%%を行います};.~
ネットワーク通信とマス目アルゴリズムの詳しい説明もしているので,既に作りたい作品を想定している方も,参考になると思います.

※クライアントは,[[演習3-2>演習3-2 ネットワーク対戦ゲームクライアント]]の''MyClient.java''を引き続き利用します.~
※サーバは,[[演習3-1-1>演習3-1-1 MyServer.java]]で作成した''MyServer2.java''を使います.


** やりたいことを考える [#e56d7212]

- オセロといっても,単純ではありません.やることはいっぱいですね!
-- まず,どんなプログラムを書けばいいかの想定と順序を組み立てましょう.
- まず,コマを自由に置ける空間を作りましょう.それからターン制,置ける判定という順に制限をかけていく,という実装順序が良さそうです.

 細かな準備
 クライアントごとに置けるコマの色を決定する
 ターン制にする
 判定を行う
  置けるかどうか
  ひっくり返すかどうか
  ターンをパスするかどうか
  勝敗はどうか
 etc ...

** 課題1・細かな準備 [#c3dff162]

+ 使用するマウスイベントを限定する
-- 余計な出力や,マス目をドラッグできる機能はいりませんよね.
-- コメントアウト(// や /* */)しておくと,その行を無効化できます.
--- 前にも説明しましたが,public void mouseEntered(MouseEvent e)など,マウスイベント受け取る関数全体を削除してはいけません.
--- これらは,マウスイベントを受け取るMouseListener,MouseMotionListenerを使ってる場合に,必ず必要なるものです.
--- この関数の中身だけをコメントアウト(// や /* */)してください.
+ ウインドウのタイトルやサイズを設定する
-- 少し広めにしておきましょう.
+ ボタンを8x8にする
-- 二重配列を使い,[[演習2-1>演習2-1 GUIプログラミングの基礎]]のような順序でボタンを置いていくと良いでしょう.
-- %%%jとi,y方向とx方向の関係に注意してください%%%.下記のような二重for文の場合は,[j][i]と書くと1行目,2行目,…と配置されます.
 for(int i=0; i<8; i++) {
   for(int j=0; j<8; j++) {
     buttonArray[j][i]. ...
   }
 }

-- setActionCommandには,ひとつの情報しか付加できません.そのため,[[演習2-1>演習2-1 GUIプログラミングの基礎]]で書いたように,jとiを用いた計算式にします.
-- この計算式を受信部分などでj,iに戻したい場合は,以下の式で変換できます.
 int i = theBnum / 8;
 int j = theBnum % 8;
&color(,yellow){ボタン作成のよくある間違い};
 buttonArray[3][3] = new JButton(BlackIcon);
 buttonArray[3][4] = new JButton(WhiteIcon);
をfor文の中で作ると,同じボタンが次々とnewで作られてしまいます.
for文の外で作成しましょう!
をfor文の中で作ると,同じボタンが次々とnewで作られてしまいます.~
for文の中では boardIconで作成し,for文の外で setIconを使って盤面の初期化を行いましょう!

+ 初期のコマを配置する
-- 最初の白と黒のコマを置きましょう.
-- 最初の白と黒のコマを置きましょう.~
--- setIconを使うと boardIconから他のアイコンに変更できます.

** 課題2・クライアントごとに置けるコマの色を決定する [#m0a0e9b8]

- MyClient内のmyColorと同じ位置に,2つの新しい変数を宣言しましょう.
 private ImageIcon myIcon, yourIcon;
-- 次に,myColorが0の時,myIconにblackIcon,yourIconにwhiteIconを代入するようにします.
--- 1の時は,その逆を代入するように書きます.
--- myColorは,オセロの白か黒かの意味で,ゲームの最初に決めますので,その部分にプログラムを書いて下さい.
- これで,いつでも自分の色のアイコン(myIcon)を参照できるようになりました.
-- 自分と相手は,myIconの中身が異なることになります.

- 次に,[[演習3-2>演習3-2 ネットワーク対戦ゲームクライアント]]で記述したプログラムを少し書き換えて,自分側でmyIconを置いた時に,相手側ではyourIconを置くようにします.
-- PLACEの送信部分で送る色の情報をmyColorにしてください.
-- 送信前にアイコンを変更する処理を色々書いていたら,この部分を%%%全て消してください%%%.
--- MyServer2は,送信した内容を,送った人へも送り返します.
--- そのため,ひっくり返す処理など,全てのクライアントで同じ処理は受信時の処理に書いた方がよいです.
- 次に,PLACEの受信部分(public void run()の中のwhile文のところ)の中に,アイコンを変更する処理を以下のように書きます.
 if(theColor == myColor){
   //送信元クライアントでの処理
   buttonArray[y][x].setIcon(myIcon);
 } else {
   //送信先クライアントでの処理
   buttonArray[y][x].setIcon(yourIcon);
 }
-- theColorとmyColorを比較しています.theColorは,送信されたmyColorの情報のはずですが…ううん,どういうことでしょう?
--- 説明は下をみてみましょう.
#ref(msgothello.png,center,50%)~
CENTER:図1. 2つのMyClient.javaの送信と受信(クリックで拡大)

-- 受信部分は両方のクライアントで実行される,という話はしましたね.
-- 送信した「自分のmyColor」と,「相手のmyColor」は異なるはずです.
-- したがって,この2つの情報を比較することで,受信部分の中で
--- &color(red){両方のクライアントで行いたい処理};
--- &color(red){送信元のみで行いたい処理};
--- &color(red){送信先のみで行いたい処理};
-- を場合分けすることができます.ここがポイント!
-- あとは,送信元はmyIcon,送信先はyourIconを置く処理を書きましょう.
- 「自分のmyIcon」と「相手のyourIcon」は同じ色のはずなので,両者とも同じ画面になります.

** 課題3・ターン制にする [#sdde45f7]

- myColorと同じように,myTurnという変数を作ります.
-- 宣言するところは,myColorと同じところですね.
-- この場所で宣言すると,どこでもこの変数(ここでは,myTurn)を見る(アクセス)ことができます.
- ターンの判定方法は様々です.ここでは,例を4つぐらい挙げておきますが,1番目か2番目が分かりやすいですね.これ以降では,1番目で説明をしていきます.
-- myTurnを「0」と「1」に限定し,一方を1,他方を0で初期化する場合
--- 0なら相手のターン,1なら自分のターン
--- 0なら黒のターン,1なら白のターン
 myTurn = 1 - myTurn; // 0を1に,1を0にする
--- これをつかうと,1と0が交互に切り替わります.
-- 両者とも0から始めて,自分のターンが済んだら自分だけ+1する場合
--- 自分と相手のターン数を比較し,一致したら先攻のターン
-- 両者とも0から始めて,自分のターンが済んだら両者とも+1する場合
--- ターン数が偶数なら先攻のターン

- myTurnの初期化は,myColorの決まった後などのタイミングで行うと良いです.
-- 「0なら黒のターン,1なら白のターン」 とした場合, myTurn = 0 をmyColorがきまったところにあとに書くと自分の色(MyColor)に応じて,順番が決まりますね.
-- 「0なら相手のターン,1なら自分のターン」とした場合は,myColorによって,1か0かを変える必要がありますね.
- クリックした時に,myTurnによって処理を行う・行わないを分けてください.
-- これは,mouseClickedの部分を書き換える必要があります.
-- つまり,自分のターンのときにはクリック(コマをおける)けど,それ以外はおけないというプログラムを書いて下さい.
- 次に,クリックしたときに,myTurnを入れ替える必要があります.
-- これは,受信時に変更する必要があります.
-- つまり,コマをおいた処理をする受信部分に, myTurn = 1 - myTurn; を書く必要があります.

- ここまでが全てできると,黒の人は黒の番のときだけにおけますし,白の人は白の番の時だけにおけます.
- これがうまくいったら,[[演習4-2>演習4-2 オセロの基礎2]]に進みましょう.

&color(,yellow){myTurnのよくある間違い};
- myTurn == myColorのときに自分の番と判定すると,うまく動かない可能性があります
- なぜ,そうなるか,考えてみましょう!以下の例はよくある間違いの例です
-- 例えば,myColorを決めるときに,myColor=0の人がmyTurn=0,myColor=1の人がmyTurn=1にしているとします
-- 「myTurn == myColorのときに自分の番」と判定すると,初回はどちらとも動きます
-- 2手目は,どちらもmyTurnが異なるため,動かなくなります
-- 例えば,myTurn=1の時が自分の番ときめます
-- myColorの設定時に,黒の人には,myTurn=1,白の人は,myTurn=0とします
-- 自分の番は,myTurn == 1などで判定するとうまくいくとおもいます

#br

&size(16){[[&ref(http://yoslab.net/netprog/next.gif,nolink); 演習4-2へ>演習4-2 オセロの基礎2]]};

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   一覧 単語検索 最終更新     最終更新のRSS