Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <string>
- #include <cctype>
- #include "validate.cpp"
- using namespace std;
- /**
- * Definicoes das constantes que armazenam quais caracteres serao mostrados
- * na tela para representar os diferentes tipos de pecas do tabuleiro.
- */
- #define KING 'R' // Rei
- #define WHITE 'S' // Suecos
- #define BLACK 'M' // Moscovitas
- #define EMPTY ' ' // Espaco em branco
- #define CASTLE 'C' // Castelo
- /**
- * A classe Tablut e a classe que estrutura o jogo, com suas propriedades
- * e metodos.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- */
- class Tablut {
- private:
- /**
- * As strings _playerOne e _playerTwo gravam os nomes dos jogadores.
- */
- string _playerOne, _playerTwo;
- /**
- * A string _currentPlayer grava o nome do jogador atual.
- */
- string _currentPlayer;
- /**
- * A matriz _map e o tabuleiro do jogo, onde serao feitas as modificacoes
- * e as jogadas.
- */
- char _map[9][9];
- /**
- * As propriedades _capturedWhites e _capturedBlacks contam quantas
- * pecas, de suas cores respectivas, foram capturadas pelo adversario.
- */
- int _capturedWhites;
- int _capturedBlacks;
- /**
- * _log e onde ficarao gravadas as mensagens de erro do jogo
- */
- string _log;
- /**
- * Metodos relacionados ao nivel mais baixo de manipulacao
- * do jogo, como alterar o log, escrever na tela e limpar a tela.
- */
- void changePlayer();
- void clearLog();
- void drawMap();
- void drawScreen();
- void getLog();
- void invertPositions(int,int,int,int);
- void populateMap();
- void setLog(string);
- void deleteInstance();
- /**
- * Metodos relacionados com as operacoes internas de validacao e
- * modificacao das propriedades da classe, eventos do jogo entre outras.
- */
- bool capturePieces(int,int,int,int);
- void endOfGame(string,string);
- int getKingPositionX();
- int getKingPositionY();
- bool movePiece(int,int,int,int);
- /**
- * Metodos de validacao das regras do jogo.
- */
- bool hasNoPiecesLeft();
- bool hasPiece(int,int);
- bool isEmpty(int,int);
- bool isInLineOrColumn(int,int,int,int);
- bool isKingOnBorder();
- bool isKingSurrounded();
- bool isMovingCastle(int,int);
- bool isMovingKingFromCenter(int,int);
- bool isMovingPieceToCenter(int,int);
- bool isMovingMoreThanOnePieceAwayFromTheCastle(int,int);
- bool isOwner(int,int);
- bool isPassingOver(int,int,int,int);
- bool isPassingOverTheCastle(int,int,int,int);
- /**
- * Metodos utilizados pelo jogo em um nivel mais alto, geralmente
- * podem requerer a entrada de dados pelo usuario.
- */
- void readTurnInput();
- public:
- /**
- * Tablut() define o metodo construtor da classe
- */
- Tablut();
- };
- /**
- * O metodo Tablut::Tablut() e o construtor da classe Tablut, e ele desenha a tela inicial,
- * solicita os nomes dos dois jogadores, e entao chama o metodo Tablut::drawScreen()
- * que faz a jogatina comecar. :D
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Void}
- */
- Tablut::Tablut(){
- system("clear");
- string player1, player2;
- //system("color 0F");
- cout << endl << endl;
- cout << " 88 88 " << endl;
- cout << " ,d 88 88 ,d " << endl;
- cout << " 88 88 88 88 " << endl;
- cout << " MM88MMM ,adPPYYba, 88,dPPYba, 88 88 88 MM88MMM " << endl;
- cout << " 88 `Y8 88P' '8a 88 88 88 88 " << endl;
- cout << " 88 ,adPPPPP88 88 d8 88 88 88 88 " << endl;
- cout << " 88, 88, ,88 88b, ,a8' 88 '8a, ,a88 88, " << endl;
- cout << " 'Y888 `'8bbdP'Y8 8Y'Ybbd8'' 88 `'YbbdP'Y8 'Y888 " << endl;
- cout << " 2008 Rafael Marin Bortolotto" << endl << endl;
- //textcolor(YELLOW);
- /**
- * Solicita o nome do primeiro jogador
- */
- cout << " Digite o nome do primeiro jogador: ";
- getline(cin,player1);
- while(player1=="" || player1 == " "){
- cout << " (#) Seu nome não pode ser em branco.\n\n Digite o nome do primeiro jogador: ";
- getline(cin,player1);
- }
- cout << " " << player1 << " será os Suecos ("<<WHITE<<"), que devem DEFENDER o Rei ("<<KING<<"). " << endl << endl;
- /**
- * Solicita o nome do segundo jogador ateh que os nomes
- * sejam diferentes.
- */
- cout << " Digite o nome do segundo jogador: ";
- getline(cin,player2);
- while(player2=="" || player2 == " "){
- cout << " (#) Seu nome não pode ser em branco.\n\n Digite o nome do segundo jogador: ";
- getline(cin,player2);
- }
- while(player1==player2){
- cout << " (#) Cada jogador deve ter um nome diferente.\n\n Digite o nome do segundo jogador: ";
- getline(cin,player2);
- }
- cout << " " << player2 << " ficará com os Moscovitas ("<<BLACK<<"), que devem ATACAR o Rei ("<<KING<<"). " << endl << endl;
- /**
- * Pressione qualquer tecla para continuar.
- */
- cout << " Pressione qualquer tecla para continuar.";
- cin.get();
- //system("pause");
- // Define o jogador 1
- this->_playerOne = player1;
- // Define o jogador 2
- this->_playerTwo = player2;
- // Peças pretas capturadas
- this->_capturedBlacks = 0;
- // Peças brancas capturadas
- this->_capturedWhites = 0;
- // O jogador atual e o primeiro jogador
- this->_currentPlayer = this->_playerOne;
- // Preenche o tabuleiro com as posicoes iniciais das pecas
- this->populateMap();
- // Desenha a tela pela primeira vez
- this->drawScreen();
- }
- /**
- * O metodo Tablut::changePlayer() alterna o jogador atual entre os dois jogadores.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Void}
- */
- void Tablut::changePlayer(){
- this->_currentPlayer = (this->_currentPlayer == this->_playerOne)? this->_playerTwo : this->_playerOne;
- }
- /**
- * O metodo Tablut::clearLog() limpa o log da tela para que as novas mensagens
- * sejam escritas na proxima vez que for recarregada.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Void}
- */
- void Tablut::clearLog(){
- this->_log = "";
- }
- /**
- * O metodo Tablut::drawMap() desenha o tabuleiro na tela.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Void}
- */
- void Tablut::drawMap() {
- cout << endl << endl << " 0 1 2 3 4 5 6 7 8 " << endl;
- cout << " ------------------------------------" << endl;
- for(int i=0; i<9; i++){
- cout << " " << i << " | ";
- for(int j=0;j<9;j++){
- cout << this->_map[i][j] << " | ";
- }
- cout << endl << " ------------------------------------" << endl;
- }
- }
- /**
- * O metodo Tablut::drawScreen() faz a limpeza da tela e recria a tela
- * a cada jogada, desenhando a situacao atual do tabuleiro e das pecas,
- * com espaco ainda para o log de mensagens e para a entrada do usuario.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Void}
- */
- void Tablut::drawScreen() {
- system("clear");
- //system("color 0F");
- this->drawMap();
- this->getLog();
- this->clearLog();
- //textcolor(YELLOW);
- cout << " " << this->_currentPlayer << ", você joga." << endl;
- // Chama a entrada do usuario
- this->readTurnInput();
- }
- /**
- * O metodo Tablut::getLog() retorna o log de mensagens de erro e avisos
- * definidos pelo programa ate entao.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Void}
- */
- void Tablut::getLog() {
- //textcolor(LIGHTRED);
- cout << this->_log << endl;
- //textcolor(YELLOW);
- }
- /**
- * O metodo Tablut::invertPositions() faz a troca entre as pecas
- * que estao na posicao [fromX,fromY] no tabuleiro com as pecas que
- * estao na posicao [toX,toY].
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Integer} fromX Coordenada X de origem da peca
- * @param {Integer} fromY Coordenada Y de origem da peca
- * @param {Integer} toX Coordenada X de destino da peca
- * @param {Integer} toY Coordenada Y de destino da peca
- * @return {Void}
- */
- void Tablut::invertPositions(int fromX, int fromY, int toX, int toY){
- char aux = this->_map[fromX][fromY];
- this->_map[fromX][fromY] = this->_map[toX][toY];
- this->_map[toX][toY] = aux;
- }
- /**
- * O metodo Tablut::populateMap() e o procedimento que popula o mapa inicial
- * do jogo, assim que a classe for instanciada.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Void}
- */
- void Tablut::populateMap() {
- /* {
- {EMPTY, EMPTY, EMPTY, BLACK, BLACK, BLACK, EMPTY, EMPTY, EMPTY},
- {EMPTY, EMPTY, EMPTY, EMPTY, BLACK, EMPTY, EMPTY, EMPTY, EMPTY},
- {EMPTY, EMPTY, EMPTY, EMPTY, WHITE, EMPTY, EMPTY, EMPTY, EMPTY},
- {BLACK, EMPTY, EMPTY, EMPTY, WHITE, EMPTY, EMPTY, EMPTY, BLACK},
- {BLACK, BLACK, WHITE, WHITE, KING, WHITE, WHITE, BLACK, BLACK},
- {BLACK, EMPTY, EMPTY, EMPTY, WHITE, EMPTY, EMPTY, EMPTY, BLACK},
- {EMPTY, EMPTY, EMPTY, EMPTY, WHITE, EMPTY, EMPTY, EMPTY, EMPTY},
- {EMPTY, EMPTY, EMPTY, EMPTY, BLACK, EMPTY, EMPTY, EMPTY, EMPTY},
- {EMPTY, EMPTY, EMPTY, BLACK, BLACK, BLACK, EMPTY, EMPTY, EMPTY}
- };*/
- this->_map[0][0] = EMPTY;
- this->_map[0][1] = EMPTY;
- this->_map[0][2] = EMPTY;
- this->_map[0][3] = BLACK;
- this->_map[0][4] = BLACK;
- this->_map[0][5] = BLACK;
- this->_map[0][6] = EMPTY;
- this->_map[0][7] = EMPTY;
- this->_map[0][8] = EMPTY;
- this->_map[1][0] = EMPTY;
- this->_map[1][1] = EMPTY;
- this->_map[1][2] = EMPTY;
- this->_map[1][3] = EMPTY;
- this->_map[1][4] = BLACK;
- this->_map[1][5] = EMPTY;
- this->_map[1][6] = EMPTY;
- this->_map[1][7] = EMPTY;
- this->_map[1][8] = EMPTY;
- this->_map[2][0] = EMPTY;
- this->_map[2][1] = EMPTY;
- this->_map[2][2] = EMPTY;
- this->_map[2][3] = EMPTY;
- this->_map[2][4] = WHITE;
- this->_map[2][5] = EMPTY;
- this->_map[2][6] = EMPTY;
- this->_map[2][7] = EMPTY;
- this->_map[2][8] = EMPTY;
- this->_map[3][0] = BLACK;
- this->_map[3][1] = EMPTY;
- this->_map[3][2] = EMPTY;
- this->_map[3][3] = EMPTY;
- this->_map[3][4] = WHITE;
- this->_map[3][5] = EMPTY;
- this->_map[3][6] = EMPTY;
- this->_map[3][7] = EMPTY;
- this->_map[3][8] = BLACK;
- this->_map[4][0] = BLACK;
- this->_map[4][1] = BLACK;
- this->_map[4][2] = WHITE;
- this->_map[4][3] = WHITE;
- this->_map[4][4] = KING;
- this->_map[4][5] = WHITE;
- this->_map[4][6] = WHITE;
- this->_map[4][7] = BLACK;
- this->_map[4][8] = BLACK;
- this->_map[5][0] = BLACK;
- this->_map[5][1] = EMPTY;
- this->_map[5][2] = EMPTY;
- this->_map[5][3] = EMPTY;
- this->_map[5][4] = WHITE;
- this->_map[5][5] = EMPTY;
- this->_map[5][6] = EMPTY;
- this->_map[5][7] = EMPTY;
- this->_map[5][8] = BLACK;
- this->_map[6][0] = EMPTY;
- this->_map[6][1] = EMPTY;
- this->_map[6][2] = EMPTY;
- this->_map[6][3] = EMPTY;
- this->_map[6][4] = WHITE;
- this->_map[6][5] = EMPTY;
- this->_map[6][6] = EMPTY;
- this->_map[6][7] = EMPTY;
- this->_map[6][8] = EMPTY;
- this->_map[7][0] = EMPTY;
- this->_map[7][1] = EMPTY;
- this->_map[7][2] = EMPTY;
- this->_map[7][3] = EMPTY;
- this->_map[7][4] = BLACK;
- this->_map[7][5] = EMPTY;
- this->_map[7][6] = EMPTY;
- this->_map[7][7] = EMPTY;
- this->_map[7][8] = EMPTY;
- this->_map[8][0] = EMPTY;
- this->_map[8][1] = EMPTY;
- this->_map[8][2] = EMPTY;
- this->_map[8][3] = BLACK;
- this->_map[8][4] = BLACK;
- this->_map[8][5] = BLACK;
- this->_map[8][6] = EMPTY;
- this->_map[8][7] = EMPTY;
- this->_map[8][8] = EMPTY;
- }
- /**
- * O metodo Tablut::setLog() adiciona uma mensagem ao log
- * de erros, que sera exibido quando o metodo Tablut::getLog() for chamado.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @params {String} message Mensagem a ser adicionada ao log.
- * @return {Void}
- */
- void Tablut::setLog(string message){
- this->_log += "\n" + message + "\n";
- }
- /**
- * O metodo Tablut::capturePieces() e responsavel por verificar se
- * na jogada atual alguma peca foi capturada e entao a captura.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Integer} fromX Coordenada X de origem da peca
- * @param {Integer} fromY Coordenada Y de origem da peca
- * @param {Integer} toX Coordenada X de destino da peca
- * @param {Integer} toY Coordenada Y de destino da peca
- * @return {Boolean}
- */
- bool Tablut::capturePieces(int fromX, int fromY, int toX, int toY){
- // Se a peca em questao nao for guerreiro, retorna falso
- if(this->_map[fromX][fromY] != WHITE && this->_map[fromX][fromY] != BLACK){
- return false;
- }
- // Define qual a cor da peca atual
- char sameRole = (this->_map[fromX][fromY] == WHITE)? WHITE : BLACK;
- // Define a cor da outra peca, a partir da peca atual
- char oppositeRole = (sameRole == WHITE)? BLACK : WHITE;
- // Conta quantas pecas ja foram capturadas
- int capturedPieces = 0;
- // Define as posicoes a serem pesquisadas
- int topSame = this->_map[toX-2][toY];
- int topOpposite = this->_map[toX-1][toY];
- int rightSame = this->_map[toX][toY+2];
- int rightOpposite = this->_map[toX][toY+1];
- int bottomSame = this->_map[toX+2][toY];
- int bottomOpposite = this->_map[toX+1][toY];
- int leftSame = this->_map[toX][toY-2];
- int leftOpposite = this->_map[toX][toY-1];
- // Se ha capturas a serem feitas acima
- if(topSame==sameRole && topOpposite==oppositeRole){
- capturedPieces++;
- this->_map[toX-1][toY] = EMPTY;
- }
- // Se ha capturas a serem feitas a direita
- if(rightSame==sameRole && rightOpposite==oppositeRole){
- capturedPieces++;
- this->_map[toX][toY+1] = EMPTY;
- }
- // Se ha capturas a serem feitas abaixo
- if(bottomSame==sameRole && bottomOpposite==oppositeRole){
- capturedPieces++;
- this->_map[toX+1][toY] = EMPTY;
- }
- // Se ha capturas a serem feitas a esquerda
- if(leftSame==sameRole && leftOpposite==oppositeRole){
- capturedPieces++;
- this->_map[toX][toY-1] = EMPTY;
- }
- // Se alguma peca foi capturada
- if(capturedPieces > 0){
- // Se a peca branca (suecos) capturaram uma peca
- if(sameRole == WHITE) {
- this->_capturedBlacks += capturedPieces;
- string message = " (!) Os suecos capturaram ";
- if(capturedPieces == 1) {
- message += "1 soldado moscovita. Ao todo já\n capturaram ";
- } else {
- message += capturedPieces + 48;
- message += " soldados moscovitas. Ao todo já\n capturaram ";
- }
- if(this->_capturedBlacks == 1) {
- message += "1 soldado moscovita.";
- } else {
- message += this->_capturedBlacks + 48;
- message += " soldados moscovitas.";
- }
- this->setLog(message);
- // Se a peca preta (moscovitas) capturaram uma peca.
- } else {
- this->_capturedWhites += capturedPieces;
- string message = " (!) Os moscovitas capturaram ";
- if(capturedPieces == 1) {
- message += "1 soldado sueco. Ao todo já\n capturaram ";
- } else {
- message += capturedPieces + 48;
- message += " soldados suecos. Ao todo já\n capturaram ";
- }
- if(this->_capturedWhites == 1) {
- message += "1 soldado sueco.";
- } else {
- message += this->_capturedWhites + 48;
- message += " soldados suecos.";
- }
- this->setLog(message);
- }
- // Se houve captura move a peca atual para o local destinado
- this->invertPositions(fromX,fromY,toX,toY);
- return true;
- }
- return false;
- }
- /**
- * O metodo Tablut::endOfGame() encerra o jogo, retornando para a tela
- * principal.
- *
- * PRECISA SER ACABADO, POIS ALEM DE UMA INTERFACE MELHOR
- * TEM QUE DIZER QUEM GANHOU, QUEM PERDEU, IMPRIMIR A AREA DE PECAS
- * CAPTURADAS, E EXPLICAR O MOTIVO DA VITORIA/DERROTA.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Void}
- */
- void Tablut::endOfGame(string reason, string winner="") {
- system("clear");
- //system("color 0F");
- cout << endl << endl;
- cout << " #### ## # # ###### #### # # ###### ##### " << endl;
- cout << " # # # # ## ## # # # # # # # # " << endl;
- cout << " # # # # ## # ##### # # # # ##### # # " << endl;
- cout << " # ### ###### # # # # # # # # ##### " << endl;
- cout << " # # # # # # # # # # # # # # " << endl;
- cout << " #### # # # # ###### #### ## ###### # # " << endl;
- cout << endl << endl;
- // textcolor(YELLOW);
- string messageReason;
- if(reason=="kingOnBorder"){
- messageReason = " O Rei escapou pela culatra!\n";
- messageReason += " Fim de guerra, os suecos ganharam.\n";
- messageReason += " Parabéns, "+this->_playerOne+"! Você derrotou os moscovitas.\n";
- } else if(reason=="kingSurrounded"){
- messageReason = " O Rei foi pego no pulo!\n";
- messageReason += " Fim de guerra, os moscovitas ganharam.\n";
- messageReason += " Parabéns, "+this->_playerTwo+"! Você derrotou os suecos.\n";
- } else if(reason=="noPiecesLeft"){
- string attackers = (winner=="white")? "suecos" : "moscovitas";
- string defenders = (winner=="white")? "moscovitas" : "suecos";
- string winnerPlayer = (winner=="white")? this->_playerOne : this->_playerTwo;
- messageReason = " Os "+attackers+" capturaram todos os "+defenders+"!\n";
- messageReason += " Fim de guerra, os "+attackers+" ganharam.\n";
- messageReason += " Parabéns, "+winnerPlayer+"! Você derrotou os "+defenders+".\n";
- }
- cout << messageReason << endl;
- cout << endl;
- cout << " +-------------------+-------------------+" << endl;
- cout << " | SUECOS | MOSCOVITAS |" << endl;
- cout << " | Capturados | Capturados |" << endl;
- cout << " +-------------------+-------------------+" << endl;
- cout << " | "<<(int)this->_capturedWhites<<" | "<<(int)this->_capturedBlacks<<" |" << endl;
- cout << " +-------------------+-------------------+" << endl;
- cout << endl;
- cout << " --------------------------------------------------" << endl;
- cout << " Universidade de Caxias do Sul"<< endl;
- cout << " Bacharelado em Tecnologias Digitais"<< endl;
- cout << " Programação I 2008/4"<< endl;
- cout << " Professor André Luis Martinotto" << endl;
- cout << " Desenvolvido por Rafael Marin Bortolotto" << endl;
- cin.get();
- //cout << " Pressione qualquer tecla para SAIR\n ";
- //system("pause");
- exit(1);
- }
- /**
- * O metodo Tablut::getKingPositionX() percorre toda a matriz e retorna
- * qual a coordenada X (linha) atual do Rei.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Integer}
- */
- int Tablut::getKingPositionX() {
- int position;
- for(int i=0; i<9; i++){
- for(int j=0;j<9;j++){
- if(this->_map[i][j] == KING) {
- return i;
- }
- }
- }
- }
- /**
- * O metodo Tablut::getKingPositionY() percorre toda a matriz e retorna
- * qual a coordenada Y (coluna) atual do Rei.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Integer}
- */
- int Tablut::getKingPositionY() {
- int position;
- for(int i=0; i<9; i++){
- for(int j=0;j<9;j++){
- if(this->_map[i][j] == KING) {
- return j;
- }
- }
- }
- }
- /**
- * O metodo Tablut::movePiece() faz as validacoes necessarias e efetua
- * a movimentacao da peca caso as validacoes forem verdadeiras.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Integer} fromX Coordenada X de origem da peca
- * @param {Integer} fromY Coordenada Y de origem da peca
- * @param {Integer} toX Coordenada X de destino da peca
- * @param {Integer} toY Coordenada Y de destino da peca
- * @return {Boolean}
- */
- bool Tablut::movePiece(int fromX, int fromY, int toX, int toY){
- // Se a peca de origem for vazia
- if(this->isEmpty(fromX,fromY)){
- this->setLog(" (#) Nao ha nenhuma peca para ser movida no local selecionado.");
- return false;
- }
- // Se a peca de origem pertence ao usuario
- if(!this->isOwner(fromX,fromY)){
- this->setLog(" (#) Voce nao pode mover esta peca pois ela pertence ao outro jogador.");
- return false;
- }
- // Se ha outra peca na coordenada de destino
- if(this->hasPiece(toX,toY)){
- this->setLog(" (#) Ja existe uma peca no local onde voce pretendia coloca-la.");
- return false;
- }
- // Se a coordenada de destino e horizontal ou vertical
- if(!this->isInLineOrColumn(fromX,fromY,toX,toY)){
- this->setLog(" (#) A peca so pode ser movida horizontalmente ou verticalmente.");
- return false;
- }
- // Se a peca esta passando por cima de outra
- if(this->isPassingOver(fromX,fromY,toX,toY)){
- this->setLog(" (#) Voce nao pode passar por cima de outra peca. ");
- return false;
- }
- // Se esta tentando mudar o rei de lugar
- if(this->isMovingKingFromCenter(fromX,fromY)){
- this->invertPositions(fromX,fromY,toX,toY);
- this->_map[4][4] = CASTLE;
- return true;
- }
- // Se esta tentando mover para o centro
- if(this->isMovingPieceToCenter(toX,toY)){
- this->setLog(" (#) Nenhuma peca, nem o rei, pode ser movido para o centro.");
- return false;
- }
- // Se capturou alguma peca retorna verdadeiro pois ja fez o movimento da peca
- if(this->capturePieces(fromX,fromY,toX,toY)){
- return true;
- }
- // Se a peca passou por cima do castelo
- if(this->isPassingOverTheCastle(fromX, fromY, toX, toY)){
- // Se passou, soh pode cair na casa logo ao lado
- if(this->isMovingMoreThanOnePieceAwayFromTheCastle(toX, toY)){
- this->setLog(" (#) Ao passar de cima do castelo, voce so pode colocar a peca\n imediatamente em seguida dele.");
- return false;
- }
- }
- // Se esta tentando mover o castelo do centro do tabuleiro
- if(this->isMovingCastle(fromX,fromY)){
- this->setLog(" (#) Voce nao pode mover o castelo do centro.");
- return false;
- }
- // Se passar nas validacoes anteriores
- this->invertPositions(fromX,fromY,toX,toY);
- return true;
- }
- /**
- * O metodo Tablut::hasNoPiecesLeft() verifica se as pecas do jogador atual
- * acabaram, ou seja, que ele perdeu o jogo.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Boolean}
- */
- bool Tablut::hasNoPiecesLeft(){
- char playerRole = (this->_currentPlayer == this->_playerOne)? WHITE : BLACK;
- int pieces = 0;
- for(int i=0; i<9; i++){
- for(int j=0; j<9; j++){
- if(this->_map[i][j]==playerRole)
- pieces++;
- }
- }
- if(pieces==0 && this->isKingSurrounded())
- return true;
- return false;
- }
- /**
- * Verifica se o objeto na coordenada especificada e nulo
- * ou nao. Se o objeto for nulo, significa que esta posicao
- * no tabuleiro esta vaga.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Integer} x Coordenada X da peca
- * @param {Integer} y Coordenada Y da peca
- * @return {Boolean}
- */
- bool Tablut::hasPiece(int x, int y){
- if(this->_map[x][y] == EMPTY || this->_map[x][y] == CASTLE)
- return false;
- return true;
- }
- /**
- * O metodo Tablut::isEmpty() verifica se a casa desejada esta
- * em branco ou nao.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Integer} x Coordenada X da casa solicitada
- * @param {Integer} y Coordenada Y da casa solicitada
- * @return {Boolean}
- */
- bool Tablut::isEmpty(int x, int y){
- if(this->_map[x][y] == EMPTY)
- return true;
- return false;
- }
- /**
- * O metodo Tablut::isInLineOrColumn() verifica se a peca na
- * posicao to esta na mesma linha ou coluna da peca from, indicando
- * que a movimentacao pode ocorrer.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Integer} fromX Coordenada X de origem da peca
- * @param {Integer} fromY Coordenada Y de origem da peca
- * @param {Integer} toX Coordenada X de destino da peca
- * @param {Integer} toY Coordenada Y de destino da peca
- * @return {Boolean}
- */
- bool Tablut::isInLineOrColumn(int fromX, int fromY, int toX, int toY){
- if((fromX==toX && fromY!=toY) || (fromY==toY && fromX!=toX))
- return true;
- return false;
- }
- /**
- * O metodo Tablut::isKingOnBorder() verifica se o rei esta em uma
- * das bordas do tabuleiro.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Boolean}
- */
- bool Tablut::isKingOnBorder() {
- int x = this->getKingPositionX();
- int y = this->getKingPositionY();
- if(x == 0 || y == 0 || x == 8 || y==8)
- return true;
- return false;
- }
- /**
- * O metodo Tablut::isKingSurrounded() verifica se o rei esta cercado
- * de pecas pretas ou nao. Se estiver, quer dizer que o jogador das pecas
- * brancas ganhou.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Boolean}
- */
- bool Tablut::isKingSurrounded() {
- int x = this->getKingPositionX();
- int y = this->getKingPositionY();
- if(!this->isKingOnBorder()) {
- char top = this->_map[x][y-1];
- char bottom = this->_map[x][y+1];
- char left = this->_map[x-1][y];
- char right = this->_map[x+1][y];
- if((top==BLACK || top==CASTLE) && (bottom==BLACK || bottom==CASTLE) && (left==BLACK || left==CASTLE) && (right==BLACK || right==CASTLE))
- return true;
- return false;
- }
- return false;
- }
- /**
- * O metodo Tablut::isMovingCastle() verifica se o jogador esta tentando
- * mover o castelo do centro do tabuleiro, o que nao eh permitido.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Array} x Coordenada X de origem da peca
- * @param {Array} y Coordenada Y de origem da peca
- * @return {Boolean}
- */
- bool Tablut::isMovingCastle(int x, int y){
- if(x==4 && y==4 && this->_map[4][4]==CASTLE)
- return true;
- return false;
- }
- /**
- * O metodo Tablut::isMovingKingFromCenter() verifica se o jogador esta tentando
- * mover o rei do centro, se ele selecionou a posicao do centro.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Array} x Coordenada X de origem da peca
- * @param {Array} y Coordenada Y de origem da peca
- * @return {Boolean}
- */
- bool Tablut::isMovingKingFromCenter(int x, int y){
- if(x==4 && y==4 && this->_map[4][4]==KING)
- return true;
- return false;
- }
- /**
- * O metodo Tablut::isMovingMoreThanOnePieceAwayFromTheCastle() verifica se a peca
- * que cruzou sobre o castelo foi colocada na casa logo em seguida, pois e a unica
- * posicao valida para essa jogada.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Array} toX Coordenada X da peca
- * @param {Array} toY Coordenada Y da peca
- * @return {Boolean}
- */
- bool Tablut::isMovingMoreThanOnePieceAwayFromTheCastle(int toX, int toY){
- if((toX==3 && toY==4) || (toX==4 && toY==5) || (toX==5 && toY==4) || (toX==4 && toY==3))
- return false;
- return true;
- }
- /**
- * O metodo Tablut::isMovingPieceToCenter() verifica se a peca atual esta sendo
- * movida para a posicao central do tabuleiro. Quem verifica se isso e possivel
- * e o metodo Tablut::canMovePieceToCenter().
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Integer} toX Coordenada X de destino da peca
- * @param {Integer} toY Coordenada Y de destino da peca
- * @return {Boolean}
- */
- bool Tablut::isMovingPieceToCenter(int toX, int toY){
- if(toX==4 && toY==4)
- return true;
- return false;
- }
- /**
- * O metodo Tablut::isOwner() verifica se o jogador atual pode mexer
- * na peca escolhida, pois o jogador das pecas pretas nao pode mexer na posicao
- * do rei nem das brancas e vice-versa.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Integer} x Coordenada X da peca solicitada
- * @param {Integer} y Coordenada Y da peca solicitada
- * @return {Boolean}
- */
- bool Tablut::isOwner(int x, int y){
- if(this->_currentPlayer == this->_playerOne){
- if(this->_map[x][y] == KING || this->_map[x][y] == WHITE || this->_map[x][y] == EMPTY || this->_map[x][y]==CASTLE) {
- return true;
- }
- } else {
- if(this->_map[x][y] == BLACK || this->_map[x][y] == EMPTY) {
- return true;
- }
- }
- return false;
- }
- /**
- * O metodo Tablut::isPassingOver() verifica se a peca a ser movida
- * passara por cima de outras pecas, o que nao e permitido no jogo.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Integer} fromX Coordenada X de origem da peca
- * @param {Integer} fromY Coordenada Y de origem da peca
- * @param {Integer} toX Coordenada X de destino da peca
- * @param {Integer} toY Coordenada Y de destino da peca
- * @return {Boolean}
- */
- bool Tablut::isPassingOver(int fromX, int fromY, int toX, int toY){
- bool isPassing = false;
- // Se esta movendo na linha
- if(fromX==toX){
- int major = (fromY > toY)? fromY : toY;
- int minor = (fromY > toY)? toY : fromY;
- int line = fromX;
- for(int i=minor+1;i<major; i++){
- if(this->_map[line][i]!=EMPTY && this->_map[line][i]!=CASTLE)
- isPassing = true;
- }
- // Se esta movendo na coluna
- } else {
- int major = (fromX > toX)? fromX : toX;
- int minor = (fromX > toX)? toX : fromX;
- int column = fromY;
- for(int i=minor+1;i<major; i++){
- if(this->_map[i][column]!=EMPTY && this->_map[i][column]!=CASTLE)
- isPassing = true;
- }
- }
- return isPassing;
- }
- /**
- * O metodo Tablut::isPassingOverTheCastle() verifica se a peca a ser movida
- * passa por cima do castelo. A partir dessa verificacao sera feita uma segunda
- * verificacao, pelo metodo Tablut::isMovingMoreThanOnePieceAwayFromTheCastle(),
- * que entao vai verificar se a peca esta sendo movida para mais de uma casa de
- * distancia do castelo.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @param {Integer} fromX Coordenada X de origem da peca
- * @param {Integer} fromY Coordenada Y de origem da peca
- * @param {Integer} toX Coordenada X de destino da peca
- * @param {Integer} toY Coordenada Y de destino da peca
- * @return {Boolean}
- */
- bool Tablut::isPassingOverTheCastle(int fromX, int fromY, int toX, int toY){
- bool isPassingOverCastle = false;
- // Se esta movendo na linha
- if(fromX==toX){
- int major = (fromY > toY)? fromY : toY;
- int minor = (fromY > toY)? toY : fromY;
- int line = fromX;
- for(int i=minor+1;i<major; i++){
- if(this->_map[line][i]==CASTLE)
- isPassingOverCastle = true;
- }
- // Se esta movendo na coluna
- } else {
- int major = (fromX > toX)? fromX : toX;
- int minor = (fromX > toX)? toX : fromX;
- int column = fromY;
- for(int i=minor+1; i<major; i++){
- if(this->_map[i][column]==CASTLE)
- isPassingOverCastle = true;
- }
- }
- return isPassingOverCastle;
- }
- /**
- * O metodo Tablut::readTurnInput() le as coordenadas digitadas pelo
- * usuario na rodada e efetua as movimentacoes, se necessarias. Verifica
- * as condicoes necessarias para encerrar o jogo, e encerra o jogo caso
- * alguma dessas condicoes seja verdadeira.
- *
- * @author Rafael Marin <rafael@rafaelmarin.net>
- * @return {Void}
- */
- void Tablut::readTurnInput() {
- char fromX[100], fromY[100], toX[100], toY[100];
- //textcolor(YELLOW);
- /**
- * Le as coordenadas de origem
- */
- cout << " Digite as coordenadas da peca a ser movida:" << endl;
- cout << " Linha: ";
- cin >> fromX;
- while(!Validate::isNumber(fromX[0]) || !Validate::isCoordinate(fromX)){
- cout << " Linha (0-8): ";
- cin >> fromX;
- }
- cout << " Coluna: ";
- cin >> fromY;
- while(!Validate::isNumber(fromY[0]) || !Validate::isCoordinate(fromY)) {
- cout << " Coluna (0-8): ";
- cin >> fromY;
- }
- /**
- * Le as coordenadas de destino
- */
- cout << " Digite as coordenadas do local para colocar a peca: " << endl;
- cout << " Linha: ";
- cin >> toX;
- while(!Validate::isNumber(toX[0]) || !Validate::isCoordinate(toX)){
- cout << " Linha (0-8): ";
- cin >> toX;
- }
- cout << " Coluna: ";
- cin >> toY;
- while(!Validate::isNumber(toY[0]) || !Validate::isCoordinate(toY)) {
- cout << " Coluna (0-8): ";
- cin >> toY;
- }
- /**
- * Se a peca foi movida com sucesso, entao o usuario e
- * trocado para que o proximo usuario jogue e entao a
- * tela principal e recarregada.
- */
- if(this->movePiece(Validate::toInt(fromX[0]),Validate::toInt(fromY[0]),Validate::toInt(toX[0]),Validate::toInt(toY[0]))){
- this->changePlayer();
- }
- if(this->isKingOnBorder()){
- this->endOfGame("kingOnBorder");
- } else if(this->isKingSurrounded()){
- this->endOfGame("kingSurrounded");
- } else if(this->hasNoPiecesLeft()){
- string winner = (this->_currentPlayer==this->_playerOne)? "black" : "white";
- this->endOfGame("noPiecesLeft",winner);
- }
- this->drawScreen();
- }
- /**
- * Funcao inicial do programa
- */
- int main() {
- new Tablut();
- return 0;
- }
- /**
- TO-DO LIST
- - (OK) [PROFESSOR] VERIFICAR SE OS CARACTERES DIGITADOS SAO INTEIROS OU CARACTERES
- - (OK) [PROFESSOR] MELHORAR A INICIALIZACAO DA MATRIZ _map - Nao ha como.
- - (OK) MOVIMENTACOES DO JOGO
- - (OK) quando o rei sai da posicao original, o centro vira o castelo que se
- torna inacessivel para todos os jogadores
- - (OK) o jogador nao pode pular com a peca por cima de outras
- - (OK) quando uma peca for movida alem do castelo ela so pode ficar encostada ao castelo
- - (OK) [PROFESSOR] O REI PODE VOLTAR AO CASTELO? - Nao
- - (OK) ZONA DAS PECAS CAPTURADAS
- - (OK) captura de pecas simples
- - (OK) foi capturada ou se colocou ao meio de duas pecas?
- - (OK) captura de quatro lados do rei (encurralado, fim de jogo)
- - (OK) captura do rei ao lado do castelo (fim de jogo)
- - (OK) todos os soldados rivais foram capturados?
- - (OK) VERIFICAR AS CONDICOES DE TERMINO DE JOGO
- - (OK) o rei chegou ao canto?
- - (OK) o rei foi encurralado?
- - (OK) o rei foi encurralado ao lado do castelo?
- - (OK) AO FIM DO JOGO, DIZER O CAMPEAO E MOSTRAR OS SOLDADOS CAPTURADOS
- - (OK) APOS O FIM DO JOGO, OFERECER RECOMECO
- BUGS
- :: (OK) Quando a pessoa digita mais de um caracter invalido em Tablut::readTurnInput();
- retorna n cin's. Provavelmente eh pq o metodo deveria poder receber um vetor de
- caracteres ao inves de apenas um caracter so.
- :: (OK) Escreve quando uma peca eh capturada o numero errado de pecas totais ja capturadas
- pelo exercito. Porem, na tela final mostra tudo certo.
- :: (OK) hasNoPiecesLeft() deve verificar se o rei pode se mover tambem, e nao apenas se acabaram
- os jogadores. Alem disso, esta sendo retornado o jogador contrario.
- :: (OK) Validação completa das coordenadas => Se é um número, e se o número está entre 0 e 8
- :: (OK) Movendo o castelo do centro, apresenta mensagem de erro incorreta.
- **/
Add Comment
Please, Sign In to add comment