@JC, I just wrote this code really quick and it does compile without errors for the server side ... but I am not sure about 1 thing .. here is the code first

import java.net.*;
import java.io.*;

public class GameServer extends Thread{
    private ServerSocket serverSocket;
    private enum Action  { Scissors, Rock, Paper;

        public int checkActions(Action action){
            int win = 1;
            int lose = -1;
            int draw = 0;
            if (this == action) return draw;

            switch (this){
                case Scissors:
                if(action == Paper) return win;
                else return lose;

                case Rock:
                if(action == Scissors) return win;
                else return lose;

                case Paper:
                if(action == Rock) return win;
                else return lose;
            }
            return 69; // Default return, will never reach it 
        }
    }
    private String inputFromUser1,inputFromUser2;

    public GameServer(int port)throws IOException{
        serverSocket = new ServerSocket(port);
    }
    public static void main(String[] args){
        int port = 9001;
        try{
            Thread t = new GameServer(port);
            t.start();
        }catch(IOException e){
            e.printStackTrace();
        }
    }

    public void run(){
        while(true){
            try{
                Socket server = serverSocket.accept();
                PrintWriter out = new PrintWriter(server.getOutputStream(), true);
                BufferedReader in = new BufferedReader(new InputStreamReader(server .getInputStream()));
                inputFromUser1 = in.readLine();
                inputFromUser2 = in.readLine();
                out.println(play(getUser1Move(),getUser2Move()));       
            } catch(IOException e){
                e.printStackTrace();
            }
        }
    }

    public String play(Action move1, Action move2) {
        int result;
        String output;
        result = move1.checkActions(move2);
        if(result==0) 
            return output = "User's move " + move1.toString() + "Computer move " 
            + move2.toString() + ", the game is: DRAW";
        else if(result==1) 
            return output = "User's move " + move1.toString() + "Computer move " 
            + move2.toString() + ", You WIN!";
        else 
            return output = "User's move " + move1.toString() + "Computer move " 
            + move2.toString() + ", You LOSE!";

    }

    public Action getUser1Move(){
        if(inputFromUser1.equals("Scissors")|| inputFromUser1.equals("Rock")|| inputFromUser1.equals("Paper")){
            switch (inputFromUser1) {
                case "Scissors":
                    return Action.Scissors;
                case "Rock":
                    return Action.Rock;
                case "Paper":
                    return Action.Paper;
            }
        }
        return getUser1Move(); //Wrong spelled or w/e, get new input
    }

    public Action getUser2Move(){
        if(inputFromUser2.equals("Scissors")|| inputFromUser2.equals("Rock")|| inputFromUser2.equals("Paper")){
            switch (inputFromUser2) {
                case "Scissors":
                    return Action.Scissors;
                case "Rock":
                    return Action.Rock;
                case "Paper":
                    return Action.Paper;
            }
        }
        return getUser2Move(); //Wrong spelled or w/e, get new input
    }
}

My doubts are about the input from users in run(), I did it this way because I think I can make it from client side so each client can send only 1 message per game, so the second input should be from second client? Does it make sense to be like this?

Recommended Answers

All 12 Replies

it does compile without errors for the server side ... but I am not sure about 1 thing ..

you do understand that mentioning what it is you have doubts about, might help us help you, right?

I did point out the thing right after the code ... :p

Okay an update ... I made the client code as well just to see if the server receives/responds to the client .. but I have problem in my run() at the server side .. having it like this

public void run(){
        while(true){
            try{System.out.println("Starting to run");
                Socket server = serverSocket.accept();
                PrintWriter out = new PrintWriter(server.getOutputStream(), true);
                BufferedReader in = new BufferedReader(new InputStreamReader(server .getInputStream()));
                System.out.println("waiting");
                inputFromUser1 = in.readLine();
                System.out.println(inputFromUser1);
                inputFromUser2 = in.readLine();
                out.print(play(getUser1Move(),getUser2Move()));
                out.flush();        
            } catch(IOException e){
                e.printStackTrace();
            }
        }
    }

It prints out "Starting to run" and I don't hear from it anymore. Any idea why would it get stucked? Basically it doesn't execute the next lives so I never see message "waiting"

Nvm found the problem of this for not getting "waiting"

Okay! Good news .. the game works BUT ... it only takes inputs from 1 user, so if I send 2 messages from 1 client, I get response back. It's some progress so far but I guess what I was afraid of at first is my problem .. back to the original post of the thread ^

Still can't figure out how to get inputs from both users and then compare those >.>

After your serverSocket.accept(); you need to start a new thread to handle that connection (pass the Socket object to the construtor of your new thread). Then in that new thread open the input & output streams etc. You main thread then loops back to the accept and waits for user2 to connect. When user2 connects you start another new thread as above. Now you have two threads. each handling the I/O from one user. Synchronising them to play the game is where this gets interesting...

um, from what I understand, this is how a new thread for each client would be started? Also, I think i'll write the inputs from users in a list and if the list has 2 answers then reply back to the clients who wins, would that work?

