Especialização em Sistemas com Java 21 LTS • Capítulo 19


🎯 Visão Geral dos Exemplos Práticos

Neste laboratório prático, implementaremos exemplos corporativos completos explorando:

  1. Modelagem de Tabuleiro e Peças com POO Pura: arquitetura de classes Board, Piece, Rook, Bishop e King.
  2. Cálculo Matricial Polimórfico de Movimentos Legais: varredura ortogonal e diagonal com detecção de obstáculos e capturas.
  3. Conversão de Notação Algébrica: tradução de coordenadas civis de xadrez (a1 a h8) para índices internos da matriz bidimensional [row][col].

💻 Exemplo 01 — Motor Funcional de Xadrez com Torre, Bispo e Rei

package com.empresa.xadrez;

/**
 * Motor completo de xadrez em modo texto demonstrando herança, polimorfismo e validação matricial.
 */
public class SimuladorPartidaXadrez {

    public enum Cor { BRANCO, PRETO }

    public record Coordenada(int linha, int coluna) {}

    public static class PosicaoXadrez {
        private final char coluna;
        private final int linha;

        public PosicaoXadrez(char coluna, int linha) {
            if (coluna < 'a' || coluna > 'h' || linha < 1 || linha > 8) {
                throw new IllegalArgumentException("Posição de xadrez inválida: " + coluna + linha);
            }
            this.coluna = coluna;
            this.linha = linha;
        }

        public Coordenada paraCoordenadaMatriz() {
            return new Coordenada(8 - linha, coluna - 'a');
        }

        public static PosicaoXadrez deCoordenada(Coordenada coord) {
            return new PosicaoXadrez((char) ('a' + coord.coluna()), 8 - coord.linha());
        }

        @Override
        public String toString() { return "" + coluna + linha; }
    }

    public static abstract class Peca {
        protected Coordenada posicao;
        protected final Cor cor;

        public Peca(Cor cor) { this.cor = cor; }

        public abstract boolean[][] gerarMovimentosValidos(Peca[][] grade);

        public Cor getCor() { return cor; }
        public Coordenada getPosicao() { return posicao; }
        public void setPosicao(Coordenada p) { this.posicao = p; }
    }

    public static class Torre extends Peca {
        public Torre(Cor cor) { super(cor); }

        @Override
        public boolean[][] gerarMovimentosValidos(Peca[][] grade) {
            boolean[][] mat = new boolean[8][8];
            int r = posicao.linha();
            int c = posicao.coluna();

            // Cima
            for (int i = r - 1; i >= 0; i--) {
                if (grade[i][c] == null) mat[i][c] = true;
                else { if (grade[i][c].getCor() != this.cor) mat[i][c] = true; break; }
            }
            // Baixo
            for (int i = r + 1; i < 8; i++) {
                if (grade[i][c] == null) mat[i][c] = true;
                else { if (grade[i][c].getCor() != this.cor) mat[i][c] = true; break; }
            }
            // Esquerda
            for (int j = c - 1; j >= 0; j--) {
                if (grade[r][j] == null) mat[r][j] = true;
                else { if (grade[r][j].getCor() != this.cor) mat[r][j] = true; break; }
            }
            // Direita
            for (int j = c + 1; j < 8; j++) {
                if (grade[r][j] == null) mat[r][j] = true;
                else { if (grade[r][j].getCor() != this.cor) mat[r][j] = true; break; }
            }
            return mat;
        }

        @Override
        public String toString() { return cor == Cor.BRANCO ? "T" : "t"; }
    }

    public static class Bispo extends Peca {
        public Bispo(Cor cor) { super(cor); }

        @Override
        public boolean[][] gerarMovimentosValidos(Peca[][] grade) {
            boolean[][] mat = new boolean[8][8];
            int r = posicao.linha();
            int c = posicao.coluna();

            // Noroeste
            for (int i = r - 1, j = c - 1; i >= 0 && j >= 0; i--, j--) {
                if (grade[i][j] == null) mat[i][j] = true;
                else { if (grade[i][j].getCor() != this.cor) mat[i][j] = true; break; }
            }
            // Nordeste
            for (int i = r - 1, j = c + 1; i >= 0 && j < 8; i--, j++) {
                if (grade[i][j] == null) mat[i][j] = true;
                else { if (grade[i][j].getCor() != this.cor) mat[i][j] = true; break; }
            }
            // Sudoeste
            for (int i = r + 1, j = c - 1; i < 8 && j >= 0; i++, j--) {
                if (grade[i][j] == null) mat[i][j] = true;
                else { if (grade[i][j].getCor() != this.cor) mat[i][j] = true; break; }
            }
            // Sudeste
            for (int i = r + 1, j = c + 1; i < 8 && j < 8; i++, j++) {
                if (grade[i][j] == null) mat[i][j] = true;
                else { if (grade[i][j].getCor() != this.cor) mat[i][j] = true; break; }
            }
            return mat;
        }

