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;
}
}