質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.77%

java でTCP通信を使ったマインスイーパーを作りたい。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,528
退会済みユーザー

退会済みユーザー

上記のゲームを作っています。クライアント側でゲームをしてその結果をサーバーで処理することを想定しています。

今回の問題はサーバ側でGUIを立てた時に、処理が流れてしまい、結果を入れる前の空の文字列をサーバに送ってしまいます。ゲームの終了まで通信を待機させてゲーム終了してから通信を行うようにしたいです。

以下、ソースコードになります。

package minesweeper;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;

class
MineSweeperClient
{
    public static void main(String[] args)
    {
        new MineSweeperClient();
    }

    MineSweeperClient(){//コンストラクター
        String hostname="localhost";

        Result result;
        MineThread mineThread = new MineThread();
        result = mineThread.getResult();

        doClientJob(hostname,result);
    }

    public void doClientJob(String hostname,Result result)
    {
        try {
            InetSocketAddress socketAddress =
                    new InetSocketAddress(hostname, 5002);

            //
            Socket socket = new Socket();
            socket.connect(socketAddress, 10000);

            InetAddress inadr;

            if ((inadr = socket.getInetAddress()) != null) {
                System.out.println("Connect to " + inadr);
            }else {
                System.out.println("Connection failed.");
                return;
            }

            PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader rd =
                    new BufferedReader(new InputStreamReader( socket.getInputStream()));

            writer.println(result);

            String getline=rd.readLine();
            System.out.println("you : " + getline);

            rd.close();
            writer.close();
            socket.close();

        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package minesweeper;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

class MinesweeperServer
{
    public static void main(String[] args){
        new MinesweeperServer();

    }//mainend

    MinesweeperServer(){//コンストラクター

        ServerSocket serverSoc = null;
        try {
            // ポート番号は、5000
            //ソケットを作成
            serverSoc = new ServerSocket(5002);
            boolean flag=true;

            //クライアントからの接続を待機するaccept()メソッド。
            //accept()は、接続があるまで処理はブロックされる。
            //もし、複数のクライアントからの接続を受け付けるようにするには
            //スレッドを使う。
            //accept()は接続時に新たなsocketを返す。これを使って通信を行なう。
            System.out.println("Waiting for Connection. ");
            int thcounter=0;
            while(flag){
                Socket socket=null;
                socket = serverSoc.accept();
                //accept()は、クライアントからの接続要求があるまでブロックする。
                //接続があれば次の命令に移る。
                //スレッドを起動し、クライアントと通信する。
                new SrvWorkerThread(socket,thcounter++).start();

                System.out.println("Waiting for New Connection. ");
            }//while end
        }
        catch (IOException e) {
            System.out.println("IOException!");
            e.printStackTrace();
        }
        finally{
            try{
                if (serverSoc != null){
                    serverSoc.close();
                }
            }
            catch (IOException ioex) {
                ioex.printStackTrace();
            }
        }//finally end

    }//コンストラクターMultiServerSample()end
}//class MultiServerSample end

class SrvWorkerThread extends Thread{
    private Socket soc;

    public SrvWorkerThread(Socket sct,int thcounter){

        soc=sct;
        System.out.println("Thread "+thcounter+"is Generated.  Connect to " + soc.getInetAddress());
    }

    public void run(){
        try{
            //socketからのデータはInputStreamReaderに送り、さらに
            //BufferedReaderによってバッファリングする。
            BufferedReader reader = new BufferedReader
                    (new InputStreamReader(soc.getInputStream()));
            //Clientへの出力用PrintWriter
            PrintWriter sendout = new PrintWriter(soc.getOutputStream(), true);
            //データ読み取りと表示。
            String line;
            line = reader.readLine();
            System.out.println("Message from client :" + line);

            if(line.equals("end")){//強制終了
                System.exit(1);
            }

            //Clientにメッセージ送信
            sendout.println("Message is received at Server. Thankyou! your message is ["+line+"]");

        }
        catch(IOException ioex){
            ioex.printStackTrace();
        }
        finally{
            try{
                if(soc != null){
                    soc.close();
                }
            }
            catch (IOException ioex){
                ioex.printStackTrace();
            }
        }//finall end
    }//run end
}//SrvWorkerThread end
package minesweeper;

import java.util.Timer;

public class MineThread  implements  ICallBackListener{

    Result result;

    MineThread(){
        InnerThread minesweeper= new InnerThread((ICallBackListener)this);
        minesweeper.start();
    }


    @Override
    public void printFinish(int time, int openCell, boolean isClear) {
        result = new Result(time, openCell, isClear);
    }

    class InnerThread extends Thread{
        ICallBackListener listener;

        InnerThread(ICallBackListener listener){
            this.listener=listener;
        }

        public void setICallBackListener(ICallBackListener listener){
            this.listener=listener;
        }

        public void run(){
            Mines mines = new Mines();
            mines.validate();
            printFinish(mines.getElapsedTime(), mines.getOpenCell(), mines.getIsGameClear());
        }
    }

    public Result getResult() {
        return result;
    }
}//outerclass end
package minesweeper;

public class Result {
    private int time;
    private int openCell;
    private boolean isClear;

    public Result(int time, int openCell, boolean isClear) {
        this.time = time;
        this.openCell = openCell;
        this.isClear = isClear;
    }

    public int getTime() {
        return time;
    }

    public int getOpenCell() {
        return openCell;
    }

    public boolean getIsClear() {
        return isClear;
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    退会済みユーザー

    2018/12/25 19:22

    以下の部分の補足お願いします。
    >GUIを立てた時に、処理が流れてしまい、結果を入れる前の空の文字列
    GUIをたてているのはどの関数か? 処理が流れてしまったのはどの関数か?
    結果を入れる前の空の文字列に対応する変数はどれか?

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2018/12/25 19:42

    一つ目のクライアントのソースコードを見ていただきたいのですが、クライアントのコンストラクタ内で
    String hostname="localhost";
    Result result;
    MineThread mineThread = new MineThread();
    //↑ここでGUIを組み立て、ゲームの一連の動作をスレッドとして開始している。
    result = mineThread.getResult();
    //↑これで結果を関数に詰めている。
    doClientJob(hostname,result);
    //↑ここで通信を開始している。

    この中で、ゲームが終了してから結果をクライアントに送るために、処理を止める方法を探しています。

    キャンセル

回答 2

checkベストアンサー

0

この2行追加で上手く動きますか?

MineThread mineThread = new MineThread();
mineThread.start();
mineThread.join();
result = mineThread.getResult();

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/13 18:52

    動きました。
    回答ありがとうございます。

    キャンセル

0

雑な方法ですが、

// ゲームの処理
booolean finishflag = false;
// ソケット
while( !finishflag ) Thread.sleep( 1 );
result = mineThread.getResult();


みたいにしたら、とりあえずリザルトを送るタイミングを選択できるかと。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る