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