        @Override
        public String toString() { return cor == Cor.BRANCO ? "B" : "b"; }
    }

    public static class TabuleiroXadrez {
        private final Peca[][] matriz = new Peca[8][8];

        public void alocarPeca(Peca peca, PosicaoXadrez pos) {
            Coordenada c = pos.paraCoordenadaMatriz();
            matriz[c.linha()][c.coluna()] = peca;
            peca.setPosicao(c);
        }

        public boolean mover(PosicaoXadrez origem, PosicaoXadrez destino) {
            Coordenada cOrig = origem.paraCoordenadaMatriz();
            Coordenada cDest = destino.paraCoordenadaMatriz();

            Peca p = matriz[cOrig.linha()][cOrig.coluna()];
            if (p == null) return false;

            boolean[][] possiveis = p.gerarMovimentosValidos(matriz);
            if (!possiveis[cDest.linha()][cDest.coluna()]) {
                System.out.printf("❌ Movimento ilegal de %s para %s!%n", origem, destino);
                return false;
            }

            // Realiza movimento
            matriz[cDest.linha()][cDest.coluna()] = p;
            matriz[cOrig.linha()][cOrig.coluna()] = null;
            p.setPosicao(cDest);
            System.out.printf("✅ Peça %s movimentada com êxito de %s para %s%n", p, origem, destino);
            return true;
        }

        public void imprimir() {
            System.out.println("    a b c d e f g h");
            System.out.println("   +----------------");
            for (int i = 0; i < 8; i++) {
                System.out.print((8 - i) + "  |");
                for (int j = 0; j < 8; j++) {
                    Peca p = matriz[i][j];
                    System.out.print((p == null ? ". " : p + " "));
                }
                System.out.println("| " + (8 - i));
            }
            System.out.println("   +----------------");
            System.out.println("    a b c d e f g h");
        }
    }

    public static void main(String[] args) {
        System.out.println("================================================================================");
        System.out.println("             SIMULADOR DE MOTOR DE XADREZ CONSOLE (JAVA 21 LTS)                 ");
        System.out.println("================================================================================");

        TabuleiroXadrez jogo = new TabuleiroXadrez();

        // Posicionamento de Peças em notação algébrica
        jogo.alocarPeca(new Torre(Cor.BRANCO), new PosicaoXadrez('a', 1));
        jogo.alocarPeca(new Bispo(Cor.BRANCO), new PosicaoXadrez('c', 1));
        jogo.alocarPeca(new Torre(Cor.PRETO), new PosicaoXadrez('a', 8));

        jogo.imprimir();

        // Tentativa de Movimento Válido da Torre Branca: a1 -> a5
        System.out.println("\n--- Movimento 1: Torre Branca a1 para a5 ---");
        jogo.mover(new PosicaoXadrez('a', 1), new PosicaoXadrez('a', 5));
        jogo.imprimir();

        // Tentativa de Captura: a5 captura a8 (Torre Preta)
        System.out.println("\n--- Movimento 2: Torre Branca a5 captura Torre Preta em a8 ---");
        jogo.mover(new PosicaoXadrez('a', 5), new PosicaoXadrez('a', 8));
        jogo.imprimir();

        System.out.println("================================================================================");
    }
}

📋 Resultado Esperado no Console

================================================================================
             SIMULADOR DE MOTOR DE XADREZ CONSOLE (JAVA 21 LTS)                 
================================================================================
    a b c d e f g h
   +----------------
8  |t . . . . . . . | 8
7  |. . . . . . . . | 7
6  |. . . . . . . . | 6
5  |. . . . . . . . | 5
4  |. . . . . . . . | 4
3  |. . . . . . . . | 3
2  |. . . . . . . . | 2
1  |T . B . . . . . | 1
   +----------------
    a b c d e f g h

--- Movimento 1: Torre Branca a1 para a5 ---
✅ Peça T movimentada com êxito de a1 para a5
    a b c d e f g h
   +----------------
8  |t . . . . . . . | 8
7  |. . . . . . . . | 7
6  |. . . . . . . . | 6
5  |T . . . . . . . | 5
4  |. . . . . . . . | 4
3  |. . . . . . . . | 3
2  |. . . . . . . . | 2
1  |. . B . . . . . | 1
   +----------------
    a b c d e f g h

--- Movimento 2: Torre Branca a5 captura Torre Preta em a8 ---
✅ Peça T movimentada com êxito de a5 para a8
    a b c d e f g h
   +----------------
8  |T . . . . . . . | 8
7  |. . . . . . . . | 7
6  |. . . . . . . . | 6
5  |. . . . . . . . | 5
4  |. . . . . . . . | 4
3  |. . . . . . . . | 3
2  |. . . . . . . . | 2
1  |. . B . . . . . | 1
   +----------------
    a b c d e f g h
================================================================================