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