Minggu, 09 Juni 2013

tugas besar client server "membuat game domino"

coding :

package game;

import game.exceptions.InvalidFaceValueException;
import game.exceptions.InvalidNumberOfPlayersException;
import game.exceptions.InvalidPieceToPlayException;
import game.exceptions.NotPlayersTurnException;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.List;

import server.Server;
import client.Client;
import client.ClientRemote;
import game.Board;
import game.Domino;

public class Game {
        public static final int NUMBER_OF_MESSAGES_PER_GAME = 3;
     
        public static final int NUMBER_OF_PLAYERS = 4; // numero de jogadores total por jogo. deve ser um múltiplo de 2
        private static final int CURR_PLAYER_UNDEFINED = -1;
     
        private List<Domino> dominoes;
        private List<Player> players; // jogadores do jogo
        private Board board; // mesa do jogo (situação atual das peças jogadas
        private int currentPlayer = CURR_PLAYER_UNDEFINED; // jogador atual
        private Domino firstPiece = null;

        private Server server;
             
        // Players can be added to the game all in one time by the Game object constructor
        public Game(List<Player> players, Server server) throws InvalidNumberOfPlayersException {
                this.server = server;
             
                if (players == null || players.size() != NUMBER_OF_PLAYERS) {
                        throw new InvalidNumberOfPlayersException();
                }
             
                List<Player> tempPlayers = new ArrayList<Player>();
                for (Player p: players) {
                        p.setCurrentGame(this);
                        tempPlayers.add(p);
                }
             
                // sorteando a ordem dos jogadores, o jogador de indice 0 será parceiro do jogador de indice 2, e o 1 do 3
                this.players = new ArrayList<Player>();
                for (int i = 0; i < NUMBER_OF_PLAYERS; i++) {
                        this.players.add(tempPlayers.remove((int) (Math.random() * (NUMBER_OF_PLAYERS - i))));
                }
             
                this.board = new Board();
        }
     
        public void startGame() throws RemoteException {              
                // Creating game pieces
                createDominoPieces();
             
                System.out.println("Existem " + players.size() + " Jogadores no jogo sendo iniciado.");
                             
                // ramdom dominoes to decide players pieces
                for (int i = 0; i < NUMBER_OF_PLAYERS; i++) {
                        List<Domino> pieces = new ArrayList<Domino>();
                     
                        for (int j = 0; j < 6; j++) {
                                int index = (int) (Math.random() * (28 - (i * 6 + j)));
                                pieces.add(dominoes.remove(index));                          
                        }
                        players.get(i).setPieces(pieces);
                }

                // decidindo quem sera o primeiro jogador (encontrar o dozão ou outra carroça)
                currentPlayer = CURR_PLAYER_UNDEFINED;
                int firstPiece = 6;
                this.firstPiece = null;
                do {
                        for (Player p: players) {
                                for (Domino d: p.getPieces()) {
                                        if (d.getFace1() == firstPiece && d.getFace2() == firstPiece) {
                                                currentPlayer = players.indexOf(p);
                                                this.firstPiece = d;
                                                break;
                                        }
                                }
                                if (currentPlayer != CURR_PLAYER_UNDEFINED) break; // já foi  encontrado o jogador que ira iniciar
                        }
                        firstPiece--; // procurar por uma carroça de menor valor
                } while (currentPlayer == CURR_PLAYER_UNDEFINED && firstPiece >= 0);
                if (currentPlayer == CURR_PLAYER_UNDEFINED) currentPlayer = 0;
             
                waitForPlayersToBeReady();
             
                // enviar uma mensagem a cada jogador, indicando que um jogo está sendo iniciado
                for (Player p: players) {
                        p.getStub().receiveMessage("Game", "O jogo está sendo iniciado.");
                }
             
                // setando os parceiros dos jogadores, e chamando o método remoto em cada jogador para iniciar o jogo
                List<String> playersNames = new ArrayList<String>();
                for (int i = 0; i < players.size(); i++) {
                        playersNames.add(players.get((currentPlayer + i) % NUMBER_OF_PLAYERS).getUserName());
                }
                if (NUMBER_OF_PLAYERS % 2 == 0) {
                        for (int i = 0; i < NUMBER_OF_PLAYERS / 2; i++) {
                                Player p = players.get(i);
                                p.setPartner(players.get(i + NUMBER_OF_PLAYERS / 2).getUserName());
                                p.getStub().startGame(playersNames, p.getPieces());
                             
                                p = players.get(i + NUMBER_OF_PLAYERS / 2);
                                p.setPartner(players.get(i).getUserName());
                                p.getStub().startGame(playersNames, p.getPieces());
                        }    
                }
             
                refreshPlayersTurns();
        }
     