public void run(){
        while(true){
            try{System.out.println("Starting to run");
                Socket server = serverSocket.accept();
                (new Thread().start());
                PrintWriter out = new PrintWriter(server.getOutputStream(), true);
                BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
                System.out.println("waiting");
                input = in.readLine();
                System.out.println(inputFromUser1);
                userInputs.add(input);
                //out.print(play(getUser1Move(),getUser2Move()) + "\n");
                //out.flush();      
            } catch(IOException e){
                e.printStackTrace();
            }
        }
    }

No, it's more like (just a sketch)

 while(true){
    Socket clientSocket = serverSocket.accept();
    new ClientThread(clientSocket).start();
 }



 class ClientThread extends Thread {

    ClientThread(Socket clientSocket) {etc

    p v run() {
      PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
      BufferedReader in = new BufferedReader(new             InputStreamReader(clientSocket.getInputStream()));
      System.out.println("waiting");
      input = in.readLine();
      etc

I ran into trouble again. It seems to be working(somehow lol) but it only sends the answer of the game ending to the client that has made the last thread, I tried moving around the PrintWriter to send message with different ways but nothing really worked yet, Here's my server side code:

Note i am pointing to run() method in my inner class ClientThread

import java.net.*;
import java.io.*;
import java.util.*;
public class GameServer extends Thread{
    private ServerSocket serverSocket;
    private enum Action  { Scissors, Rock, Paper;

        public int checkActions(Action action){
            int win = 1;
            int lose = -1;
            int draw = 0;
            if (this == action) return draw;

            switch (this){
                case Scissors:
                if(action == Paper) return win;
                else return lose;

                case Rock:
                if(action == Scissors) return win;
                else return lose;

                case Paper:
                if(action == Rock) return win;
                else return lose;
            }
            return 69; // Default return, will never reach it 
        }
    }
    private String inputFromUser1,inputFromUser2, input;
    private List<String> userInputs = new ArrayList<String>();
    public GameServer(int port)throws IOException{
        serverSocket = new ServerSocket(port);
    }
    public static void main(String[] args){
        int port = 9001;
        try{
            Thread t = new GameServer(port);
            t.start();
        }catch(IOException e){
            e.printStackTrace();
        }
    }

    public void run(){
        while(true){
            try{System.out.println("Starting to run");
                Socket server = serverSocket.accept();
                new ClientThread(server).start(); 
                //System.out.println(userInputs.size());
                } catch(IOException e){
                e.printStackTrace();
            }
        }
    }

    public String play(Action move1, Action move2) {
        int result;
        String output;
        result = move1.checkActions(move2);
        if(result==0) 
            return output = "User's move " + move1.toString() + "Computer move " 
            + move2.toString() + ", the game is: DRAW";
        else if(result==1) 
            return output = "User's move " + move1.toString() + "Computer move " 
            + move2.toString() + ", You WIN!";
        else 
            return output = "User's move " + move1.toString() + "Computer move " 
            + move2.toString() + ", You LOSE!";

    }

    public Action getUser1Move(){
        inputFromUser1 = userInputs.get(0);
        if(inputFromUser1.equals("Scissors")|| inputFromUser1.equals("Rock")|| inputFromUser1.equals("Paper")){
            switch (inputFromUser1) {
                case "Scissors":
                    return Action.Scissors;
                case "Rock":
                    return Action.Rock;
                case "Paper":
                    return Action.Paper;
            }
        }
        return getUser1Move(); //Wrong spelled or w/e, get new input
    }

    public Action getUser2Move(){
        inputFromUser2 = userInputs.get(1);
        if(inputFromUser2.equals("Scissors")|| inputFromUser2.equals("Rock")|| inputFromUser2.equals("Paper")){
            switch (inputFromUser2) {
                case "Scissors":
                    return Action.Scissors;
                case "Rock":
                    return Action.Rock;
                case "Paper":
                    return Action.Paper;
            }
        }
        return getUser2Move(); //Wrong spelled or w/e, get new input
    }

    public class ClientThread extends Thread{
        Socket clientSocket;
        public ClientThread(Socket s){
            this.clientSocket = s;
        }
        public void run(){
            boolean isRunning = true;

            try{
                PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
                BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                System.out.println("waiting");
                input = in.readLine();
                System.out.println(input);
                userInputs.add(input);
                while(isRunning){
                if(userInputs.size()>=2){
                    out.print(play(getUser1Move(),getUser2Move()) + "\n");
                    out.flush();
                    userInputs.clear();
                    isRunning = false;
                }}  
            } catch(IOException e){
                e.printStackTrace();
            } 
        }
    }
}

Thats because the code that sends the result is in an if test that's only true for the second input.

I would keep references to both ClientThreads somewhere in the game, and have a public "send" method in the ClientThread class so the game can send messages to any/all clients whenever it wants. You need to break away from the "receive a line/send a line loop" thinking and allow asynchronous input and output, after all, this is all about Threads...

(edit - addedum):
This code is getting very messy because it doen't use any of Java's O.O. capabilities (except where absolutely necessary). You should be thinking about the objects in the application, and starting to partition the functionality into them. The idea is to get a number of small classes, each of which does it's own thing without worrying about the internals of any other class. The only thing that matters is the public interface for each class.
By way of illustration here's one way to approach a very first pass at this...

class Server {
   // listens for incoming connections, creates RemotePlayers
   // could also do DNS stuff to make itself discoverable
}

interface Player {
   // could be local (console or GUI), remote or computer
   // takes input from user and calls game.move(...)
   public void send(String s); // sends message to user
}
class LocalConsolePlayer implements Player {
   // (already got the code for console handling)
}    
class RemotePlayer implements Player {
   // a user who is connected via an IP socket
   ...
}
class ComputerPlayer implements Player {
   // A.I. opponent for single player fun
}

interface Game {
   // defines how Players interact with a Game
   public void addPlayer(Player p);
   public void move(Player p; String theMove);
   public String getGameState(); // for display to a user
   // can also call player.send(String s) to update user
}
class PaperScissorsRock implements Game {
   ...
}
class TicTacToe implements Game ...

Hey James, thanks for answering!
I took the advice of your post before the edit, and saving Thread instances into an array list, then looping through them and using print to return answer to the clients connected. It does work! Here's my code if anyone wants to take a look/give any suggestions to improve it. Also, thanks James for the edit, now when the console application works versus Computer and versus player/player sending IP packets, I am considering to implement a GUI, where the user can choose whether to play against pc or against another player

EDIT: Here's a picture of it running ;)

import java.net.*;
import java.io.*;
import java.util.*;
public class GameServer extends Thread{
    private ServerSocket serverSocket;
    private enum Action  { Scissors, Rock, Paper;

        public int checkActions(Action action){
            int win = 1;
            int lose = -1;
            int draw = 0;
            if (this == action) return draw;

            switch (this){
                case Scissors:
                if(action == Paper) return win;
                else return lose;

                case Rock:
                if(action == Scissors) return win;
                else return lose;

                case Paper:
                if(action == Rock) return win;
                else return lose;
            }
            return 69; // Default return, will never reach it 
        }
    }
    private String inputFromUser1,inputFromUser2, input;
    private List<String> userInputs = new ArrayList<String>();
    private ArrayList<ClientThread> alThreads = new ArrayList<ClientThread>();
    public GameServer(int port)throws IOException{
        serverSocket = new ServerSocket(port);
    }
    public static void main(String[] args){
        int port = 9001;
        try{
            Thread t = new GameServer(port);
            t.start();
        }catch(IOException e){
            e.printStackTrace();
        }
    }

    public void run(){
        while(true){
            try{System.out.println("Starting to run");
                Socket server = serverSocket.accept();
                //new ClientThread(server).start();
                ClientThread ct = new ClientThread(server);
                alThreads.add(ct);
                ct.start();

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

    public String play(Action move1, Action move2) {
        int result;
        String output;
        result = move1.checkActions(move2);
        if(result==0) 
            return output = "User's move " + move1.toString() + "Computer move " 
            + move2.toString() + ", the game is: DRAW";
        else if(result==1) 
            return output = "User's move " + move1.toString() + "Computer move " 
            + move2.toString() + ", You WIN!";
        else 
            return output = "User's move " + move1.toString() + "Computer move " 
            + move2.toString() + ", You LOSE!";

    }

    public Action getUser1Move(){
        inputFromUser1 = userInputs.get(0);
        if(inputFromUser1.equals("Scissors")|| inputFromUser1.equals("Rock")|| inputFromUser1.equals("Paper")){
            switch (inputFromUser1) {
                case "Scissors":
                    return Action.Scissors;
                case "Rock":
                    return Action.Rock;
                case "Paper":
                    return Action.Paper;
            }
        }
        return getUser1Move(); //Wrong spelled or w/e, get new input
    }

    public Action getUser2Move(){
        inputFromUser2 = userInputs.get(1);
        if(inputFromUser2.equals("Scissors")|| inputFromUser2.equals("Rock")|| inputFromUser2.equals("Paper")){
            switch (inputFromUser2) {
                case "Scissors":
                    return Action.Scissors;
                case "Rock":
                    return Action.Rock;
                case "Paper":
                    return Action.Paper;
            }
        }
        return getUser2Move(); //Wrong spelled or w/e, get new input
    }

    public class ClientThread extends Thread{
        Socket clientSocket;
        PrintWriter out;
        //try{

        //} catch(IOException e){
        //  e.printStackTrace();
        //}
        public ClientThread(Socket s){
            this.clientSocket = s;
        }
        public void run(){


            try{
                out = new PrintWriter(clientSocket.getOutputStream(), true);
                BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                System.out.println("waiting");
                input = in.readLine();
                System.out.println(input);
                userInputs.add(input);
                System.out.println(userInputs.size());
                if(userInputs.size()>1){
                    //System.out.println(play(getUser1Move(),getUser2Move()));
                    for(ClientThread t:alThreads){
                        t.print();
                    }
                    alThreads.clear();
                    userInputs.clear();             


                }

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

        public void print() throws IOException{
            //System.out.println(play(getUser1Move(),getUser2Move()));
            this.out.print(play(getUser1Move(),getUser2Move()) + "\n");
            this.out.flush();

        }
    }
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.