Especialização em Sistemas com Python & POO com Type Hints • Capítulo 19


🗺️ Mapa Conceitual do Tópico

flowchart TD
    subgraph BOARD_DOMAIN["Domínio do Tabuleiro e Coordenadas"]
        COORD["Notação Algébrica ('a1'..'h8') ↔ Matriz 2D [0..7, 0..7]\nConversão Algorítmica r = 8 - rank, c = ord(col) - ord('a')"]
        BOARD["Classe Tabuleiro\nGrade Bidimensional 8x8 de Ponteiros (Peca | None)"]
    end

    subgraph PIECES_POLY["Hierarquia Polimórfica de Peças"]
        PECA["Classe Abstrata Peca (ABC)\n#Cor cor · #Tabuleiro tabuleiro · int qtd_movimentos"]
        SLIDING["Peças Deslizantes (Sliding Pieces)\nTorre (Retas) · Bispo (Diagonais) · Dama (Combinada)"]
        STEPPING["Peças de Passo (Stepping Pieces)\nRei (Vizinhança 1) · Cavalo (Deltas em L: 8 opções) · Peão"]
    end

    subgraph ENGINE["Orquestrador da Partida (Engine)"]
        MATCH["PartidaXadrez (Aggregate Root)\nTurno · Jogador Ativo · Validação de Xeque e Xeque-Mate"]
        ATOMIC_MOVE["executar_movimento(): Simula Lance → Valida Rei Seguro → Confirma"]
    end

    COORD --> BOARD
    BOARD --> PIECES_POLY
    PIECES_POLY --> ENGINE
    ENGINE --> CLI["Renderização no Terminal via Símbolos Unicode e Cores ANSI"]

    style BOARD_DOMAIN fill:#ede7f6,stroke:#512da8,stroke-width:2px
    style PIECES_POLY fill:#e1f5fe,stroke:#0288d1,stroke-width:2px
    style ENGINE fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px

♟️ 1. O Desafio Arquitetural do Motor de Xadrez

O Projeto Integrador I desafia o estudante a projetar e implementar um motor de xadrez em Python puro, aplicando todos os pilares consolidados da orientação a objetos corporativa:

  • Herança e Polimorfismo Nominal (abc.ABC): Cada tipo de peça de xadrez implementa de forma independente seu algoritmo de cálculo de movimentos legais.
  • Encapsulamento e Invariantes: O tabuleiro protege sua grade interna bidimensional, impedindo que peças se sobreponham ilegalmente ou saltem para fora das 64 casas.
  • Modelagem de Domínio Rica: Enums semânticos de cor, objetos de posição imutáveis e agregação de regras de jogo (xeque, xeque-mate e promoção).

📐 2. Álgebra de Coordenadas Algébricas e Matriz 2D

O xadrez humano utiliza coordenadas alfanuméricas (colunas de a até h e fileiras de 1 até 8). O computador processa uma matriz bidimensional contígua $8 \times 8$ com índices de $0$ a $7$:

\[\text{linha\_matriz} = 8 - \text{fileira} \quad \text{e} \quad \text{coluna\_matriz} = \text{ord}(\text{coluna}) - \text{ord}('a')\]
from dataclasses import dataclass

@dataclass(frozen=True, slots=True)
class PosicaoXadrez:
    coluna: str  # 'a' a 'h'
    linha: int   # 1 a 8

    def para_indices(self) -> tuple[int, int]:
        r = 8 - self.linha
        c = ord(self.coluna.lower()) - ord('a')
        return r, c

    @classmethod
    def de_indices(cls, r: int, c: int) -> "PosicaoXadrez":
        col = chr(ord('a') + c)
        lin = 8 - r
        return cls(coluna=col, linha=lin)

👑 3. Polimorfismo das Peças: Peças Deslizantes vs Passo Único

A classe abstrata Peca obriga todas as peças a devolverem uma matriz booleana $8 \times 8$ com suas intenções de movimento:

from abc import ABC, abstractmethod

class Peca(ABC):
    def __init__(self, tabuleiro: "Tabuleiro", cor: "Cor") -> None:
        self.tabuleiro = tabuleiro
        self.cor = cor
        self.qtd_movimentos: int = 0

    @abstractmethod
    def movimentos_possiveis(self) -> list[list[bool]]:
        """Retorna matriz 8x8 onde True indica casas alcançáveis."""
        ...

Algoritmos de Deslocamento:

  1. Peças Deslizantes (Sliding - Torre, Bispo, Dama): Projetam raios em direções vetoriais $(\Delta r, \Delta c)$ até encontrar a borda do tabuleiro ou outra peça. Se for adversária, marca a captura e interrompe o raio; se for aliada, interrompe imediatamente antes.
  2. Peças de Salto (Stepping - Rei e Cavalo): Avaliam um conjunto finito de vetores discretos (o Cavalo possui exatamente 8 saltos em L possíveis: $(\pm 1, \pm 2)$ e $(\pm 2, \pm 1)$), testando se a casa de pouso é livre ou abriga adversário.

🛡️ 4. O Agregado Raiz PartidaXadrez e a Validação de Xeque

A inteligência da partida reside em um ciclo em três tempos:

  1. O jogador escolhe a peça de origem e o destino desejado.
  2. A partida simula o movimento provisoriamente no tabuleiro.
  3. Se o movimento deixar o próprio Rei do jogador sob ataque (em estado de Xeque), o lance é imediatamente desfeito (Rollback) e uma exceção de domínio XadrezError("Você não pode se colocar em xeque!") é lançada.
sequenceDiagram
    participant Jogador
    participant Engine as PartidaXadrez
    participant Tabuleiro

    Jogador->>Engine: executar_jogada(e2, e4)
    Engine->>Tabuleiro: mover_provisorio(e2, e4)
    Engine->>Engine: testar_rei_em_xeque(Cor.BRANCA)
    alt Rei sob Ataque
        Engine->>Tabuleiro: desfazer_movimento()
        Engine-->>Jogador: Erro: Lance ilegal (Rei em Xeque)
    else Rei Seguro
        Engine->>Engine: confirmar_captura_e_avancar_turno()
        Engine-->>Jogador: Lance Válido (Vez das Pretas)
    end