[[TopPage]] > [[演習課題]] > 演習3-2 ネットワーク対戦ゲームクライアント * ネットワーク対戦ゲームクライアントの作成 [#rc5dd636] まず,下記のプログラムと画像3枚を同じフォルダにダウンロードしてください. &ref(MyClient.java,,,MyClient.java ダウンロード);/[[ソースコードファイルを見る>http://yoslab.net/netprog/source/MyClient.java]] 画像ファイルの保存は,画像ファイル上で右クリックし&color(red){「名前をつけて画像を保存」};をクリックします.~ ★保存先のフォルダが変わっている場合がありますので,注意してください. &ref(White.jpg); ... White.jpg~ &ref(Black.jpg); ... Black.jpg~ &ref(GreenFrame.jpg); ... GreenFrame.jpg~ ※サーバは,演習3-1でダウンロードした''MyServer.java''を使います. ** プログラムの実行 [#lf76b5e0] 接続を確認するために,コマンドプロンプトを3つ起動させます. - 一つのコマンドプロンプトで,MyServer.javaを起動させます. - あとの二つのコマンドプロンプトで,MyClient.javaを起動させます. - MyClientに表示されたコマを動かしてください.もう一方のクライアント画面にあるコマも動きましたよね? -- 動かない場合は,MyServer.javaのコンパイルからやり直してみてください. #ref(multimove.png,nolink,center)~ CENTER:図1. 2つのMyClient.java ** プログラム(MyClient.java)の解説 [#a545d56e] MyClient.javaは大きく4つの部分に分かれています. + MyClient~ ここは,MyClient()が起動したときに,最初に動く(実際はmain()が最初ですが,main()の中で最初に呼ばれている)部分です. -- 名前の入力ダイアログの表示 -- メインのウィンドウの表示 -- サーバへの接続~ を行います. + MesgRecvThread~ MyClient.javaでいつも動いている(監視している)ところは,この部分です. 具体的には「public void run()」が,プログラムの起動中ずーーっと動作をしています. + main~ 起動時には,ここの関数が呼ばれますが,実際には,すぐに,MyClientが呼び出され,その中で,MesgRecvThreadが呼び出されています. + マウスイベント部(mouseClicked,mouseEntered,mouseExited,mousePressed,mouseReleased,mouseDragged,mouseMoved)~ マウスでオブジェクトに何かしたときに,発生します. このマウスの処理に応じたプログラムを書くことで,何かできます.~ 上記のプログラムでは,mouseDraggedとmouseClickedに処理を記述しています. ** プログラムの改良 [#haf84ef4] プログラムの改良を通じて,動きを理解しましょう.''しっかり読むことが重要です!!'' *** 改良1 - 複数のPC間で通信できるようにしましょう. [#h8ecac89] いずれ複数のPCを使ってテストするためにも,%%%先にやっておきましょう%%%.やり方はいくつかありますが,例えば下記の方法があります. -- 名前の入力ダイアログのあとに,%%%「サーバのIPアドレス」の入力のためのダイアログを表示し,IPアドレスを入力%%%させます. -- IPアドレスが空の場合には,%%%''"localhost"''(自分のPCのサーバ)に接続します.それ以外は,入力したサーバに接続します%%%. --- "localhost"は,IPアドレス127.0.0.1(自分のPC)を表す特別な名前です. --- 自分のPCへのアクセスという操作はよくあるため,覚えやすい"localhost"という名前が付けられています. -- この方法ではPCが最低2台必要になります.1台はサーバとクライアントが動作しており,もう一台は,クライアントだけ動作しています.~ &br; PCのUPアドレスの調べ方は,IPアドレスを調べる方法を見てください.」 &br; 複数のPC間で通信テストをやりたい場合,[[Q&A>Q&A#bf9593c6]]を参考にしてください. &color(,yellow){ヒント};: - 名前ダイアログを出すプログラムが,MyClientのどこかにあります. -- それを参考にIPアドレスダイアログを出すようにしましょう. - %%%入力で得られた変数をどこで用いるか%%%,についても考える必要があります. -- "localhost"にしか接続できない状況を変更して,入力内容に従うようにしましょう. - 通信できるかどうかのチェックはIPアドレスを調べる方法や[[Q&A>Q&A#bf9593c6]]を参考に. &color(,yellow){ポート番号とは};: - ポート番号とは,TCP/IPを用いた通信において,プログラムを区別するための番号です. - 同じ番号同士で通信をします. - 今回のサンプルでは,10000番をしています.0番〜65535番までつかえますが,0-1023番までは,ウェルノウンポートという番号で,特定のサービスに予約されています. &color(,yellow){失敗例(MyServerが起動しない!)};: - 「ソケットへの接続エラー」のようなエラーメッセージがでます. - 「ソケット」というのは,インターネット(TCP/IP)の考え方の一つです. - エラーの原因ですが,「MyServer」が2つ立ち上がっていませんか? - MyServerは,サーバーです.特定のポート(このプログラム例では,10000番ポートで待ちます) - すでに先に一つのMyServerが立ち上がっていると,もう一つのMyServerは起動時に,すでにポートが使われているためにエラーとなります! &br; *** 改良2 - 特定の番号のコマは動かないようにしてみましょう. [#led7117f] 例えば,配列の1番目だけは,動かないようにしてみましょう.mouseDraggedのところの,theArrayIndex(ボタン番号)をうまく使います. &br;&br; &color(,yellow){ヒント1};: - theArrayIndexは文字列なので,比較する時は注意してください. &color(,yellow){ヒント2};: - 配列の0番目は動かない=配列の0番目以外は動く とかけばいいですね! &color(,yellow){ヒント3};:下記のプログラムは,0以外の場合には,x=x+1;が動く例です. if(x != 0){ x = x + 1; } &br;&br; *** 改良3 - 自動的に,黒と白を決めてみましょう. [#w37c0d86] &size(18){※この課題では,演習3-1-1の練習問題で作成した&color(red){MyServer2.java};を使います!!}; #br MyServer2では,演習3-1-1の練習問題(MyServer2.java)では,接続してきたクライアントに対して, 1 と接続番号を送信していますね.~ この接続番号「1」(2回目は2,3回目は3...)の数字を使うと例えば,偶数は黒,奇数は白とすると,つないだプログラムごとに黒と白が判定できます. #br MyClientの受信部分は public void run() です.そこで, out.println(myName);//名前を送る の後に, String myNumberStr = br.readLine(); を追加します. これで,サーバが送った番号を受け取れますが,このままだとまだ,単なる文字なので, Integer.parseIntを使って数値にします. &br; また,この数値を奇数が偶数かを判定するには, %(モジュロ)演算子を使います. &br; 例えば,下記は偶数の時にif文の条件を満たします. if(myNumberInt % 2 == 0){ } 自分が黒か白かの情報は,他の場所でも使いますので,どこでも使えるように, public class MyClient extends JFrame implements MouseListener,MouseMotionListener { private JButton buttonArray[]; のようなところに, private int myColor; と宣言しておいて, -myNumberIntが偶数のときはmyColorを0(黒)にする -myNumberIntが奇数のときはmyColorを1(白)にする などと決めておくと良いでしょう. &br; これで,プログラム中のどこでも自分の色を参照できるようになります. 試しに,コマをクリックしたら,myColorの色に変えるよう修正してください. &br; &color(,yellow){もう少し改良!};:これまでの改良では,特に画面上に変化はありませんので,もう一つ改良します. コマをクリックしたら,myColorの色に変えるよう修正してください.~ この修正は, public void mouseClicked(MouseEvent e) の中を修正します. 最初のmouseClickedのプログラムは,白がおかれていたら,黒に, それ以外が置かれていたら,白にするプログラムです. そのプログラムを,白の人は白だけ,黒の人は黒だけおけるように修正してください.~ 先ほど作成した,myColorを使って,if文を書いてみましょう. 修正ができたら,実行してみて,~ 一方のMyClientは黒だけしかおけないことを~ 一方のMyClientは白だけしかおけないことを確認してください.~ *** 改良4 - 自分のコマをクリックしたときに,相手のコマも変わるようにしましょう. [#gfbbac92] 現在は,コマをクリックしたら,自分のコマしか色が変わりません. まず,''(1)mouseClicked''のところで,mouseDraggedの中身を参考にしながら送信部分を作ります.~ mouseDraggedの中身を参考にしてください.~ mouseDraggedの中身をみるとわかるのですが,~ (1)自分自身の設定する~ (2)相手(サーバ経由で相手に)にその情報を送る~ という流れです.~ mouseDraggedの場合は,移動先の座標を計算して, その座標を,サーバに送っています. mouseClickedの場合には,まず,自分のコマを置いて, そのコマの位置と色をサーバにおくるという形にすればよいです. では実際に書いてみましょう.~ mouseClickedを見ると,すでにひっくり返す部分は書き終わっていますね.~ あとはサーバに送るところを書くだけです.~ ここでは,「MOVE」の代わりに「PLACE」(コマを置く)という命令を出してみましょう.~ MOVEでは位置を送信情報としていますが,ここでは自分の色(myColor)を送る必要があります. 次に,''(2)MesgRecvThreadのrun()''の中に,if(cmd.equals("MOVE")){...という部分がありますね.~ この中身を参考にしましょう.「PLACE」の命令を受け取った場合を考え,このif文の中に,コマの色を変えるプログラムを書きます.~ ここに書くのは,%%%情報を送った自分も,受け取った相手も動作する%%%内容です.要注意ですよ! 今から書くのは,PLACEなので,コピーしたif文のMOVEをPLACEにしましょう.~ 次に,送信したmyColorを受け取る部分が必要です.~ int x = を int theColor = として,myColorをうけとりましょう.~ ここで,int myColorとすると,おかしなことになるので,しないように注意してください.~ 次に,buttonArrayに送られた色のコマを設定しましょう.~ if文で書くと,色に応じて変更できますね. &ref(サーバとクライアントの関係_key_pdf__page_1_of_2_.jpg,,75%);~ 図.MyClientからMyServerへの流れ1(プログラム) &ref(サーバとクライアントの関係_key_pdf__page_2_of_2_.jpg,,75%);~ 図.MyClientからMyServerへの流れ2(プログラムのイメージ) &color(,yellow){ヒント};: - 通信相手には"文字列"(msg)の情報しか送れません. -- したがって,msgに入れられる情報は"文字列"か"数字(の文字列)"に限られます. -- "MOVE 2 23 27"という文字列からは,1個の文字列と3個の数字の情報が得られますね. 下記を忘れるとサーバーにデータを送られないので,忘れないように. //サーバに情報を送る out.println(msg);//送信データをバッファに書き出す out.flush();//送信データをフラッシュ(ネットワーク上にはき出す)する &br; - (1)の送信部分では,クリックした直後の処理と送信情報の準備・送信を行います.~ - (2)の受信部分では,送信で受け取った情報を使って,&size(18){&color(red){両方のクライアントで};};処理を行います. 以上から,ネットワークを利用したプログラミングでは,書きたい操作が - &color(red){%%%相手の画面にも反映させたい場合%%%→受信部分に書く}; - &color(red){%%%自分の画面のみに反映させたい場合%%%→送らず,その場で書く}; とする必要がある,ということですね.詳しい動きは,[[演習4-1>演習4-1 オセロの基礎1]]も参考にしてください. &br; *** 補足 [#pb140054] MyServer.javaには,接続数の制限があります.つまり接続数が100を超えるとサーバが止まってしまいます.~ maxConnection = 100で制限していますので,気になる人は数を増やしておくと良いでしょう. ※本来なら,socketは使い回せるのですが,プログラムの簡略化のため,このような書き方をしています. #br なお,MyClientの名前は変えても構いませんが,ファイル名を変えるとプログラムの中も変える必要があります.~ ある程度動いたら,名前を変えたり,バックアップをとったりすると,あとで動かなくなったときに,おかしいところを探すのに便利です. ※配布しているソースコードに記述してある「マウスが入った」などの表示を止めたいとき… -演習2-2 イベント処理を参考にしてみてください. -全部消してしまう(コメントアウトも)と,&color(red){エラーが出ます};. #br &color(,yellow){バックアップのコツ};: - ちゃんと動いているプログラムを大きく変更するときには,バックアップを取っていると便利です. - ただし,Javaは,ファイル名を変更すると,なかのクラス名の変更も必要になります.ですので,フォルダに入れる形にしましょう. - フォルダ名は日付やファイル名,バージョンなどで区別すると,いいと思います. &size(16){[[&ref(http://yoslab.net/netprog/next.gif,nolink); 演習ページ>演習課題]]};