package j7; // File: SeaGameClient.java // 海ゲームのクライアントプログラム // Usage: java SeaGameClient // 起動してloginボタンを押すと,接続先サーバの名前や利用者の名前を問い合わせてくる // サーバ名と利用者名を入力する // 続いてOK ボタンを押すと,ポート番号10000 番でサーバと接続 // // プログラムを停止するにはlogout ボタンを押す import java.awt.*; // グラフィックス import java.awt.event.*;// イベント関連 import java.net.*; // ネットワーク関連 import java.io.*; import java.util.*; public class SeaGameClient implements Runnable { Frame f;// クライアント情報表示用ウィンドウ Panel p;// 上下左右の移動ボタンと海の状態を表示するパネル Canvas c;// 海の状態を表示するキャンバス //--------------------------------------------------------------------- // GUI 画面の初期配置 public SeaGameClient () { Button b; f = new Frame();//クライアント情報ウィンドウ全体の表示 p = new Panel();//海表示部分と操作ボタンの表示 p.setLayout(new BorderLayout()); // upボタンの作成 b = new Button("up"); b.addActionListener(new ActionListener(){ // upボタンが押されたらupコマンドを送信 public void actionPerformed(ActionEvent e){ sendCommand("up"); } }); p.add(b, BorderLayout.NORTH); // leftボタンの作成 b = new Button("left"); b.addActionListener(new ActionListener(){ // leftボタンが押されたらleftコマンドを送信 public void actionPerformed(ActionEvent e){ sendCommand("left"); } }); p.add(b, BorderLayout.WEST); // rightボタンの作成 b = new Button("right"); b.addActionListener(new ActionListener(){ // rightボタンが押されたらrightコマンドを送信 public void actionPerformed(ActionEvent e){ sendCommand("right"); } }); p.add(b, BorderLayout.EAST); // downボタンの作成 b = new Button("down"); b.addActionListener(new ActionListener(){ // downボタンが押されたらdownコマンドを送信 public void actionPerformed(ActionEvent e){ sendCommand("down"); } }); p.add(b, BorderLayout.SOUTH); // 海上の様子を表示するCanvasを作成 c = new Canvas(); c.setSize(256,256);// 大きさの設定 // フレームに必要な部品の取り付け p.add(c); f.add(p); // フレームfにloginボタンの取り付け b = new Button("login"); b.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ // loginボタンが押された場合の処理 // サーバがセットされていなければlogin処理 if(server == null) login(); } }); f.add(b,BorderLayout.NORTH); // フレームfにlogoutボタンの取り付け b = new Button("logout"); b.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ logout(); } }); f.add(b,BorderLayout.SOUTH); // フレームfを表示します f.setSize(335,345); f.setVisible(true); } // end of SeaGameClient //-------------------------------------------------------------------- // runメソッド/ 500ミリ秒ごとに画面を更新 public void run(){ while (true){ try { Thread.sleep(500); }catch(Exception e){ } // repainメソッドを用いて,サーバ上の情報を画面に出力します repaint(); } } // end of run //--------------------------------------------------------------------- // login処理関連のオブジェクト int sx = 100; int sy = 100; TextField host, tf_name; Dialog d; //--------------------------------------------------------------------- // loginウィンドウを表示し,必要な情報を得る // 実際のlogin処理は,realLoginメソッド void login(){ // ウィンドウの表示とデータの入力 d = new Dialog(f, true); host = new TextField(10) ; tf_name = new TextField(10) ; d.setLayout(new GridLayout(3,2)); d.add(new Label("host:")); d.add(host); d.add(new Label("name:")); d.add(tf_name); Button b = new Button("OK"); b.addActionListener(new ActionListener(){ // 入力が完了したら,readlLoginメソッドを使ってサーバにloginします public void actionPerformed(ActionEvent e){ realLogin(host.getText(), tf_name.getText()); d.dispose(); } }); d.add(b); d.setResizable(true); d.setSize(200, 150); d.setVisible(true); (new Thread(this)).start(); } // end of login //--------------------------------------------------------------------- // realLogin関連のオブジェクト Socket server;// ゲームサーバとの接続ソケット int port = 10000; // 接続ポート BufferedReader in; // 入力ストリーム PrintWriter out; // 出力ストリーム String name; // ゲーム参加者の名前 //--------------------------------------------------------------------- // サーバへのログイン処理 void realLogin(String host, String name){ try { // サーバとの接続 this.name = name; server = new Socket(host, port); in = new BufferedReader(new InputStreamReader( server.getInputStream())); out = new PrintWriter(server.getOutputStream()); // loginコマンドの送付 out.println("login " + name); out.flush(); repaint(); } catch(Exception e) { e.printStackTrace(); System.exit(1); } } // end of realLogin //--------------------------------------------------------------------- // サーバからのログアウト void logout(){ try { // logoutコマンドの送付 out.println("logout"); out.flush(); server.close(); }catch (Exception e){ ; } System.exit(0); } // end of logout //--------------------------------------------------------------------- // サーバからゲームの情報を得て,クライアントの画面再描画 void repaint(){ // サーバにstatコマンドを送付し,盤面の様子などの情報を取得 out.println("stat"); out.flush(); try { String line = in.readLine();// サーバからの入力の読み込み Graphics g = c.getGraphics();// Canvas cに海の様子を表示 // 海の描画 (青い四角形) g.setColor(Color.blue); g.fillRect(0, 0, 256, 256); //ship_infoから始まる船の情報の先頭行を探す while (!"ship_info".equalsIgnoreCase(line)) line = in.readLine(); // 船の情報ship_infoの表示 // ship_infoはピリオドのみの行で終了 line = in.readLine(); while (!".".equals(line)){ StringTokenizer st = new StringTokenizer(line); String obj_name = st.nextToken().trim(); // 名前を読み取ります // 自分の船は赤(red)でし,他人の船は緑(green)で表示 if (obj_name.equals(name)) //自分の船 g.setColor(Color.red); else // 他人の船 g.setColor(Color.green); // 船の位置座標を読み取る int x = Integer.parseInt(st.nextToken()) ; int y = Integer.parseInt(st.nextToken()) ; g.fillOval(x - 10, 256 - y - 10, 20, 20); // 船を表示 g.drawString(st.nextToken(),x+10,256-y+10) ; // 得点を船の右下に表示 g.drawString(obj_name,x+10,256-y-10) ; // 名前を船の右上に表示 line = in.readLine(); } // end while (!".".equals(line)) // energy_infoから始まる,燃料タンクの情報の待ち受け while (!"energy_info".equalsIgnoreCase(line)) line = in.readLine(); // 燃料タンクの情報energy_infoの表示 line = in.readLine(); while (!".".equals(line)){ // ピリオドのみの行でない間,繰り返す StringTokenizer st = new StringTokenizer(line); // 燃料タンクの位置座標を読み取る int x = Integer.parseInt(st.nextToken()) ; int y = Integer.parseInt(st.nextToken()) ; // 燃料タンクを白抜きの赤丸で示す g.setColor(Color.red); g.fillOval(x - 5, 256 - y - 5, 10, 10); g.setColor(Color.white); g.fillOval(x - 3, 256 - y - 3, 6, 6); line = in.readLine(); } // end while (!".".equals(line)) } catch (Exception e) { e.printStackTrace(); System.exit(1); } } // end of repaint //--------------------------------------------------------------------- // サーバへコマンドを送信 void sendCommand(String s){ if ("up".equals(s)){ out.println("up"); }else if ("down".equals(s)){ out.println("down"); }else if ("left".equals(s)){ out.println("left"); }else if ("right".equals(s)){ out.println("right"); } out.flush(); } // mainメソッド // SeaGameClientを起動します public static void main(String[] arg){ new SeaGameClient(); } } // end of class SeaGameClient