Escreva uma função que verifica se ocorreu xeque em um determinado jogo de xadrez. O tabuleiro de xadrez é representado por uma matriz inteira
. Nesta matriz, o valor 0 indica a ausência de peça em uma determinada posição do tabuleiro. Peças são representadas pelos valores indicados na Tabela 1.
Table 1: Tabela 1: Valores que representam as peças de um jogo de xadrez.\captionsetup{labelformat=empty}
Valor
Peça
1
Peão preto
2
Cavalo preto
3
Torre preta
4
Bispo preto
5
Rei preto
6
Rainha preta
7
Peão branco
8
Cavalo branco
9
Torre branca
10
Bispo branco
11
Rei branco
12
Rainha branca
Table 1: Tabela 1: Valores que representam as peças de um jogo de xadrez.
\captionsetup{labelformat=empty}
| Valor | Peça |
| 1 | Peão preto |
| 2 | Cavalo preto |
| 3 | Torre preta |
| 4 | Bispo preto |
| 5 | Rei preto |
| 6 | Rainha preta |
| 7 | Peão branco |
| 8 | Cavalo branco |
| 9 | Torre branca |
| 10 | Bispo branco |
| 11 | Rei branco |
| 12 | Rainha branca |
Passo 1
O que o problema pede e quais informações são dadas.
- Pede-se uma função que verifica se ocorreu xeque num jogo de xadrez representado por uma matriz inteira
. - A matriz usa o valor
para casa vazia. - As peças são codificadas com os inteiros
até conforme a tabela: -
: Peão preto -
: Cavalo preto -
: Torre preta -
: Bispo preto -
: Rei preto -
: Rainha preta -
: Peão branco -
: Cavalo branco -
: Torre branca -
: Bispo branco -
: Rei branco -
: Rainha branca
-
- Deve-se determinar se um rei está sendo atacado por qualquer peça adversária (i.e., se há xeque). Vou retornar informação para ambos os reis (preto e branco).
- Convenção adotada para orientações do tabuleiro: a matriz é indexada por linhas e colunas com índices inteiros. A linha aumenta para baixo (linha
é o topo, linha o fundo). Nesse sistema: - Peões pretos atacam nas casas
e a partir de . - Peões brancos atacam nas casas
e a partir de .
- Peões pretos atacam nas casas
- Resultado final esperado da função: indicar se o rei preto está em xeque e se o rei branco está em xeque (duas flags booleanas).
Passo 2
Localizar os reis no tabuleiro — por que e como.
- Antes de checar ataques precisamos conhecer as posições exatas dos reis: procurar na matriz o valor do rei preto (
) e do rei branco ( ). - Procedimento prático:
- Percorrer todas as linhas
até e colunas até . - Quando encontrar valor
, guardar como posição do rei preto. - Quando encontrar valor
, guardar como posição do rei branco.
- Percorrer todas as linhas
- Se algum dos reis não for encontrado, a posição é inválida. (Vou assumir que o enunciado dá posições válidas, mas o código pode checar e sinalizar erro.)
Passo 3
Como decidir se uma casa está sendo atacada — ideia geral.
- Um rei está em xeque se existir ao menos uma peça adversária que possa, num movimento legal de ataque, ocupar a casa do rei.
- Em vez de simular movimentos de todas as peças, é mais simples e eficiente testar se a casa do rei é “atacada” segundo os padrões de ataque de cada tipo de peça:
- ataques de peão (padrão fixo),
- saltos de cavalo (padrão fixo),
- ataques deslizantes de torre, bispo e rainha (varrem direções até encontrar um bloqueio),
- ataque pelo rei adversário (caso de casas adjacentes).
- Implementação: escrever uma função auxiliar is_attacked(r,c,attacker_color) que verifica se a casa
é atacada por alguma peça da cor atacante.
Passo 4
Regras de ataque específicas — peões e cavalos (casos simples).
- Peões:
- Se estiver testando se uma casa
é atacada por peões pretos, então verificar se há um peão preto nas casas ou com relação à casa atacada? Cuidado com a orientação! - Usando a convenção adotada (linha aumenta para baixo):
- Um peão preto numa posição
ataca . Logo, para saber se é atacada por peão preto, verificar se existe um peão preto em ou . - Um peão branco numa posição
ataca . Logo, para saber se é atacada por peão branco, verificar se existe um peão branco em ou .
- Um peão preto numa posição
- Em resumo (fórmula prática para is_attacked):
- Se attacker_color é “black”: olhar peças pretas em
e e ver se são peões pretos ( ). - Se attacker_color é “white”: olhar peças brancas em
e e ver se são peões brancos ( ).
- Se attacker_color é “black”: olhar peças pretas em
- Lembre-se de checar limites do tabuleiro antes de acessar a matriz.
- Se estiver testando se uma casa
- Cavalos:
- O cavalo tem 8 saltos: offsets
e . - Para cada um desses offsets, verificar se há um cavalo do atacante (código
para preto, para branco) na casa correspondente.
- O cavalo tem 8 saltos: offsets
Passo 5
Regras de ataque específicas — peças deslizantes: torre, bispo e rainha.
- Conceito: torre, bispo e rainha atacam varrendo retas (linhas, colunas, diagonais) até o primeiro obstáculo. Se o primeiro obstáculo nessa direção é uma peça atacante do tipo compatível, então a casa é atacada por esse tipo.
- Direções para verificar:
- Para torre (e também rainha em modo torre): quatro direções ortogonais:
- cima:
- baixo:
- esquerda:
- direita:
- cima:
- Para bispo (e também rainha em modo bispo): quatro direções diagonais:
-
, , ,
-
- Para torre (e também rainha em modo torre): quatro direções ortogonais:
- Procedimento por direção:
- Partir da casa alvo
, avançar uma casa por vez na direção escolhida (i.e., incrementar e conforme offset) — equivalently, olhar as casas ao longo da reta até encontrar a primeira peça ou sair do tabuleiro. - Se encontrar a primeira peça e ela pertence ao atacante e é do tipo certo (torre para ortogonais, bispo para diagonais, rainha para qualquer uma das direções), então a casa está atacada.
- Se encontrar qualquer peça que não seja do atacante, a direção está bloqueada e não há ataque nessa direção.
- Partir da casa alvo
- Observação: é comum começar do rei e olhar para fora, mas o mesmo raciocínio vale iniciando da casa do rei e caminhando.
Passo 6
Ataque de rei (caso de casas adjacentes) e resumo da rotina is_attacked.
- Rei adversário ataca as oito casas adjacentes. Embora posições legais não permitam reis adjacentes, é prudente checar: olhar as 8 vizinhanças imediatas por um rei do atacante (código
para rei preto, para rei branco). - Ordem prática de checagem dentro de is_attacked (por eficiência e simplicidade):
- Checar ataques de peão (já são verificados em poucas casas).
- Checar ataques de cavalo (8 testes).
- Checar ataques deslizantes: primeiro ortogonais para torre/rei/rainha; depois diagonais para bispo/rei/rainha.
- Checar vizinhança por rei (pode ser feito junto com cavalo ou depois).
- Se qualquer uma dessas checagens confirmar a presença de peça atacante que possa atingir
, retornar verdadeiro (a casa está atacada). Caso contrário, falso.
Passo 7
Complexidade, cuidados e exemplos simples para fixar.
- Complexidade: cada chamada a is_attacked faz um número limitado de verificações (constante) e varre no máximo 8 raios até bloqueio. Em um tabuleiro
isto é muito eficiente. - Cuidados:
- Sempre verificar limites das coordenadas antes de acessar a matriz.
- Identificar corretamente a cor da peça lida: valores
a são pretos; a são brancos.
- Exemplo pequeno (mental):
- Rei preto em
. Se houver um cavalo branco em (offset relativo ao rei), então is_attacked devolve verdadeiro para ataque de cavalo. - Rei branco em
. Se há uma torre preta em e nenhuma peça entre e , então o raio ortogonal detecta torre preta e conclui xeque.
- Rei preto em
Passo 8
Montagem final da função principal.
- Passos da função check_check(board):
- Procurar posições do rei preto (
) e do rei branco ( ). - Chamar is_attacked( pos_rei_preto, attacker_color = “white” ) para saber se o rei preto está em xeque.
- Chamar is_attacked( pos_rei_branco, attacker_color = “black” ) para saber se o rei branco está em xeque.
- Retornar as duas flags booleanas, por exemplo como tupla
.
- Procurar posições do rei preto (
- Observação sobre retorno: este formato é útil em provas/implementações porque descreve claramente o estado de xeque para ambos os dois lados.
Passo 9
Implementação pronta (pseudocódigo explicado linha a linha).
- Abaixo está uma implementação em Python, com as funções auxiliares dentro de check_check. Ela segue exatamente os passos ensinados: localiza reis, define checagens de peão, cavalo, deslizantes e rei, e retorna os dois booleanos.
Resposta
def check_check(board):
“”"
Recebe
0: casa vazia
1…6: peças pretas (1 peão, 2 cavalo, 3 torre, 4 bispo, 5 rei, 6 rainha)
7…12: peças brancas (7 peão, 8 cavalo, 9 torre, 10 bispo, 11 rei, 12 rainha)
Retorna uma tupla (preto_em_xeque, branco_em_xeque) com booleans indicando
se o rei preto (5) ou o rei branco (11) está sob ataque.
Convenção: linhas indexadas 0…7 de cima para baixo; colunas 0…7 da esquerda para a direita.
“”"
ROWS, COLS = 8, 8
“”"
Recebe
board, uma matriz 8x8 (lista de listas) com inteiros conforme a tabela:0: casa vazia
1…6: peças pretas (1 peão, 2 cavalo, 3 torre, 4 bispo, 5 rei, 6 rainha)
7…12: peças brancas (7 peão, 8 cavalo, 9 torre, 10 bispo, 11 rei, 12 rainha)
Retorna uma tupla (preto_em_xeque, branco_em_xeque) com booleans indicando
se o rei preto (5) ou o rei branco (11) está sob ataque.
Convenção: linhas indexadas 0…7 de cima para baixo; colunas 0…7 da esquerda para a direita.
“”"
ROWS, COLS = 8, 8
def in_bounds(r, c):
return 0 <= r < ROWS and 0 <= c < COLS
def piece_color(val):
if val == 0:
return None
if 1 <= val <= 6:
return 'black'
if 7 <= val <= 12:
return 'white'
return None
def find_kings():
pos_black = None
pos_white = None
for r in range(ROWS):
for c in range(COLS):
if board[r][c] == 5:
pos_black = (r, c)
elif board[r][c] == 11:
pos_white = (r, c)
if pos_black and pos_white:
return pos_black, pos_white
return pos_black, pos_white
# checa se a casa (r,c) é atacada por alguma peça de attacker_color ('black' or 'white')
def is_attacked(r, c, attacker_color):
# códigos de peças por cor
if attacker_color == 'black':
pawn_code = 1
knight_code = 2
rook_code = 3
bishop_code = 4
king_code = 5
queen_code = 6
else:
pawn_code = 7
knight_code = 8
rook_code = 9
bishop_code = 10
king_code = 11
queen_code = 12
# 1) ataques de peão
# lembrando convenção: peões pretos atacam para baixo (r+1), peões brancos atacam para cima (r-1)
if attacker_color == 'black':
# procurar peão em (r-1, c-1) ou (r-1, c+1)
for dc in (-1, 1):
rp, cp = r - 1, c + dc
if in_bounds(rp, cp) and board[rp][cp] == pawn_code:
return True
else:
# attacker white: peão branco estaria em (r+1, c-1) ou (r+1, c+1)
for dc in (-1, 1):
rp, cp = r + 1, c + dc
if in_bounds(rp, cp) and board[rp][cp] == pawn_code:
return True
# 2) ataques de cavalo
knight_offsets = [(-2, -1), (-2, 1), (-1, -2), (-1, 2), (1, -2), (1, 2), (2, -1), (2, 1)]
for dr, dc in knight_offsets:
rr, cc = r + dr, c + dc
if in_bounds(rr, cc) and board[rr][cc] == knight_code:
return True
# 3) ataques deslizantes - torres/rei/rainha em ortogonais
orth_dirs = [(-1, 0), (1, 0), (0, -1), (0, 1)]
for dr, dc in orth_dirs:
rr, cc = r + dr, c + dc
while in_bounds(rr, cc):
val = board[rr][cc]
if val != 0:
# encontrou a primeira peça nessa direção
if val == rook_code or val == queen_code:
return True
# rei adversário em casa adjacente também conta (checar apenas na primeira casa)
if (rr, cc) == (r + dr, c + dc) and val == king_code:
return True
break
rr += dr
cc += dc
# 4) ataques deslizantes - bispo/rei/rainha em diagonais
diag_dirs = [(-1, -1), (-1, 1), (1, -1), (1, 1)]
for dr, dc in diag_dirs:
rr, cc = r + dr, c + dc
while in_bounds(rr, cc):
val = board[rr][cc]
if val != 0:
if val == bishop_code or val == queen_code:
return True
if (rr, cc) == (r + dr, c + dc) and val == king_code:
return True
break
rr += dr
cc += dc
return False
pos_black, pos_white = find_kings()
if pos_black is None or pos_white is None:
raise ValueError("Posição inválida: algum dos reis não foi encontrado no tabuleiro.")
preto_em_xeque = is_attacked(pos_black[0], pos_black[1], 'white')
branco_em_xeque = is_attacked(pos_white[0], pos_white[1], 'black')
return preto_em_xeque, branco_em_xeque