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 de 1 a 8) e a matriz interna do Board.
  • ChessPiece: Estende Piece, adicionando a identidade cromática (Color.WHITE ou Color.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:

  1. Localizar o Rei: Itera sobre as peças ativas do jogador atual até encontrar a peça do tipo King.
  2. Varredura de Ameaças: Itera sobre todas as peças do oponente ainda em jogo. Se a posição do Rei estiver marcada como true na matriz possibleMoves() de qualquer peça adversária, a partida está em Xeque.
  3. 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("================================================================================");
    }
}