El servidor s'encarrega de gestionar les connexions dels jugadors i d'emparellar-los perquè
juguen entre ells:
El servidor espera que es connecten dos jugadors perquè comencen una partida entre ells.
Quan dos jugadors es connecten, llança un nou fil que gestiona la partida entre els dos
jugadors.
Com que és una aplicació amb múltiples clients, la gestió de cada client és independent, en el
seu propi fil d'execució. El codi font és el següent:
TicTacToeServer.java
packageud3.exercises.tictactoe.server;importjava.io.IOException;importjava.net.ServerSocket;importjava.net.Socket;importjava.util.ArrayList;importjava.util.List;importjava.util.Scanner;publicclassTicTacToeServerextendsThread{ServerSocketserver;List<TicTacToeGame>games;TicTacToeGamenextGame;booleanrunning;publicTicTacToeServer(intport)throwsIOException{server=newServerSocket(port);games=newArrayList<>();nextGame=newTicTacToeGame(0);running=true;}publicvoidclose(){running=false;this.interrupt();}/** * TODO: Execució del servidor. * <p> * El servidor accepta les connexions dels clients. * Quan dos jugadors es connecten, els emparella per començar una partida. */@Overridepublicvoidrun(){while(running){try{// TODO}catch(Exceptione){// TODO: Adaptar la excepcióSystem.err.println("Error while accepting new connection");System.err.println(e.getMessage());}}}publicstaticvoidmain(String[]args){try{Scannerscanner=newScanner(System.in);TicTacToeServerserver=newTicTacToeServer(1234);server.start();scanner.nextLine();server.close();}catch(IOExceptione){thrownewRuntimeException(e);}}}
TicTacToeServerPlayerHandler.java
packageud3.exercises.tictactoe.server;importud3.exercises.tictactoe.models.BoardChoice;importud3.exercises.tictactoe.models.TicTacToeMessage;importud3.exercises.tictactoe.models.TicTacToeMessageType;importjava.io.*;importjava.net.Socket;import staticud3.exercises.tictactoe.models.TicTacToeMessageType.*;publicclassTicTacToeServerPlayerHandler{privatefinalSocketsocket;privatefinalObjectOutputStreamout;privatefinalObjectInputStreamin;publicTicTacToeServerPlayerHandler(Socketsocket)throwsIOException{this.socket=socket;this.in=newObjectInputStream(socket.getInputStream());this.out=newObjectOutputStream(socket.getOutputStream());}publicvoidsendMessage(TicTacToeMessageTypetype,Stringmessage)throwsIOException{out.writeObject(newTicTacToeMessage(type,message));}publicvoidsendMessage(TicTacToeMessageTypetype,Stringmessage,Objectobj)throwsIOException{TicTacToeMessageticTacToeMessage=newTicTacToeMessage(type,message);ticTacToeMessage.setObject(obj);out.writeObject(ticTacToeMessage);}publicvoidsendMessage(TicTacToeMessageTypetype)throwsIOException{out.writeObject(newTicTacToeMessage(type));}publicBoardChoicegetChoice()throwsIOException,ClassNotFoundException{TicTacToeMessagereceivedMessage=(TicTacToeMessage)in.readObject();while(receivedMessage.getType()!=POST){sendMessage(ERROR,"Expected a POST message.");receivedMessage=(TicTacToeMessage)in.readObject();}return(BoardChoice)receivedMessage.getObject();}publicvoidclose()throwsIOException{this.socket.close();}}
Aquest fil s'encarrega de portar a terme la partida entre els dos jugadors connectats.
Internament, emmagatzema el tauler Board amb l'estat de la partida actual. Pregunta per torns
als jugadors per un moviment, que va actualitzant en el seu tauler. A més, comunica a cada
jugador els moviments perquè el client puga actualitzar el seu tauler.
La comunicació es gestiona mitjançant objectes TicTacToeMessage, que tenen un
TicTacToeMessageType, un missatge i un objecte.
TicTacToeGame.java
packageud3.exercises.tictactoe.server;importud3.exercises.tictactoe.models.Board;importud3.exercises.tictactoe.models.BoardChoice;importud3.exercises.tictactoe.models.TicTacToeMessageType;importjava.io.IOException;importjava.net.Socket;importjava.util.ArrayList;importjava.util.List;importjava.util.concurrent.ThreadLocalRandom;import staticud3.exercises.tictactoe.models.TicTacToeMessageType.*;publicclassTicTacToeGameextendsThread{privatefinalintid;privatefinalList<TicTacToeServerPlayerHandler>players;privatefinalBoardboard;privatebooleanfinished;privateintcurrentPlayer;publicTicTacToeGame(intid){this.id=id;this.players=newArrayList<>();board=newBoard();finished=false;}publicvoidaddPlayer(Socketclient)throwsIOException{if(players.size()<2)players.add(newTicTacToeServerPlayerHandler(client));}publicbooleanenoughPlayers(){returnplayers.size()>=2;}publicTicTacToeServerPlayerHandlergetCurrentPlayer(){returnplayers.get(currentPlayer);}publicvoidsendGlobalMessage(TicTacToeMessageTypetype)throwsIOException{for(TicTacToeServerPlayerHandlerplayer:players){player.sendMessage(type);}}publicvoidsendGlobalMessage(TicTacToeMessageTypetype,Stringmessage)throwsIOException{for(TicTacToeServerPlayerHandlerplayer:players){player.sendMessage(type,message);}}publicvoidsendGlobalMessage(TicTacToeMessageTypetype,Stringmessage,Objectobj)throwsIOException{for(TicTacToeServerPlayerHandlerplayer:players){player.sendMessage(type,message,obj);}}/** * TODO: Send the choice to all players, so they update the board. */publicvoidupdateClientBoards(BoardChoicechoice)throwsIOException{}publicvoidchangeTurn(){currentPlayer=(currentPlayer+1)%players.size();}privatevoidclose()throwsIOException{for(TicTacToeServerPlayerHandlerplayer:players){player.close();}}/** * Server side of TicTacToe game. * <p> * TODO: The server should keep track of: * - Comunication with both connected players. * - The TicTacToe Board. It should be updated given * the players choices. * - It's a turn based game. * - Winner/Loser or draw. */@Overridepublicvoidrun(){try{// TODO}catch(Exceptione){System.err.println(e.getMessage());}}}
El client es compon d'un únic fil d'execució que ha de reaccionar als missatges enviats pel
servidor i actuar en conseqüència, seguint el protocol.
TicTacToeClient.java
packageud3.exercises.tictactoe.client;importud3.exercises.tictactoe.models.Board;importud3.exercises.tictactoe.models.BoardChoice;importud3.exercises.tictactoe.models.TicTacToeMessage;importud3.exercises.tictactoe.models.TicTacToeMessageType;importjava.io.IOException;importjava.io.ObjectInputStream;importjava.io.ObjectOutputStream;importjava.net.Socket;importjava.util.Scanner;import staticud3.exercises.tictactoe.models.TicTacToeMessageType.*;publicclassTicTacToeClient{privatefinalSocketsocket;privatefinalScannerscanner;privatefinalObjectOutputStreamout;privatefinalObjectInputStreamin;privateBoardboard;privatebooleanfinished;publicTicTacToeClient(Stringhost,intport)throwsIOException{this.scanner=newScanner(System.in);this.socket=newSocket(host,port);this.out=newObjectOutputStream(socket.getOutputStream());this.in=newObjectInputStream(socket.getInputStream());this.board=newBoard();this.finished=false;}privateTicTacToeMessagereadMessage()throwsIOException,ClassNotFoundException{return(TicTacToeMessage)in.readObject();}privatevoidsendMessage(TicTacToeMessageTypetype,Stringmessage,Objectobj)throwsIOException{TicTacToeMessageticTacToeMessage=newTicTacToeMessage(type,message);ticTacToeMessage.setObject(obj);out.writeObject(ticTacToeMessage);}/** * TODO: Ask for the position where the user wants to play. * Send the user's choice to the server. */privatevoidplayMove()throwsIOException{}/** * Client-side TicTacToe game. * <p> * TODO: This method should recevie a TicTacToeMessage from the server and implement * the accions based on the message type. * */publicvoidgame()throwsIOException,ClassNotFoundException{}publicstaticvoidmain(String[]args){System.out.println("Connectant-se amb el servidor...");try{TicTacToeClientticTacToeClient=newTicTacToeClient("localhost",1234);ticTacToeClient.game();}catch(IOException|ClassNotFoundExceptione){System.err.println(e.getMessage());}}}
📌 Aquest document pot quedar desactualitzat després d’imprimir-lo. Pots consultar la versió més recent
a la pàgina web.
🌿 Abans d’imprimir aquest document, considera si és realment necessari. Redueix el consum de paper i ajuda a protegir el nostre entorn.