        private void createDominoPieces() {
                dominoes = new ArrayList<Domino>();
                for (int i = 0; i <= 6; i++) {
                        for (int j = i; j <= 6; j++) {
                                try {
                                        dominoes.add(new Domino(i, j));
                                } catch (InvalidFaceValueException e) {
                                        e.printStackTrace();
                                }
                        }
                }
        }
     
        private void waitForPlayersToBeReady() throws RemoteException {
                for (Player p: players) {
                        String service = Client.SERVICE_NAME_PREFIX + p.getUserName();                
                        Registry registry = LocateRegistry.getRegistry();
                     
                        ClientRemote stub = null;
                        int i = 0;
                        do {
                                try {
                                        stub = (ClientRemote) registry.lookup(service);
                                        System.out.println("O Servico remoto do jogador " + p.getUserName() + " esta pronto.");
                                } catch (NotBoundException e) {
                                        System.out.println("O Jogador " + p.getUserName() + " ainda não inicializou o serviço remoto");
                                        try {
                                                Thread.sleep(500);
                                                i++;
                                        } catch (InterruptedException e1) {
                                                e1.printStackTrace();
                                        }
                                }    
                        } while (stub == null || i >= 20);
                     
                        if (i >= 20) removePlayer(p);
                     
                        p.setStub(stub);
                }
        }
     
        public void makeMove(Player p, Domino d, int position) throws NotPlayersTurnException, InvalidPieceToPlayException {
                if (players.get(currentPlayer).equals(p)) {
                        if (d != null) {
                                if (board.isAValidPieceToPlay(d, position)) {
                                        board.addPiece(d, position);
                                        players.get(currentPlayer).getPieces().remove(d);
                                        currentPlayer = (currentPlayer + 1) % NUMBER_OF_PLAYERS;
                                } else {
                                        throw new InvalidPieceToPlayException();
                                }
                        } else {
                                currentPlayer = (currentPlayer + 1) % NUMBER_OF_PLAYERS;
                        }
                             
                        for (Player player: players) {
                                if (!player.equals(p)) {
                                        try {
                                                player.getStub().moveMade(d, position);
                                        } catch (RemoteException e) {
                                                removePlayer(player);
                                                return;
                                        }
                                }
                        }
                     
                        // TODO verificar se o jogo terminou
                        if (p.getPieces().size() == 0) {
                                // o jogador bateu: finalizar o jogo
                                playerWon(p);
                                return;
                        } else {
                                boolean finalized = true;
                                for (Player pTemp: players) {
                                        for (Domino dTemp: pTemp.getPieces()) {
                                                if (board.isAValidPieceToPlay(dTemp, Board.POSITION_START) || board.isAValidPieceToPlay(dTemp, Board.POSITION_END)) {
                                                        finalized = false;
                                                        break;
                                                }
                                        }
                                        if (!finalized) break;
                                }
                                if (finalized) {
                                        countPiecesPoints();
                                        return;
                                }
                        }
                     
                        // iniciando em uma nova Thread para poder retornar sem ficar bloqueado
                        new Thread() {
                                public void run() {
                                        refreshPlayersTurns();                                        
                                }
                        }.start();
                     
                } else {
                        throw new NotPlayersTurnException();
                }
        }
     
