Online Morpion serveur

Voici le code du serveur. La version courante ne gère pas la fin de partie (victoire de l’un des joueurs ou match nul)

package net.chezdom.nouakchott.onlinemorpion;

import java.io.IOException;
import java.net.ServerSocket;

public class OMServer extends Thread {

	private static int DEFAULTPORT = 9091;
	private ServerSocket listener;
	private Player playerX=null;
	private Player playerO=null;
	private Game game=null;

	public OMServer(int port) {
		try {
			listener = new ServerSocket(port);
			System.out.println("Online Morpion Server lancé sur le port "+port);
		} catch (IOException e) {
			System.out.println("Impossible de lancer Online Morpion Server sur le port "+port);
			System.exit(0);
		}
		start();
	}
	
	public void run() {
		SocketHelper s=null;
		while (true) {
			try {
				s=new SocketHelper();
				s.open(listener.accept());
				System.out.println("Tentative de connexion d'un client");
				
				if ((playerX!=null) && (playerO!=null)) {
					System.out.println("Connexion refusée (déjà 2 joueurs)");
					s.sendMessage("FULL");
					s.close();
					s=null;
				}
				else {
					String shakehands=s.readMessage();
					if (shakehands.equals("OMCP")) {
						if (playerX==null) playerX=new Player(s,'X',this);
						else playerO=new Player(s,'O',this);
						if ((playerX!=null) && (playerO!=null))
							game=new Game(playerX,playerO);
						
					}
					else {
						s.sendMessage("ERROR");
						s.close();
						s=null;
						System.out.println("Connexion refusée : protocole incorrect");
					}
				}
					
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public void disconnect(Player p) {
		System.out.println("Deconnexion du client "+p.getMark());
		if (p==playerX) playerX=null;
		else playerO=null;
		game=null;
	}


	public static void Usage() {
		System.out.println("Usage: java OMServer [-h] [portnumber]");
		System.exit(0);
	}	
	
	public static void main(String[] args) {
		int port=DEFAULTPORT;
		if (args.length>0) {
			if ((args[0].equals("-h")) || (args.length>1)) Usage();
			try {
				port=Integer.parseInt(args[0]);
			}
			catch (NumberFormatException e) {
				Usage();
			}
		}
		new OMServer(port);
	}

}

class Game {
	private Player playerX;
	private Player playerO;
	private Player nextPlayer;
	
	private Player[] board = {
	        null, null, null,
	        null, null, null,
	        null, null, null};
	
	public Game(Player playerX, Player playerO) {
		super();
		this.playerX = playerX;
		this.playerO = playerO;
		this.playerX.setOtherPlayer(this.playerO, this);
		this.playerO.setOtherPlayer(this.playerX, this);
		nextPlayer=playerX;
		System.out.println("La partie commence");
		nextPlayer.startGame();
		nextPlayer.giveHand();
	}

	public boolean play(int sel, Player player) {
		if (board[sel]==null) {
			System.out.println("Valid move on "+sel);
			board[sel]=player;
			return true;
		}
		//System.out.println("Cell "+sel+"already in use");
		return false;
	}
	
	public void nextPlayer() {
		if (nextPlayer==playerX) nextPlayer=playerO;
		else nextPlayer=playerX;
		nextPlayer.giveHand();
	}
	
	public Player hasWinner() {
		for (int i=0;i<3;i++) {
			if ((board[i*3]!=null) && (board[i*3]==board[i*3+1]) && (board[i*3]==board[i*3+2]))
				return board[i*3]; 
			if ((board[i]!=null) && (board[i]==board[i+3]) & (board[i]==board[i+6]))
				return board[i];
			if ((board[4]!=null) && (board[0]==board[4]) & (board[4]==board[8]))
				return board[4];
			if ((board[4]!=null) && (board[2]==board[4]) & (board[4]==board[6]))
				return board[4];
		}
		return null;
	}

	public boolean isTie() {
		for (int i=0;i<9;i++)
			if (board[i]==null) { System.out.println(i);return false;}
		return true;
	}
}

class Player extends Thread {
    private char mark;
    private SocketHelper socket;
    private boolean alive;
    private OMServer server;
    private String playerName = "Unknown";
    private String otherPlayerName = "Unknown";
    private Player otherPlayer=null;
    private Game game;
    
    public Player(SocketHelper socket, char mark, OMServer server) {
        this.socket = socket;
        this.mark = mark;
        this.server = server;
        System.out.println("Player "+mark+" connecté");
		socket.sendMessage("WELCOME "+mark);
		alive=true;
		start();
    }
    
    public char getMark() {
		return mark;
	}
        
	public String getPlayerName() {
		return playerName;
	}

	public void setOtherPlayer(Player otherPlayer, Game game) {
		this.otherPlayer = otherPlayer;
		this.game=game;
		this.otherPlayerName = otherPlayer.getPlayerName();
		socket.sendMessage("OTHERNAME "+otherPlayerName);
	}
	
	public void setOtherPlayerName(String otherPlayerName) {
		this.otherPlayerName = otherPlayerName;
		socket.sendMessage("OTHERNAME "+otherPlayerName);
	}

	public void otherPlayerCancel() {
		socket.sendMessage("OTHERCANCEL");
		otherPlayer=null;
		otherPlayerName="Unknown";
	}

	public void startGame() {
		socket.sendMessage("START");
		otherPlayer.socket.sendMessage("START");
	}
	
	public void giveHand() {
		socket.sendMessage("HAND");
	}
	
	public void run() {
    	while (alive) {
    		String answer=socket.readMessage();
    		if (answer!=null) {
    			System.out.println("RECU "+answer+" DE "+mark);
    			if (answer.equals("CANCEL")) {
    				// Deconnection du joueur, abandon de la partie, libération d'une place
    				if (otherPlayer!=null) otherPlayer.otherPlayerCancel();
    				server.disconnect(this);
    				alive=false;
    			} else if (answer.startsWith("NAME")) {
    				playerName=answer.substring(5);
    		        System.out.println("Player "+mark+" name : "+playerName);
    		        if (this.otherPlayer!=null) this.otherPlayer.setOtherPlayerName(playerName);
    			} else if (answer.startsWith("PLAY")) {
    				// Le joueur a cliqué sur une case
    				int sel=Integer.parseInt(answer.substring(5));
    				if (game.play(sel,this)) {
    					socket.sendMessage("VALID");
    					otherPlayer.socket.sendMessage("OTHERPLAY "+sel);
    					if (game.hasWinner()!=null) {
    						socket.sendMessage("WIN");
    						otherPlayer.socket.sendMessage("LOST");
    					} else if (game.isTie()) {
    						socket.sendMessage("TIE");
    						otherPlayer.socket.sendMessage("TIE");
    					} else
    						game.nextPlayer();
    				} else 
    					socket.sendMessage("WRONG");
    			}
    		}
    	}
    	socket.close();
    }
}

Le serveur utilise la classe outil SocketHelper suivante pour encapsuler la gestion des sockets. Vous pouvez utiliser cette classe aussi pour le client.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class SocketHelper {
	private Socket socket;
	private BufferedReader input;
	private PrintStream out;
	private String errorMessage;
	
	public boolean open(Socket socket) {
		this.socket=socket;
		return openStreams();
	}
	
	public boolean open(String server, int port) {
		try {
			socket=new Socket(server,port);
		} catch (UnknownHostException e) {
			socket=null;
			errorMessage="Serveur inconnu";
		} catch (IOException e) {
			socket=null;
			errorMessage="Impossible d'établir la connexion avec "+server+"sur le port "+port;
		}

		if (socket==null) return false;
		return openStreams();
	}
	
	public boolean openStreams() {
		if (socket==null) return false;
		
		try {
			input=new BufferedReader(new InputStreamReader(socket.getInputStream()));
			out=new PrintStream(socket.getOutputStream());
		} catch (IOException e) {
			try {
				socket.close();
			} catch (IOException e1) {/*Nothing to do here*/}
			socket=null;
			errorMessage="Impossible d'ouvrir les flux d'E/S.";
			return false;
		}

		return true;
	}
	
	public void close() {
		try {
			input.close();
			out.close();
			socket.close();
		} catch (IOException e) {
			System.err.println("Cannot close socket!");
			/*Nothing to do here*/}
		socket=null;
	}
	
	public boolean isConnected() {
		return socket!=null;
	}
	
	public String getErrorMessage() {
		return errorMessage;
	}

	public boolean sendMessage(String msg) {
		if (socket==null) return false;
		out.println(msg);
		return true;
	}
	
	public String readMessage() {
		if (socket==null) return null;
		String answer=null;
		try {
			answer = input.readLine();
		} catch (IOException e) {
			answer=null;
		}
		return answer;
	}
}

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *