Guest User

Untitled

a guest
Jun 2nd, 2018
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 35.99 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <cctype>
  4. #include "validate.cpp"
  5.  
  6. using namespace std;
  7.  
  8. /**
  9. * Definicoes das constantes que armazenam quais caracteres serao mostrados
  10. * na tela para representar os diferentes tipos de pecas do tabuleiro.
  11. */
  12. #define KING 'R' // Rei
  13. #define WHITE 'S' // Suecos
  14. #define BLACK 'M' // Moscovitas
  15. #define EMPTY ' ' // Espaco em branco
  16. #define CASTLE 'C' // Castelo
  17.  
  18. /**
  19. * A classe Tablut e a classe que estrutura o jogo, com suas propriedades
  20. * e metodos.
  21. *
  22. * @author Rafael Marin <rafael@rafaelmarin.net>
  23. */
  24. class Tablut {
  25.  
  26. private:
  27. /**
  28. * As strings _playerOne e _playerTwo gravam os nomes dos jogadores.
  29. */
  30. string _playerOne, _playerTwo;
  31.  
  32. /**
  33. * A string _currentPlayer grava o nome do jogador atual.
  34. */
  35. string _currentPlayer;
  36.  
  37. /**
  38. * A matriz _map e o tabuleiro do jogo, onde serao feitas as modificacoes
  39. * e as jogadas.
  40. */
  41. char _map[9][9];
  42.  
  43. /**
  44. * As propriedades _capturedWhites e _capturedBlacks contam quantas
  45. * pecas, de suas cores respectivas, foram capturadas pelo adversario.
  46. */
  47. int _capturedWhites;
  48. int _capturedBlacks;
  49.  
  50. /**
  51. * _log e onde ficarao gravadas as mensagens de erro do jogo
  52. */
  53. string _log;
  54.  
  55. /**
  56. * Metodos relacionados ao nivel mais baixo de manipulacao
  57. * do jogo, como alterar o log, escrever na tela e limpar a tela.
  58. */
  59. void changePlayer();
  60. void clearLog();
  61. void drawMap();
  62. void drawScreen();
  63. void getLog();
  64. void invertPositions(int,int,int,int);
  65. void populateMap();
  66. void setLog(string);
  67. void deleteInstance();
  68.  
  69. /**
  70. * Metodos relacionados com as operacoes internas de validacao e
  71. * modificacao das propriedades da classe, eventos do jogo entre outras.
  72. */
  73. bool capturePieces(int,int,int,int);
  74. void endOfGame(string,string);
  75. int getKingPositionX();
  76. int getKingPositionY();
  77. bool movePiece(int,int,int,int);
  78.  
  79. /**
  80. * Metodos de validacao das regras do jogo.
  81. */
  82. bool hasNoPiecesLeft();
  83. bool hasPiece(int,int);
  84. bool isEmpty(int,int);
  85. bool isInLineOrColumn(int,int,int,int);
  86. bool isKingOnBorder();
  87. bool isKingSurrounded();
  88. bool isMovingCastle(int,int);
  89. bool isMovingKingFromCenter(int,int);
  90. bool isMovingPieceToCenter(int,int);
  91. bool isMovingMoreThanOnePieceAwayFromTheCastle(int,int);
  92. bool isOwner(int,int);
  93. bool isPassingOver(int,int,int,int);
  94. bool isPassingOverTheCastle(int,int,int,int);
  95.  
  96. /**
  97. * Metodos utilizados pelo jogo em um nivel mais alto, geralmente
  98. * podem requerer a entrada de dados pelo usuario.
  99. */
  100. void readTurnInput();
  101.  
  102. public:
  103. /**
  104. * Tablut() define o metodo construtor da classe
  105. */
  106. Tablut();
  107. };
  108.  
  109. /**
  110. * O metodo Tablut::Tablut() e o construtor da classe Tablut, e ele desenha a tela inicial,
  111. * solicita os nomes dos dois jogadores, e entao chama o metodo Tablut::drawScreen()
  112. * que faz a jogatina comecar. :D
  113. *
  114. * @author Rafael Marin <rafael@rafaelmarin.net>
  115. * @return {Void}
  116. */
  117. Tablut::Tablut(){
  118. system("clear");
  119. string player1, player2;
  120.  
  121. //system("color 0F");
  122.  
  123. cout << endl << endl;
  124. cout << " 88 88 " << endl;
  125. cout << " ,d 88 88 ,d " << endl;
  126. cout << " 88 88 88 88 " << endl;
  127. cout << " MM88MMM ,adPPYYba, 88,dPPYba, 88 88 88 MM88MMM " << endl;
  128. cout << " 88 `Y8 88P' '8a 88 88 88 88 " << endl;
  129. cout << " 88 ,adPPPPP88 88 d8 88 88 88 88 " << endl;
  130. cout << " 88, 88, ,88 88b, ,a8' 88 '8a, ,a88 88, " << endl;
  131. cout << " 'Y888 `'8bbdP'Y8 8Y'Ybbd8'' 88 `'YbbdP'Y8 'Y888 " << endl;
  132. cout << " 2008 Rafael Marin Bortolotto" << endl << endl;
  133.  
  134. //textcolor(YELLOW);
  135.  
  136. /**
  137. * Solicita o nome do primeiro jogador
  138. */
  139. cout << " Digite o nome do primeiro jogador: ";
  140. getline(cin,player1);
  141. while(player1=="" || player1 == " "){
  142. cout << " (#) Seu nome não pode ser em branco.\n\n Digite o nome do primeiro jogador: ";
  143. getline(cin,player1);
  144. }
  145.  
  146. cout << " " << player1 << " será os Suecos ("<<WHITE<<"), que devem DEFENDER o Rei ("<<KING<<"). " << endl << endl;
  147.  
  148. /**
  149. * Solicita o nome do segundo jogador ateh que os nomes
  150. * sejam diferentes.
  151. */
  152. cout << " Digite o nome do segundo jogador: ";
  153. getline(cin,player2);
  154. while(player2=="" || player2 == " "){
  155. cout << " (#) Seu nome não pode ser em branco.\n\n Digite o nome do segundo jogador: ";
  156. getline(cin,player2);
  157. }
  158. while(player1==player2){
  159. cout << " (#) Cada jogador deve ter um nome diferente.\n\n Digite o nome do segundo jogador: ";
  160. getline(cin,player2);
  161. }
  162. cout << " " << player2 << " ficará com os Moscovitas ("<<BLACK<<"), que devem ATACAR o Rei ("<<KING<<"). " << endl << endl;
  163.  
  164. /**
  165. * Pressione qualquer tecla para continuar.
  166. */
  167. cout << " Pressione qualquer tecla para continuar.";
  168. cin.get();
  169. //system("pause");
  170.  
  171. // Define o jogador 1
  172. this->_playerOne = player1;
  173.  
  174. // Define o jogador 2
  175. this->_playerTwo = player2;
  176.  
  177. // Peças pretas capturadas
  178. this->_capturedBlacks = 0;
  179.  
  180. // Peças brancas capturadas
  181. this->_capturedWhites = 0;
  182.  
  183. // O jogador atual e o primeiro jogador
  184. this->_currentPlayer = this->_playerOne;
  185.  
  186. // Preenche o tabuleiro com as posicoes iniciais das pecas
  187. this->populateMap();
  188.  
  189. // Desenha a tela pela primeira vez
  190. this->drawScreen();
  191. }
  192.  
  193. /**
  194. * O metodo Tablut::changePlayer() alterna o jogador atual entre os dois jogadores.
  195. *
  196. * @author Rafael Marin <rafael@rafaelmarin.net>
  197. * @return {Void}
  198. */
  199. void Tablut::changePlayer(){
  200. this->_currentPlayer = (this->_currentPlayer == this->_playerOne)? this->_playerTwo : this->_playerOne;
  201. }
  202.  
  203. /**
  204. * O metodo Tablut::clearLog() limpa o log da tela para que as novas mensagens
  205. * sejam escritas na proxima vez que for recarregada.
  206. *
  207. * @author Rafael Marin <rafael@rafaelmarin.net>
  208. * @return {Void}
  209. */
  210. void Tablut::clearLog(){
  211. this->_log = "";
  212. }
  213.  
  214. /**
  215. * O metodo Tablut::drawMap() desenha o tabuleiro na tela.
  216. *
  217. * @author Rafael Marin <rafael@rafaelmarin.net>
  218. * @return {Void}
  219. */
  220. void Tablut::drawMap() {
  221. cout << endl << endl << " 0 1 2 3 4 5 6 7 8 " << endl;
  222. cout << " ------------------------------------" << endl;
  223. for(int i=0; i<9; i++){
  224. cout << " " << i << " | ";
  225. for(int j=0;j<9;j++){
  226. cout << this->_map[i][j] << " | ";
  227. }
  228. cout << endl << " ------------------------------------" << endl;
  229. }
  230. }
  231.  
  232. /**
  233. * O metodo Tablut::drawScreen() faz a limpeza da tela e recria a tela
  234. * a cada jogada, desenhando a situacao atual do tabuleiro e das pecas,
  235. * com espaco ainda para o log de mensagens e para a entrada do usuario.
  236. *
  237. * @author Rafael Marin <rafael@rafaelmarin.net>
  238. * @return {Void}
  239. */
  240. void Tablut::drawScreen() {
  241. system("clear");
  242. //system("color 0F");
  243.  
  244. this->drawMap();
  245. this->getLog();
  246. this->clearLog();
  247.  
  248. //textcolor(YELLOW);
  249. cout << " " << this->_currentPlayer << ", você joga." << endl;
  250.  
  251. // Chama a entrada do usuario
  252. this->readTurnInput();
  253. }
  254.  
  255. /**
  256. * O metodo Tablut::getLog() retorna o log de mensagens de erro e avisos
  257. * definidos pelo programa ate entao.
  258. *
  259. * @author Rafael Marin <rafael@rafaelmarin.net>
  260. * @return {Void}
  261. */
  262. void Tablut::getLog() {
  263. //textcolor(LIGHTRED);
  264. cout << this->_log << endl;
  265. //textcolor(YELLOW);
  266. }
  267.  
  268. /**
  269. * O metodo Tablut::invertPositions() faz a troca entre as pecas
  270. * que estao na posicao [fromX,fromY] no tabuleiro com as pecas que
  271. * estao na posicao [toX,toY].
  272. *
  273. * @author Rafael Marin <rafael@rafaelmarin.net>
  274. * @param {Integer} fromX Coordenada X de origem da peca
  275. * @param {Integer} fromY Coordenada Y de origem da peca
  276. * @param {Integer} toX Coordenada X de destino da peca
  277. * @param {Integer} toY Coordenada Y de destino da peca
  278. * @return {Void}
  279. */
  280. void Tablut::invertPositions(int fromX, int fromY, int toX, int toY){
  281. char aux = this->_map[fromX][fromY];
  282. this->_map[fromX][fromY] = this->_map[toX][toY];
  283. this->_map[toX][toY] = aux;
  284. }
  285.  
  286. /**
  287. * O metodo Tablut::populateMap() e o procedimento que popula o mapa inicial
  288. * do jogo, assim que a classe for instanciada.
  289. *
  290. * @author Rafael Marin <rafael@rafaelmarin.net>
  291. * @return {Void}
  292. */
  293. void Tablut::populateMap() {
  294.  
  295. /* {
  296. {EMPTY, EMPTY, EMPTY, BLACK, BLACK, BLACK, EMPTY, EMPTY, EMPTY},
  297. {EMPTY, EMPTY, EMPTY, EMPTY, BLACK, EMPTY, EMPTY, EMPTY, EMPTY},
  298. {EMPTY, EMPTY, EMPTY, EMPTY, WHITE, EMPTY, EMPTY, EMPTY, EMPTY},
  299. {BLACK, EMPTY, EMPTY, EMPTY, WHITE, EMPTY, EMPTY, EMPTY, BLACK},
  300. {BLACK, BLACK, WHITE, WHITE, KING, WHITE, WHITE, BLACK, BLACK},
  301. {BLACK, EMPTY, EMPTY, EMPTY, WHITE, EMPTY, EMPTY, EMPTY, BLACK},
  302. {EMPTY, EMPTY, EMPTY, EMPTY, WHITE, EMPTY, EMPTY, EMPTY, EMPTY},
  303. {EMPTY, EMPTY, EMPTY, EMPTY, BLACK, EMPTY, EMPTY, EMPTY, EMPTY},
  304. {EMPTY, EMPTY, EMPTY, BLACK, BLACK, BLACK, EMPTY, EMPTY, EMPTY}
  305. };*/
  306.  
  307. this->_map[0][0] = EMPTY;
  308. this->_map[0][1] = EMPTY;
  309. this->_map[0][2] = EMPTY;
  310. this->_map[0][3] = BLACK;
  311. this->_map[0][4] = BLACK;
  312. this->_map[0][5] = BLACK;
  313. this->_map[0][6] = EMPTY;
  314. this->_map[0][7] = EMPTY;
  315. this->_map[0][8] = EMPTY;
  316.  
  317. this->_map[1][0] = EMPTY;
  318. this->_map[1][1] = EMPTY;
  319. this->_map[1][2] = EMPTY;
  320. this->_map[1][3] = EMPTY;
  321. this->_map[1][4] = BLACK;
  322. this->_map[1][5] = EMPTY;
  323. this->_map[1][6] = EMPTY;
  324. this->_map[1][7] = EMPTY;
  325. this->_map[1][8] = EMPTY;
  326.  
  327. this->_map[2][0] = EMPTY;
  328. this->_map[2][1] = EMPTY;
  329. this->_map[2][2] = EMPTY;
  330. this->_map[2][3] = EMPTY;
  331. this->_map[2][4] = WHITE;
  332. this->_map[2][5] = EMPTY;
  333. this->_map[2][6] = EMPTY;
  334. this->_map[2][7] = EMPTY;
  335. this->_map[2][8] = EMPTY;
  336.  
  337. this->_map[3][0] = BLACK;
  338. this->_map[3][1] = EMPTY;
  339. this->_map[3][2] = EMPTY;
  340. this->_map[3][3] = EMPTY;
  341. this->_map[3][4] = WHITE;
  342. this->_map[3][5] = EMPTY;
  343. this->_map[3][6] = EMPTY;
  344. this->_map[3][7] = EMPTY;
  345. this->_map[3][8] = BLACK;
  346.  
  347. this->_map[4][0] = BLACK;
  348. this->_map[4][1] = BLACK;
  349. this->_map[4][2] = WHITE;
  350. this->_map[4][3] = WHITE;
  351. this->_map[4][4] = KING;
  352. this->_map[4][5] = WHITE;
  353. this->_map[4][6] = WHITE;
  354. this->_map[4][7] = BLACK;
  355. this->_map[4][8] = BLACK;
  356.  
  357. this->_map[5][0] = BLACK;
  358. this->_map[5][1] = EMPTY;
  359. this->_map[5][2] = EMPTY;
  360. this->_map[5][3] = EMPTY;
  361. this->_map[5][4] = WHITE;
  362. this->_map[5][5] = EMPTY;
  363. this->_map[5][6] = EMPTY;
  364. this->_map[5][7] = EMPTY;
  365. this->_map[5][8] = BLACK;
  366.  
  367. this->_map[6][0] = EMPTY;
  368. this->_map[6][1] = EMPTY;
  369. this->_map[6][2] = EMPTY;
  370. this->_map[6][3] = EMPTY;
  371. this->_map[6][4] = WHITE;
  372. this->_map[6][5] = EMPTY;
  373. this->_map[6][6] = EMPTY;
  374. this->_map[6][7] = EMPTY;
  375. this->_map[6][8] = EMPTY;
  376.  
  377. this->_map[7][0] = EMPTY;
  378. this->_map[7][1] = EMPTY;
  379. this->_map[7][2] = EMPTY;
  380. this->_map[7][3] = EMPTY;
  381. this->_map[7][4] = BLACK;
  382. this->_map[7][5] = EMPTY;
  383. this->_map[7][6] = EMPTY;
  384. this->_map[7][7] = EMPTY;
  385. this->_map[7][8] = EMPTY;
  386.  
  387. this->_map[8][0] = EMPTY;
  388. this->_map[8][1] = EMPTY;
  389. this->_map[8][2] = EMPTY;
  390. this->_map[8][3] = BLACK;
  391. this->_map[8][4] = BLACK;
  392. this->_map[8][5] = BLACK;
  393. this->_map[8][6] = EMPTY;
  394. this->_map[8][7] = EMPTY;
  395. this->_map[8][8] = EMPTY;
  396. }
  397.  
  398. /**
  399. * O metodo Tablut::setLog() adiciona uma mensagem ao log
  400. * de erros, que sera exibido quando o metodo Tablut::getLog() for chamado.
  401. *
  402. * @author Rafael Marin <rafael@rafaelmarin.net>
  403. * @params {String} message Mensagem a ser adicionada ao log.
  404. * @return {Void}
  405. */
  406. void Tablut::setLog(string message){
  407. this->_log += "\n" + message + "\n";
  408. }
  409.  
  410. /**
  411. * O metodo Tablut::capturePieces() e responsavel por verificar se
  412. * na jogada atual alguma peca foi capturada e entao a captura.
  413. *
  414. * @author Rafael Marin <rafael@rafaelmarin.net>
  415. * @param {Integer} fromX Coordenada X de origem da peca
  416. * @param {Integer} fromY Coordenada Y de origem da peca
  417. * @param {Integer} toX Coordenada X de destino da peca
  418. * @param {Integer} toY Coordenada Y de destino da peca
  419. * @return {Boolean}
  420. */
  421. bool Tablut::capturePieces(int fromX, int fromY, int toX, int toY){
  422. // Se a peca em questao nao for guerreiro, retorna falso
  423. if(this->_map[fromX][fromY] != WHITE && this->_map[fromX][fromY] != BLACK){
  424. return false;
  425. }
  426. // Define qual a cor da peca atual
  427. char sameRole = (this->_map[fromX][fromY] == WHITE)? WHITE : BLACK;
  428. // Define a cor da outra peca, a partir da peca atual
  429. char oppositeRole = (sameRole == WHITE)? BLACK : WHITE;
  430.  
  431. // Conta quantas pecas ja foram capturadas
  432. int capturedPieces = 0;
  433.  
  434. // Define as posicoes a serem pesquisadas
  435.  
  436. int topSame = this->_map[toX-2][toY];
  437. int topOpposite = this->_map[toX-1][toY];
  438.  
  439. int rightSame = this->_map[toX][toY+2];
  440. int rightOpposite = this->_map[toX][toY+1];
  441.  
  442. int bottomSame = this->_map[toX+2][toY];
  443. int bottomOpposite = this->_map[toX+1][toY];
  444.  
  445. int leftSame = this->_map[toX][toY-2];
  446. int leftOpposite = this->_map[toX][toY-1];
  447.  
  448. // Se ha capturas a serem feitas acima
  449. if(topSame==sameRole && topOpposite==oppositeRole){
  450. capturedPieces++;
  451. this->_map[toX-1][toY] = EMPTY;
  452. }
  453. // Se ha capturas a serem feitas a direita
  454. if(rightSame==sameRole && rightOpposite==oppositeRole){
  455. capturedPieces++;
  456. this->_map[toX][toY+1] = EMPTY;
  457. }
  458. // Se ha capturas a serem feitas abaixo
  459. if(bottomSame==sameRole && bottomOpposite==oppositeRole){
  460. capturedPieces++;
  461. this->_map[toX+1][toY] = EMPTY;
  462. }
  463. // Se ha capturas a serem feitas a esquerda
  464. if(leftSame==sameRole && leftOpposite==oppositeRole){
  465. capturedPieces++;
  466. this->_map[toX][toY-1] = EMPTY;
  467. }
  468.  
  469. // Se alguma peca foi capturada
  470. if(capturedPieces > 0){
  471. // Se a peca branca (suecos) capturaram uma peca
  472. if(sameRole == WHITE) {
  473. this->_capturedBlacks += capturedPieces;
  474.  
  475. string message = " (!) Os suecos capturaram ";
  476. if(capturedPieces == 1) {
  477. message += "1 soldado moscovita. Ao todo já\n capturaram ";
  478. } else {
  479. message += capturedPieces + 48;
  480. message += " soldados moscovitas. Ao todo já\n capturaram ";
  481. }
  482. if(this->_capturedBlacks == 1) {
  483. message += "1 soldado moscovita.";
  484. } else {
  485. message += this->_capturedBlacks + 48;
  486. message += " soldados moscovitas.";
  487. }
  488. this->setLog(message);
  489.  
  490. // Se a peca preta (moscovitas) capturaram uma peca.
  491. } else {
  492. this->_capturedWhites += capturedPieces;
  493.  
  494. string message = " (!) Os moscovitas capturaram ";
  495. if(capturedPieces == 1) {
  496. message += "1 soldado sueco. Ao todo já\n capturaram ";
  497. } else {
  498. message += capturedPieces + 48;
  499. message += " soldados suecos. Ao todo já\n capturaram ";
  500. }
  501. if(this->_capturedWhites == 1) {
  502. message += "1 soldado sueco.";
  503. } else {
  504. message += this->_capturedWhites + 48;
  505. message += " soldados suecos.";
  506. }
  507. this->setLog(message);
  508. }
  509.  
  510. // Se houve captura move a peca atual para o local destinado
  511. this->invertPositions(fromX,fromY,toX,toY);
  512. return true;
  513. }
  514. return false;
  515. }
  516.  
  517. /**
  518. * O metodo Tablut::endOfGame() encerra o jogo, retornando para a tela
  519. * principal.
  520. *
  521. * PRECISA SER ACABADO, POIS ALEM DE UMA INTERFACE MELHOR
  522. * TEM QUE DIZER QUEM GANHOU, QUEM PERDEU, IMPRIMIR A AREA DE PECAS
  523. * CAPTURADAS, E EXPLICAR O MOTIVO DA VITORIA/DERROTA.
  524. *
  525. * @author Rafael Marin <rafael@rafaelmarin.net>
  526. * @return {Void}
  527. */
  528. void Tablut::endOfGame(string reason, string winner="") {
  529. system("clear");
  530.  
  531. //system("color 0F");
  532. cout << endl << endl;
  533. cout << " #### ## # # ###### #### # # ###### ##### " << endl;
  534. cout << " # # # # ## ## # # # # # # # # " << endl;
  535. cout << " # # # # ## # ##### # # # # ##### # # " << endl;
  536. cout << " # ### ###### # # # # # # # # ##### " << endl;
  537. cout << " # # # # # # # # # # # # # # " << endl;
  538. cout << " #### # # # # ###### #### ## ###### # # " << endl;
  539. cout << endl << endl;
  540.  
  541. // textcolor(YELLOW);
  542. string messageReason;
  543. if(reason=="kingOnBorder"){
  544. messageReason = " O Rei escapou pela culatra!\n";
  545. messageReason += " Fim de guerra, os suecos ganharam.\n";
  546. messageReason += " Parabéns, "+this->_playerOne+"! Você derrotou os moscovitas.\n";
  547. } else if(reason=="kingSurrounded"){
  548. messageReason = " O Rei foi pego no pulo!\n";
  549. messageReason += " Fim de guerra, os moscovitas ganharam.\n";
  550. messageReason += " Parabéns, "+this->_playerTwo+"! Você derrotou os suecos.\n";
  551. } else if(reason=="noPiecesLeft"){
  552. string attackers = (winner=="white")? "suecos" : "moscovitas";
  553. string defenders = (winner=="white")? "moscovitas" : "suecos";
  554. string winnerPlayer = (winner=="white")? this->_playerOne : this->_playerTwo;
  555.  
  556. messageReason = " Os "+attackers+" capturaram todos os "+defenders+"!\n";
  557. messageReason += " Fim de guerra, os "+attackers+" ganharam.\n";
  558. messageReason += " Parabéns, "+winnerPlayer+"! Você derrotou os "+defenders+".\n";
  559. }
  560.  
  561. cout << messageReason << endl;
  562.  
  563. cout << endl;
  564. cout << " +-------------------+-------------------+" << endl;
  565. cout << " | SUECOS | MOSCOVITAS |" << endl;
  566. cout << " | Capturados | Capturados |" << endl;
  567. cout << " +-------------------+-------------------+" << endl;
  568. cout << " | "<<(int)this->_capturedWhites<<" | "<<(int)this->_capturedBlacks<<" |" << endl;
  569. cout << " +-------------------+-------------------+" << endl;
  570. cout << endl;
  571.  
  572. cout << " --------------------------------------------------" << endl;
  573. cout << " Universidade de Caxias do Sul"<< endl;
  574. cout << " Bacharelado em Tecnologias Digitais"<< endl;
  575. cout << " Programação I 2008/4"<< endl;
  576. cout << " Professor André Luis Martinotto" << endl;
  577. cout << " Desenvolvido por Rafael Marin Bortolotto" << endl;
  578.  
  579. cin.get();
  580.  
  581. //cout << " Pressione qualquer tecla para SAIR\n ";
  582. //system("pause");
  583. exit(1);
  584. }
  585.  
  586. /**
  587. * O metodo Tablut::getKingPositionX() percorre toda a matriz e retorna
  588. * qual a coordenada X (linha) atual do Rei.
  589. *
  590. * @author Rafael Marin <rafael@rafaelmarin.net>
  591. * @return {Integer}
  592. */
  593. int Tablut::getKingPositionX() {
  594. int position;
  595. for(int i=0; i<9; i++){
  596. for(int j=0;j<9;j++){
  597. if(this->_map[i][j] == KING) {
  598. return i;
  599. }
  600. }
  601. }
  602. }
  603.  
  604. /**
  605. * O metodo Tablut::getKingPositionY() percorre toda a matriz e retorna
  606. * qual a coordenada Y (coluna) atual do Rei.
  607. *
  608. * @author Rafael Marin <rafael@rafaelmarin.net>
  609. * @return {Integer}
  610. */
  611. int Tablut::getKingPositionY() {
  612. int position;
  613. for(int i=0; i<9; i++){
  614. for(int j=0;j<9;j++){
  615. if(this->_map[i][j] == KING) {
  616. return j;
  617. }
  618. }
  619. }
  620. }
  621.  
  622. /**
  623. * O metodo Tablut::movePiece() faz as validacoes necessarias e efetua
  624. * a movimentacao da peca caso as validacoes forem verdadeiras.
  625. *
  626. * @author Rafael Marin <rafael@rafaelmarin.net>
  627. * @param {Integer} fromX Coordenada X de origem da peca
  628. * @param {Integer} fromY Coordenada Y de origem da peca
  629. * @param {Integer} toX Coordenada X de destino da peca
  630. * @param {Integer} toY Coordenada Y de destino da peca
  631. * @return {Boolean}
  632. */
  633. bool Tablut::movePiece(int fromX, int fromY, int toX, int toY){
  634.  
  635. // Se a peca de origem for vazia
  636. if(this->isEmpty(fromX,fromY)){
  637. this->setLog(" (#) Nao ha nenhuma peca para ser movida no local selecionado.");
  638. return false;
  639. }
  640. // Se a peca de origem pertence ao usuario
  641. if(!this->isOwner(fromX,fromY)){
  642. this->setLog(" (#) Voce nao pode mover esta peca pois ela pertence ao outro jogador.");
  643. return false;
  644. }
  645. // Se ha outra peca na coordenada de destino
  646. if(this->hasPiece(toX,toY)){
  647. this->setLog(" (#) Ja existe uma peca no local onde voce pretendia coloca-la.");
  648. return false;
  649. }
  650. // Se a coordenada de destino e horizontal ou vertical
  651. if(!this->isInLineOrColumn(fromX,fromY,toX,toY)){
  652. this->setLog(" (#) A peca so pode ser movida horizontalmente ou verticalmente.");
  653. return false;
  654. }
  655. // Se a peca esta passando por cima de outra
  656. if(this->isPassingOver(fromX,fromY,toX,toY)){
  657. this->setLog(" (#) Voce nao pode passar por cima de outra peca. ");
  658. return false;
  659. }
  660. // Se esta tentando mudar o rei de lugar
  661. if(this->isMovingKingFromCenter(fromX,fromY)){
  662. this->invertPositions(fromX,fromY,toX,toY);
  663. this->_map[4][4] = CASTLE;
  664. return true;
  665. }
  666. // Se esta tentando mover para o centro
  667. if(this->isMovingPieceToCenter(toX,toY)){
  668. this->setLog(" (#) Nenhuma peca, nem o rei, pode ser movido para o centro.");
  669. return false;
  670. }
  671. // Se capturou alguma peca retorna verdadeiro pois ja fez o movimento da peca
  672. if(this->capturePieces(fromX,fromY,toX,toY)){
  673. return true;
  674. }
  675. // Se a peca passou por cima do castelo
  676. if(this->isPassingOverTheCastle(fromX, fromY, toX, toY)){
  677. // Se passou, soh pode cair na casa logo ao lado
  678. if(this->isMovingMoreThanOnePieceAwayFromTheCastle(toX, toY)){
  679. this->setLog(" (#) Ao passar de cima do castelo, voce so pode colocar a peca\n imediatamente em seguida dele.");
  680. return false;
  681. }
  682. }
  683. // Se esta tentando mover o castelo do centro do tabuleiro
  684. if(this->isMovingCastle(fromX,fromY)){
  685. this->setLog(" (#) Voce nao pode mover o castelo do centro.");
  686. return false;
  687. }
  688.  
  689. // Se passar nas validacoes anteriores
  690. this->invertPositions(fromX,fromY,toX,toY);
  691. return true;
  692. }
  693.  
  694. /**
  695. * O metodo Tablut::hasNoPiecesLeft() verifica se as pecas do jogador atual
  696. * acabaram, ou seja, que ele perdeu o jogo.
  697. *
  698. * @author Rafael Marin <rafael@rafaelmarin.net>
  699. * @return {Boolean}
  700. */
  701. bool Tablut::hasNoPiecesLeft(){
  702. char playerRole = (this->_currentPlayer == this->_playerOne)? WHITE : BLACK;
  703. int pieces = 0;
  704. for(int i=0; i<9; i++){
  705. for(int j=0; j<9; j++){
  706. if(this->_map[i][j]==playerRole)
  707. pieces++;
  708. }
  709. }
  710. if(pieces==0 && this->isKingSurrounded())
  711. return true;
  712. return false;
  713. }
  714.  
  715. /**
  716. * Verifica se o objeto na coordenada especificada e nulo
  717. * ou nao. Se o objeto for nulo, significa que esta posicao
  718. * no tabuleiro esta vaga.
  719. *
  720. * @author Rafael Marin <rafael@rafaelmarin.net>
  721. * @param {Integer} x Coordenada X da peca
  722. * @param {Integer} y Coordenada Y da peca
  723. * @return {Boolean}
  724. */
  725. bool Tablut::hasPiece(int x, int y){
  726. if(this->_map[x][y] == EMPTY || this->_map[x][y] == CASTLE)
  727. return false;
  728. return true;
  729. }
  730.  
  731. /**
  732. * O metodo Tablut::isEmpty() verifica se a casa desejada esta
  733. * em branco ou nao.
  734. *
  735. * @author Rafael Marin <rafael@rafaelmarin.net>
  736. * @param {Integer} x Coordenada X da casa solicitada
  737. * @param {Integer} y Coordenada Y da casa solicitada
  738. * @return {Boolean}
  739. */
  740. bool Tablut::isEmpty(int x, int y){
  741. if(this->_map[x][y] == EMPTY)
  742. return true;
  743. return false;
  744. }
  745.  
  746. /**
  747. * O metodo Tablut::isInLineOrColumn() verifica se a peca na
  748. * posicao to esta na mesma linha ou coluna da peca from, indicando
  749. * que a movimentacao pode ocorrer.
  750. *
  751. * @author Rafael Marin <rafael@rafaelmarin.net>
  752. * @param {Integer} fromX Coordenada X de origem da peca
  753. * @param {Integer} fromY Coordenada Y de origem da peca
  754. * @param {Integer} toX Coordenada X de destino da peca
  755. * @param {Integer} toY Coordenada Y de destino da peca
  756. * @return {Boolean}
  757. */
  758. bool Tablut::isInLineOrColumn(int fromX, int fromY, int toX, int toY){
  759. if((fromX==toX && fromY!=toY) || (fromY==toY && fromX!=toX))
  760. return true;
  761. return false;
  762. }
  763.  
  764. /**
  765. * O metodo Tablut::isKingOnBorder() verifica se o rei esta em uma
  766. * das bordas do tabuleiro.
  767. *
  768. * @author Rafael Marin <rafael@rafaelmarin.net>
  769. * @return {Boolean}
  770. */
  771. bool Tablut::isKingOnBorder() {
  772. int x = this->getKingPositionX();
  773. int y = this->getKingPositionY();
  774.  
  775. if(x == 0 || y == 0 || x == 8 || y==8)
  776. return true;
  777. return false;
  778. }
  779.  
  780. /**
  781. * O metodo Tablut::isKingSurrounded() verifica se o rei esta cercado
  782. * de pecas pretas ou nao. Se estiver, quer dizer que o jogador das pecas
  783. * brancas ganhou.
  784. *
  785. * @author Rafael Marin <rafael@rafaelmarin.net>
  786. * @return {Boolean}
  787. */
  788. bool Tablut::isKingSurrounded() {
  789. int x = this->getKingPositionX();
  790. int y = this->getKingPositionY();
  791.  
  792. if(!this->isKingOnBorder()) {
  793. char top = this->_map[x][y-1];
  794. char bottom = this->_map[x][y+1];
  795. char left = this->_map[x-1][y];
  796. char right = this->_map[x+1][y];
  797.  
  798. if((top==BLACK || top==CASTLE) && (bottom==BLACK || bottom==CASTLE) && (left==BLACK || left==CASTLE) && (right==BLACK || right==CASTLE))
  799. return true;
  800. return false;
  801. }
  802. return false;
  803. }
  804.  
  805. /**
  806. * O metodo Tablut::isMovingCastle() verifica se o jogador esta tentando
  807. * mover o castelo do centro do tabuleiro, o que nao eh permitido.
  808. *
  809. * @author Rafael Marin <rafael@rafaelmarin.net>
  810. * @param {Array} x Coordenada X de origem da peca
  811. * @param {Array} y Coordenada Y de origem da peca
  812. * @return {Boolean}
  813. */
  814. bool Tablut::isMovingCastle(int x, int y){
  815. if(x==4 && y==4 && this->_map[4][4]==CASTLE)
  816. return true;
  817. return false;
  818. }
  819.  
  820. /**
  821. * O metodo Tablut::isMovingKingFromCenter() verifica se o jogador esta tentando
  822. * mover o rei do centro, se ele selecionou a posicao do centro.
  823. *
  824. * @author Rafael Marin <rafael@rafaelmarin.net>
  825. * @param {Array} x Coordenada X de origem da peca
  826. * @param {Array} y Coordenada Y de origem da peca
  827. * @return {Boolean}
  828. */
  829. bool Tablut::isMovingKingFromCenter(int x, int y){
  830. if(x==4 && y==4 && this->_map[4][4]==KING)
  831. return true;
  832. return false;
  833. }
  834.  
  835. /**
  836. * O metodo Tablut::isMovingMoreThanOnePieceAwayFromTheCastle() verifica se a peca
  837. * que cruzou sobre o castelo foi colocada na casa logo em seguida, pois e a unica
  838. * posicao valida para essa jogada.
  839. *
  840. * @author Rafael Marin <rafael@rafaelmarin.net>
  841. * @param {Array} toX Coordenada X da peca
  842. * @param {Array} toY Coordenada Y da peca
  843. * @return {Boolean}
  844. */
  845. bool Tablut::isMovingMoreThanOnePieceAwayFromTheCastle(int toX, int toY){
  846. if((toX==3 && toY==4) || (toX==4 && toY==5) || (toX==5 && toY==4) || (toX==4 && toY==3))
  847. return false;
  848. return true;
  849. }
  850.  
  851. /**
  852. * O metodo Tablut::isMovingPieceToCenter() verifica se a peca atual esta sendo
  853. * movida para a posicao central do tabuleiro. Quem verifica se isso e possivel
  854. * e o metodo Tablut::canMovePieceToCenter().
  855. *
  856. * @author Rafael Marin <rafael@rafaelmarin.net>
  857. * @param {Integer} toX Coordenada X de destino da peca
  858. * @param {Integer} toY Coordenada Y de destino da peca
  859. * @return {Boolean}
  860. */
  861. bool Tablut::isMovingPieceToCenter(int toX, int toY){
  862. if(toX==4 && toY==4)
  863. return true;
  864. return false;
  865. }
  866.  
  867. /**
  868. * O metodo Tablut::isOwner() verifica se o jogador atual pode mexer
  869. * na peca escolhida, pois o jogador das pecas pretas nao pode mexer na posicao
  870. * do rei nem das brancas e vice-versa.
  871. *
  872. * @author Rafael Marin <rafael@rafaelmarin.net>
  873. * @param {Integer} x Coordenada X da peca solicitada
  874. * @param {Integer} y Coordenada Y da peca solicitada
  875. * @return {Boolean}
  876. */
  877. bool Tablut::isOwner(int x, int y){
  878. if(this->_currentPlayer == this->_playerOne){
  879. if(this->_map[x][y] == KING || this->_map[x][y] == WHITE || this->_map[x][y] == EMPTY || this->_map[x][y]==CASTLE) {
  880. return true;
  881. }
  882. } else {
  883. if(this->_map[x][y] == BLACK || this->_map[x][y] == EMPTY) {
  884. return true;
  885. }
  886. }
  887. return false;
  888. }
  889.  
  890. /**
  891. * O metodo Tablut::isPassingOver() verifica se a peca a ser movida
  892. * passara por cima de outras pecas, o que nao e permitido no jogo.
  893. *
  894. * @author Rafael Marin <rafael@rafaelmarin.net>
  895. * @param {Integer} fromX Coordenada X de origem da peca
  896. * @param {Integer} fromY Coordenada Y de origem da peca
  897. * @param {Integer} toX Coordenada X de destino da peca
  898. * @param {Integer} toY Coordenada Y de destino da peca
  899. * @return {Boolean}
  900. */
  901. bool Tablut::isPassingOver(int fromX, int fromY, int toX, int toY){
  902. bool isPassing = false;
  903.  
  904. // Se esta movendo na linha
  905. if(fromX==toX){
  906. int major = (fromY > toY)? fromY : toY;
  907. int minor = (fromY > toY)? toY : fromY;
  908. int line = fromX;
  909.  
  910. for(int i=minor+1;i<major; i++){
  911. if(this->_map[line][i]!=EMPTY && this->_map[line][i]!=CASTLE)
  912. isPassing = true;
  913. }
  914.  
  915. // Se esta movendo na coluna
  916. } else {
  917. int major = (fromX > toX)? fromX : toX;
  918. int minor = (fromX > toX)? toX : fromX;
  919. int column = fromY;
  920.  
  921. for(int i=minor+1;i<major; i++){
  922. if(this->_map[i][column]!=EMPTY && this->_map[i][column]!=CASTLE)
  923. isPassing = true;
  924. }
  925. }
  926. return isPassing;
  927. }
  928.  
  929. /**
  930. * O metodo Tablut::isPassingOverTheCastle() verifica se a peca a ser movida
  931. * passa por cima do castelo. A partir dessa verificacao sera feita uma segunda
  932. * verificacao, pelo metodo Tablut::isMovingMoreThanOnePieceAwayFromTheCastle(),
  933. * que entao vai verificar se a peca esta sendo movida para mais de uma casa de
  934. * distancia do castelo.
  935. *
  936. * @author Rafael Marin <rafael@rafaelmarin.net>
  937. * @param {Integer} fromX Coordenada X de origem da peca
  938. * @param {Integer} fromY Coordenada Y de origem da peca
  939. * @param {Integer} toX Coordenada X de destino da peca
  940. * @param {Integer} toY Coordenada Y de destino da peca
  941. * @return {Boolean}
  942. */
  943. bool Tablut::isPassingOverTheCastle(int fromX, int fromY, int toX, int toY){
  944. bool isPassingOverCastle = false;
  945.  
  946. // Se esta movendo na linha
  947. if(fromX==toX){
  948.  
  949. int major = (fromY > toY)? fromY : toY;
  950. int minor = (fromY > toY)? toY : fromY;
  951. int line = fromX;
  952.  
  953. for(int i=minor+1;i<major; i++){
  954. if(this->_map[line][i]==CASTLE)
  955. isPassingOverCastle = true;
  956. }
  957.  
  958. // Se esta movendo na coluna
  959. } else {
  960.  
  961. int major = (fromX > toX)? fromX : toX;
  962. int minor = (fromX > toX)? toX : fromX;
  963. int column = fromY;
  964.  
  965. for(int i=minor+1; i<major; i++){
  966. if(this->_map[i][column]==CASTLE)
  967. isPassingOverCastle = true;
  968. }
  969.  
  970. }
  971. return isPassingOverCastle;
  972. }
  973.  
  974. /**
  975. * O metodo Tablut::readTurnInput() le as coordenadas digitadas pelo
  976. * usuario na rodada e efetua as movimentacoes, se necessarias. Verifica
  977. * as condicoes necessarias para encerrar o jogo, e encerra o jogo caso
  978. * alguma dessas condicoes seja verdadeira.
  979. *
  980. * @author Rafael Marin <rafael@rafaelmarin.net>
  981. * @return {Void}
  982. */
  983. void Tablut::readTurnInput() {
  984. char fromX[100], fromY[100], toX[100], toY[100];
  985.  
  986. //textcolor(YELLOW);
  987.  
  988. /**
  989. * Le as coordenadas de origem
  990. */
  991. cout << " Digite as coordenadas da peca a ser movida:" << endl;
  992. cout << " Linha: ";
  993. cin >> fromX;
  994. while(!Validate::isNumber(fromX[0]) || !Validate::isCoordinate(fromX)){
  995. cout << " Linha (0-8): ";
  996. cin >> fromX;
  997. }
  998.  
  999. cout << " Coluna: ";
  1000. cin >> fromY;
  1001. while(!Validate::isNumber(fromY[0]) || !Validate::isCoordinate(fromY)) {
  1002. cout << " Coluna (0-8): ";
  1003. cin >> fromY;
  1004. }
  1005.  
  1006. /**
  1007. * Le as coordenadas de destino
  1008. */
  1009. cout << " Digite as coordenadas do local para colocar a peca: " << endl;
  1010. cout << " Linha: ";
  1011. cin >> toX;
  1012. while(!Validate::isNumber(toX[0]) || !Validate::isCoordinate(toX)){
  1013. cout << " Linha (0-8): ";
  1014. cin >> toX;
  1015. }
  1016.  
  1017. cout << " Coluna: ";
  1018. cin >> toY;
  1019. while(!Validate::isNumber(toY[0]) || !Validate::isCoordinate(toY)) {
  1020. cout << " Coluna (0-8): ";
  1021. cin >> toY;
  1022. }
  1023.  
  1024. /**
  1025. * Se a peca foi movida com sucesso, entao o usuario e
  1026. * trocado para que o proximo usuario jogue e entao a
  1027. * tela principal e recarregada.
  1028. */
  1029.  
  1030. if(this->movePiece(Validate::toInt(fromX[0]),Validate::toInt(fromY[0]),Validate::toInt(toX[0]),Validate::toInt(toY[0]))){
  1031. this->changePlayer();
  1032. }
  1033. if(this->isKingOnBorder()){
  1034. this->endOfGame("kingOnBorder");
  1035. } else if(this->isKingSurrounded()){
  1036. this->endOfGame("kingSurrounded");
  1037. } else if(this->hasNoPiecesLeft()){
  1038. string winner = (this->_currentPlayer==this->_playerOne)? "black" : "white";
  1039. this->endOfGame("noPiecesLeft",winner);
  1040. }
  1041. this->drawScreen();
  1042. }
  1043.  
  1044. /**
  1045. * Funcao inicial do programa
  1046. */
  1047. int main() {
  1048. new Tablut();
  1049. return 0;
  1050. }
  1051.  
  1052. /**
  1053. TO-DO LIST
  1054.  
  1055. - (OK) [PROFESSOR] VERIFICAR SE OS CARACTERES DIGITADOS SAO INTEIROS OU CARACTERES
  1056. - (OK) [PROFESSOR] MELHORAR A INICIALIZACAO DA MATRIZ _map - Nao ha como.
  1057.  
  1058. - (OK) MOVIMENTACOES DO JOGO
  1059. - (OK) quando o rei sai da posicao original, o centro vira o castelo que se
  1060. torna inacessivel para todos os jogadores
  1061. - (OK) o jogador nao pode pular com a peca por cima de outras
  1062. - (OK) quando uma peca for movida alem do castelo ela so pode ficar encostada ao castelo
  1063. - (OK) [PROFESSOR] O REI PODE VOLTAR AO CASTELO? - Nao
  1064.  
  1065. - (OK) ZONA DAS PECAS CAPTURADAS
  1066. - (OK) captura de pecas simples
  1067. - (OK) foi capturada ou se colocou ao meio de duas pecas?
  1068. - (OK) captura de quatro lados do rei (encurralado, fim de jogo)
  1069. - (OK) captura do rei ao lado do castelo (fim de jogo)
  1070. - (OK) todos os soldados rivais foram capturados?
  1071.  
  1072. - (OK) VERIFICAR AS CONDICOES DE TERMINO DE JOGO
  1073. - (OK) o rei chegou ao canto?
  1074. - (OK) o rei foi encurralado?
  1075. - (OK) o rei foi encurralado ao lado do castelo?
  1076.  
  1077. - (OK) AO FIM DO JOGO, DIZER O CAMPEAO E MOSTRAR OS SOLDADOS CAPTURADOS
  1078.  
  1079. - (OK) APOS O FIM DO JOGO, OFERECER RECOMECO
  1080.  
  1081. BUGS
  1082. :: (OK) Quando a pessoa digita mais de um caracter invalido em Tablut::readTurnInput();
  1083. retorna n cin's. Provavelmente eh pq o metodo deveria poder receber um vetor de
  1084. caracteres ao inves de apenas um caracter so.
  1085. :: (OK) Escreve quando uma peca eh capturada o numero errado de pecas totais ja capturadas
  1086. pelo exercito. Porem, na tela final mostra tudo certo.
  1087.  
  1088. :: (OK) hasNoPiecesLeft() deve verificar se o rei pode se mover tambem, e nao apenas se acabaram
  1089. os jogadores. Alem disso, esta sendo retornado o jogador contrario.
  1090.  
  1091. :: (OK) Validação completa das coordenadas => Se é um número, e se o número está entre 0 e 8
  1092.  
  1093. :: (OK) Movendo o castelo do centro, apresenta mensagem de erro incorreta.
  1094.  
  1095. **/
Add Comment
Please, Sign In to add comment