        private void refreshPlayersTurns() {
                // chamando o método para que os jogadores iniciem as jogadas
                PlayerThread t = null;
                for (int i = 0; i < NUMBER_OF_PLAYERS; i++) {
                        if (i == currentPlayer) {
                                // iniciando uma nova thread, para que a atual (do jogo) não fique bloqueada
                                t = new PlayerThread(players.get(i)) {                                
                                        public void run() {
                                                try {
                                                        p.getStub().myTimeToPlay();
                                                } catch (RemoteException e) {
                                                        remoteExceptionThrowed = true;
                                                }    
                                        }
                                };
                                t.start();
                        } else {
                                try {
                                        players.get(i).getStub().waitAnotherPlayersMove();
                                } catch (RemoteException e) {
                                        removePlayer(players.get(i));
                                        return;
                                }
                        }
                }
             
                if (t != null) {
                        if (t.isRemoteExceptionThrowed()) {
                                removePlayer(players.get(currentPlayer));
                                return;
                        } else {
                                while (t.getState() != Thread.State.TERMINATED) {
                                        try {
                                                Thread.sleep(300);
                                        } catch (InterruptedException e) {
                                                e.printStackTrace();
                                        }
                                }
                        }
                }
        }
     
        // retorno o numero de caracteres máximo de uma mensagem, dada a quantidade de mensagens ainda disponíveis
        public static int getNumberOfCharsByAvailableMessages(int availableMessages) {
                int maximumNumberOfChars = 10;
             
                if (availableMessages <= NUMBER_OF_MESSAGES_PER_GAME && availableMessages >= 0) {
                        return maximumNumberOfChars - (NUMBER_OF_MESSAGES_PER_GAME - availableMessages) * 2;
                }
             
                return 0;
        }

        public boolean isAValidPieceToPlay(Domino d) {
                // verificando se a peça está com o jogador da vez
                for (Domino pd: players.get(currentPlayer).getPieces()) {
                        if (pd.equals(d)) {
                                // verificando se a peça pode ser jogada
                                if (board.getDominoes() == null || board.getDominoes().size() == 0) {
                                        if (firstPiece == null) {
                                                return true;
                                        } else {
                                                return firstPiece.equals(d);
                                        }
                                } else {
                                        boolean valid = board.isAValidPieceToPlay(d, Board.POSITION_START) || board.isAValidPieceToPlay(d, Board.POSITION_END);
                                        if (valid) return true;
                                        else return false;
                                }
                        }
                }
             
                return false;
        }

        public void removePlayer(final Player playerToRemove) {
                // os outros jogadores devem ser liberados para jogar
                for (Player player: players) {
                        if (playerToRemove != player) {
                                try {
                                        player.setCurrentGame(null);
                                     
                                        player.getStub().receiveMessage("Servidor", "O Jogador " + playerToRemove.getUserName() + " saiu do jogo. O jogo está sendo finalizado.");
                                        player.getStub().receiveMessage("Servidor", "Outro Jogo será iniciado assim que possível");
                                     
                                        PlayerThread pt = new PlayerThread(player) {
                                                public void run() {
                                                        try {
                                                                this.p.getStub().endGame(Client.END_GAME_CAUSE_PLAYER_LOGGED_OUT, "O Jogador " + playerToRemove.getUserName() + " saiu do jogo.\nO jogo está sendo finalizado.");
                                                                server.freePlayer(p);
                                                        } catch (RemoteException e) {
                                                                remoteExceptionThrowed = true;
                                                                Game.this.server.removePlayer(p);
                                                        }            
                                                }
                                        };
                                        pt.start();
                                } catch (RemoteException e) {
                                        this.server.removePlayer(playerToRemove);
                                }
                        }
                }
        }
     
