3

I have a simple program that allows 2 clients to connect to a server.

Once connected, They can take turns to click on the blank card image.

Once any of the 2 clients clicks on blank card image, the card image will change to Club of Ace image.

The changes will be shown on both sides of the client and click will be disabled for both clients.

After 2 seconds, it changes back to blank card image and the client is able to click again.


Problem

I am able to show the Club of Ace image on both sides after a client has clicked, but when the image changes back to blank card image after 2 seconds, I am not able to click it anymore.

This is what I have tried in my run() method(Updated)

public void run() {

    while(true) {
        try {
            while (true) {
                response = is.readLine();
                if(!response.equals("")) {
                    System.out.println(response);
                    responded = true;
                }
                break;
            }
        } catch (IOException e) {
            System.err.println("IOException:  " + e);
        }
        if(responded) {
            timer = new Timer(1000,new TimerC());
            timer.start();
            responded = false;
        }
    }
}

Here is my full code for my client. Please help

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.ImageIcon;
import javax.swing.Timer;

public class Client implements Runnable {

    static Socket clientSocket = null;
    ObjectInputStream in = null;
    String serverMsg;
    static PrintStream os = null;
    static DataInputStream is = null;
    static boolean closed = false;
    static String s = "";
    static String cardType = "";
    static GameUI gameUI;
    int countdown = 3;
    Timer timer = new Timer(1000,null);
    String response = null;
    boolean  responded = false;

    public static void main(String args[]) {
        try {
            clientSocket = new Socket("localhost", 5550);
            os = new PrintStream(clientSocket.getOutputStream());
            is = new DataInputStream(clientSocket.getInputStream());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        gameUI = new GameUI();

        gameUI.cardOne.addMouseListener(new MouseAdapter()  
        {  
            public void mouseClicked(MouseEvent e)  
            {  
                s = gameUI.cardOne.getText();

            }  
        }); 

        if (clientSocket != null && os != null && is != null) {
            try {
                new Thread(new Client()).start();
                while (!closed) {
                    os.println(s.trim());
                }

                os.close();
                is.close();
                clientSocket.close();
            } catch (IOException e) {
                System.err.println("IOException:  " + e);
            }
        }

    }

    public void run() {
        try {
            while (true && !responded) {
                response = is.readLine();
                if(!response.equals("")) {
                    System.out.println(response);
                    responded = true;
                    break;
                }
            }

        } catch (IOException e) {
            System.err.println("IOException:  " + e);
        }

        if(responded) {
            timer = new Timer(1000,new TimerC());
            timer.start();
            responded = false;
        }
    }

    class TimerC implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent event) {
            if(countdown == 0) { 
                timer.stop();
                gameUI.cardOne.setIcon(new ImageIcon(GameUI.revealCard("blank.png")));
                countdown = 3;
            }

            else {
                gameUI.cardOne.setIcon(new ImageIcon(GameUI.revealCard(response)));
                countdown--;
                System.out.println(countdown);

            }  
        }
    }
}
user2935569
  • 347
  • 2
  • 7
  • 15
  • 1
    Note: `while (true && !responded)` is the same as `while(!responded)`. – Jonny Henly Apr 23 '16 at 09:09
  • Your `run` method executes the while loop only once, you need to surround everything in your run method with another while loop that iterates until *game over*. Also you should choose to either remove that `break` after `responded = true` or change the while to `while(true)`. – Jonny Henly Apr 23 '16 at 09:14
  • @JonnyHenly I tried surrounding everything with another while loop as you suggested but once I clicked, it will be caught in an endless loop. – user2935569 Apr 23 '16 at 09:51
  • But can you click the card again? Also did you surround **everything** in your `run` method or just the `while` loop? – Jonny Henly Apr 23 '16 at 10:13
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/109985/discussion-between-user2935569-and-jonny-henly). – user2935569 Apr 23 '16 at 10:21

1 Answers1

0

For sure both client and server use buffered streams. This is nature of the socket connections. It does not send information byte by byte. It sends buffers. Your logic operates with lines, it waits for end of line character. It could be in the middle of the buffer so your program will wait till buffer is full and it could be many lines.

To eliminate this wait sending part (on both server and client) should use flush method to send data immedailtely.

In particular add one line of code on the client side

 while (!closed) {
   os.println(s.trim());
   os.flush(); // <- send immediately right now
 }

and similar on the server side if your send something from the server side.

Community
  • 1
  • 1
Alex
  • 4,457
  • 2
  • 20
  • 59