Capítulo 19: Projeto Integrador 1: Arquitetura Orientada a Objetos de um Motor de Xadrez em Console
Especialização em Sistemas com Java 21 LTS • Módulo de Banco de Dados e Projetos Integradores
🗺️ Mapa Conceitual do Tópico
classDiagram
class Board {
-int rows
-int columns
-Piece[][] pieces
+placePiece(Piece piece, Position position) void
+removePiece(Position position) Piece
+piece(int row, int column) Piece
+positionExists(Position position) boolean
+thereIsAPiece(Position position) boolean
}
class Piece {
<<abstract>>
#Position position
#Board board
+possibleMoves()* boolean[][]
+possibleMove(Position position) boolean
+isThereAnyPossibleMove() boolean
}
class ChessPiece {
<<abstract>>
-Color color
-int moveCount
+getColor() Color
+increaseMoveCount() void
}
class King {
+possibleMoves() boolean[][]
}
class Rook {
+possibleMoves() boolean[][]
}
class ChessMatch {
-int turn
-Color currentPlayer
-boolean check
-boolean checkMate
-Board board
+performChessMove(ChessPosition source, ChessPosition target) ChessPiece
}
Board o-- Piece : "Composição (8x8)"
Piece <|-- ChessPiece : "extends"
ChessPiece <|-- King : "extends"
ChessPiece <|-- Rook : "extends"
ChessMatch --> Board : "Orquestrador de Regras"
♟️ 1. Arquitetura em Camadas do Motor de Xadrez
O projeto do sistema de xadrez em Java é uma das mais consagradas demonstrações práticas de Orientação a Objetos Pura, exigindo separação estrita de responsabilidades em camadas concêntricas:
1. Camada de Tabuleiro (Baixo Nível - Board Layer)
Focada exclusivamente na mecânica geométrica de uma grade bidimensional de $8 \times 8$:
Position(row, column): Índices numéricos de 0 a 7.Board: Responsável por validar se uma coordenada é válida, se uma casa está ocupada e por alocar ou desalocar ponteiros de peças. Não possui conhecimento sobre regras de xadrez, cores ou turnos.BoardException: Exceção de runtime para tentativas de acesso fora dos limites ou posições já ocupadas.
2. Camada de Xadrez (Alto Nível - Chess Layer)
Implementa a lógica do jogo sob a ótica das regras oficiais da FIDE (Federação Internacional de Xadrez):
ChessPosition(column, row): Mapeamento entre notação algébrica tradicional de xadrez (colunas de'a'a'h', linhas de1a8) e a matriz interna doBoard.ChessPiece: EstendePiece, adicionando a identidade cromática (Color.WHITEouColor.BLACK) e a contagem de movimentos.ChessMatch: A máquina de estados da partida, gerenciando controle de turnos, peças capturadas, teste de xeque (Check), xeque-mate e jogadas especiais.
3. Camada de Apresentação e UI (Console UI Layer)
Lê inputs do usuário no terminal (ex: e2 e4), limpa a tela e renderiza o tabuleiro utilizando códigos de escape ANSI para coloração em consoles modernos.
⚔️ 2. Polimorfismo e Cálculo de Movimentos Possíveis
O coração algorítmico de cada peça é o método abstrato:
public abstract boolean[][] possibleMoves();
Cada peça concreta retorna uma matriz booleana de $8 \times 8$ onde os valores true representam destinos legais para onde a peça pode se mover a partir de sua posição atual:
1. Movimentos Ortogonais (Torre / Rook):
A Torre percorre as quatro direções ortogonais (acima, abaixo, esquerda, direita) em laço contínuo enquanto as casas estiverem desocupadas. Se encontrar uma peça adversária, inclui aquela casa como movimento de captura e interrompe o laço nessa direção.
2. Movimentos Radiais (Rei / King):
O Rei analisa exatamente as 8 casas adjacentes que o circundam, garantindo que não colida com peças da mesma cor e que não se mova para uma casa sob ameaça adversária.
🛡️ 3. Algoritmo de Verificação de Xeque e Xeque-Mate
A detecção de xeque é computada invertendo a perspectiva da partida:
- Localizar o Rei: Itera sobre as peças ativas do jogador atual até encontrar a peça do tipo
King. - Varredura de Ameaças: Itera sobre todas as peças do oponente ainda em jogo. Se a posição do Rei estiver marcada como
truena matrizpossibleMoves()de qualquer peça adversária, a partida está em Xeque. - Xeque-Mate: Se o jogador está em xeque e nenhum movimento possível de nenhuma de suas peças consegue tirar o Rei do estado de xeque, decreta-se o Xeque-Mate.
📊 4. Matriz Comparativa: Modelagem de Motores de Xadrez
| Característica | POO Pura (Matriz de Peças) | Bitboards (64-bit Integers) |
|---|---|---|
| Abstração | Altíssima (Classes, Herança, Polimorfismo) | Baixa (Máscaras binárias em primitivos long) |
| Foco Pedagógico | Excelência em Design Patterns e SOLID | Algoritmos de IA e Teoria de Grafos |
| Desempenho Bruto | ~100.000 posições/segundo | +50.000.000 posições/segundo (Stockfish) |
| Legibilidade e Manutenção | Código limpo, intuitivo e modular | Complexidade matemática de bits avançada |
💻 5. Código de Demonstração Corporativo (Java 21 LTS)
package com.empresa.xadrez;
/**
* Núcleo do motor de xadrez orientado a objetos demonstrando o cálculo polimórfico de Torre e Rei.
*/
public class MotorXadrezConsole {
public enum Cor { BRANCO, PRETO }
public record Posicao(int linha, int coluna) {
public Posicao definirValores(int l, int c) { return new Posicao(l, c); }
}
public static abstract class Peca {
protected Posicao posicao;
protected final Cor cor;
public Peca(Cor cor) {
this.cor = cor;
}
public abstract boolean[][] calcularMovimentosPossiveis(Peca[][] tabuleiro);
public Cor getCor() { return cor; }
public Posicao getPosicao() { return posicao; }
public void setPosicao(Posicao pos) { this.posicao = pos; }
}
public static class Torre extends Peca {
public Torre(Cor cor) { super(cor); }
@Override
public boolean[][] calcularMovimentosPossiveis(Peca[][] tabuleiro) {
boolean[][] mat = new boolean[8][8];
int r = posicao.linha();
int c = posicao.coluna();
// Varredura para Cima
for (int i = r - 1; i >= 0; i--) {
if (tabuleiro[i][c] == null) {
mat[i][c] = true;
} else {
if (tabuleiro[i][c].getCor() != this.cor) mat[i][c] = true; // Captura
break; // Bloqueio
}
}
// Varredura para Baixo
for (int i = r + 1; i < 8; i++) {
if (tabuleiro[i][c] == null) {
mat[i][c] = true;
} else {
if (tabuleiro[i][c].getCor() != this.cor) mat[i][c] = true;
break;
}
}
return mat;
}
@Override
public String toString() { return cor == Cor.BRANCO ? "T" : "t"; }
}
public static class Rei extends Peca {
public Rei(Cor cor) { super(cor); }
@Override
public boolean[][] calcularMovimentosPossiveis(Peca[][] tabuleiro) {
boolean[][] mat = new boolean[8][8];
int[] dLinha = {-1, -1, -1, 0, 0, 1, 1, 1};
int[] dColuna = {-1, 0, 1, -1, 1, -1, 0, 1};
for (int i = 0; i < 8; i++) {
int nl = posicao.linha() + dLinha[i];
int nc = posicao.coluna() + dColuna[i];
if (nl >= 0 && nl < 8 && nc >= 0 && nc < 8) {
if (tabuleiro[nl][nc] == null || tabuleiro[nl][nc].getCor() != this.cor) {
mat[nl][nc] = true;
}
}
}
return mat;
}
@Override
public String toString() { return cor == Cor.BRANCO ? "R" : "r"; }
}
public static void imprimirTabuleiro(Peca[][] tabuleiro) {
System.out.println(" a b c d e f g h");
for (int i = 0; i < 8; i++) {
System.out.print((8 - i) + " ");
for (int j = 0; j < 8; j++) {
if (tabuleiro[i][j] == null) {
System.out.print("- ");
} else {
System.out.print(tabuleiro[i][j] + " ");
}
}
System.out.println((8 - i));
}
System.out.println(" a b c d e f g h");
}
public static void main(String[] args) {
System.out.println("================================================================================");
System.out.println(" MOTOR DE XADREZ ORIENTADO A OBJETOS (JAVA 21 LTS) ");
System.out.println("================================================================================");
Peca[][] tabuleiro = new Peca[8][8];
Torre torreBranca = new Torre(Cor.BRANCO);
torreBranca.setPosicao(new Posicao(7, 0)); // a1
tabuleiro[7][0] = torreBranca;
Rei reiBranco = new Rei(Cor.BRANCO);
reiBranco.setPosicao(new Posicao(7, 4)); // e1
tabuleiro[7][4] = reiBranco;
Torre torrePreta = new Torre(Cor.PRETO);
torrePreta.setPosicao(new Posicao(0, 0)); // a8
tabuleiro[0][0] = torrePreta;
imprimirTabuleiro(tabuleiro);
System.out.println("\nCalculando movimentos possíveis da Torre Branca em a1:");
boolean[][] movs = torreBranca.calcularMovimentosPossiveis(tabuleiro);
for (int l = 0; l < 8; l++) {
for (int c = 0; c < 8; c++) {
if (movs[l][c]) {
char colunaLetra = (char) ('a' + c);
int linhaNumero = 8 - l;
System.out.printf(" ➡️ Movimento legal para: %c%d%s%n",
colunaLetra, linhaNumero, (tabuleiro[l][c] != null ? " [CAPTURA]" : ""));
}
}
}
System.out.println("================================================================================");
}
}