        private void playerWon(final Player winner) {
                for (Player player: players) {
                        try {
                                player.setCurrentGame(null);
                             
                                if (player != winner) {
                                        player.getStub().receiveMessage("Servidor", "O Jogador " + player.getUserName() + " Bateu! Um Novo Jogo Será iniciado.");    
                                } else {
                                        player.getStub().receiveMessage("Servidor", "Você Venceu o Jogo!!! Um Novo Jogo Será iniciado.");
                                }
                             
                             
                                PlayerThread pt = new PlayerThread(player) {
                                        public void run() {
                                                try {
                                                        if (p != winner) {
                                                                this.p.getStub().endGame(Client.END_GAME_CAUSE_PLAYER_WON, "O Jogador " + winner.getUserName() + " Bateu!\nUm novo jogo será iniciado assim que possível.");  
                                                        } else {
                                                                this.p.getStub().endGame(Client.END_GAME_CAUSE_PLAYER_WON, "Você Venceu o Jogo!!!\nUm novo jogo será iniciado assim que possível.");
                                                        }                                                    
                                                        server.freePlayer(p);
                                                } catch (RemoteException e) {
                                                        remoteExceptionThrowed = true;
                                                        Game.this.server.removePlayer(p);
                                                }            
                                        }
                                };
                                pt.start();
                        } catch (RemoteException e) {
                                this.server.removePlayer(player);
                        }
                }
        }
     
     
        private void countPiecesPoints() {
                int less = -1;
                final List<Player> winners = new ArrayList<Player>();
             
                // contagem dos pontos
                for (Player p: players) {
                        if (less == -1 || p.getPoints() < less) {
                                winners.clear();
                                winners.add(p);
                                less = p.getPoints();
                        } else if (p.getPoints() == less) {
                                winners.add(p);
                        }
                }
             
                String w = "";
                for (Player p: winners) {
                        w += p.getUserName();
                        if (winners.indexOf(p) < winners.size() - 2) {
                                w += ", ";
                        } else if (winners.indexOf(p) == winners.size() - 2) {
                                w += " e ";
                        }
                }
             
                final String s = w;
             
                for (Player player: players) {
                        try {
                                player.setCurrentGame(null);
                             
                                if (winners.size() == 1) {
                                        if (!winners.contains(player)) {
                                                player.getStub().receiveMessage("Servidor", "O Jogador " + winners.get(0).getUserName() + " Venceu nos pontos! Um Novo Jogo Será iniciado.");
                                        } else {
                                                player.getStub().receiveMessage("Servidor", "Você Venceu o Jogo nos Pontos!!! Um Novo Jogo Será iniciado.");
                                        }
                                } else {
                                     
                                        player.getStub().receiveMessage("Servidor", "Empate entre os jogadores " + w + "! Um Novo Jogo Será iniciado.");      
                                     
                                }
                             
                                PlayerThread pt = new PlayerThread(player) {
                                        public void run() {
                                                try {
                                                        if (winners.size() == 1) {
                                                                if (!winners.contains(p)) {
                                                                        this.p.getStub().endGame(Client.END_GAME_CAUSE_GAME_CLOSED, "O Jogador " + winners.get(0).getUserName() + " Venceu nos Pontos!\nUm novo jogo será iniciado assim que possível.");    
                                                                } else {
                                                                        this.p.getStub().endGame(Client.END_GAME_CAUSE_GAME_CLOSED, "Você Venceu o Jogo nos Pontos!!!\nUm novo jogo será iniciado assim que possível.");
                                                                }
                                                        } else {
                                                                this.p.getStub().endGame(Client.END_GAME_CAUSE_GAME_CLOSED, "Empate entre os jogadores " + s + "!\nUm novo jogo será iniciado assim que possível.");
                                                        }
                                                        server.freePlayer(p);
                                                } catch (RemoteException e) {
                                                        remoteExceptionThrowed = true;
                                                        Game.this.server.removePlayer(p);
                                                }            
                                        }
                                };
                                pt.start();
                        } catch (RemoteException e) {
                                this.server.removePlayer(player);
                        }
                }
        }
}

Tidak ada komentar:

Posting Komentar