Newer
Older
test001 / SeaGameClient.java
@Motoki Miura Motoki Miura on 7 Aug 2020 7 KB java files
// 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