#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
#include "jogadasvalidas.h"
#include "jogo.h"
#include "traducao.h"
/*Note: The source code is entirely written in Portuguese now.*/
/*At the Github repository, this file is equivalent to 'jogo.c'.*/
void limpezaBuffer(){
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
}
static const char TABULEIRO_INICIAL[8][8] = {
{'t', 'c', 'b', 'q', 'k', 'b', 'c', 't'},
{'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
{'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'},
{'T', 'C', 'B', 'Q', 'K', 'B', 'C', 'T'}
};
static char tabuleiro[8][8];
static int jogadorDaVez = 0; // 0 para o Jogador 1 (maiúsculas), 1 para o Jogador 2 (minúsculas)
static int movimentosSemCapturaouPiao = 0;
typedef struct {
char nome[20];
int pontos;
} Jogador;
static Jogador jogadores[2];
static int movimentosFeitos = 0;
static bool ganhou = false;
static bool SalvarJogo();
static bool CarregarJogo();
static const char* ObterSimboloPeca(char peca) {
static const char* simbolos[] = {
['P'] = "♙",
['T'] = "♖",
['C'] = "♘",
['B'] = "♗",
['Q'] = "♕",
['K'] = "♔",
['p'] = "♟",
['t'] = "♜",
['c'] = "♞",
['b'] = "♝",
['q'] = "♛",
['k'] = "♚",
[' '] = " "
};
int ConversorIndice = (int)peca;
if(ConversorIndice < sizeof(simbolos) / sizeof(simbolos[0]) && simbolos[ConversorIndice] != NULL){
return simbolos[ConversorIndice];
}
return " "; // Caso de segurança
}
static void ExibirTabuleiro() {
printf("\n a b c d e f g h\n");
for (int i = 8; i >= 1; i--) {
int conversaoLinha = 8 - i;
printf("%d ", i);
for (int j = 0; j < 8; j++) {
printf("%s ", ObterSimboloPeca(tabuleiro[conversaoLinha][j]));
}
printf("\n");
}
}
/**
* Solicita ao jogador que insira uma jogada no formato de notação algébrica.
* Parâmetros:
* linhaOrigem, colunaOrigem: ponteiros para armazenar a linha e coluna de origem.
* linhaDestino, colunaDestino: ponteiros para armazenar a linha e coluna de destino.
* O jogador pode digitar "salvar" para salvar o jogo atual.
* O jogador pode digitar "desistir" para dar a vitória ao oponente.
*/
static bool obterCoordenada(int *linhaOrigem, int *colunaOrigem, int *linhaDestino, int *colunaDestino){
char input[10];
while(1){
printf(Msg(MSG_JOGO_DIGITE_JOGADA), jogadores[jogadorDaVez].nome);
int retornoInput = scanf("%9s", input);
if (retornoInput == EOF){
printf(Msg(MSG_JOGO_ENCERRAMENTO_EOF));
return false; // Indica que o jogo deve ser encerrado
}
if(retornoInput != 1){
printf(Msg(MSG_JOGO_JOGADA_INVALIDA));
limpezaBuffer();
continue;
}
limpezaBuffer();
if(strcmp(input, "salvar") == 0 || strcmp(input, "SALVAR") == 0 ||
strcmp(input, "save") == 0 || strcmp(input, "SAVE") == 0){
if(SalvarJogo()){
printf(Msg(MSG_JOGO_SALVAR_SUCESSO));
} else {
printf(Msg(MSG_JOGO_SALVAR_ERRO));
}
continue;
}
if(strcmp(input, "desistir") == 0 || strcmp(input, "DESISTIR") == 0 || strcmp(input, "resign") == 0 || strcmp(input, "RESIGN") == 0){
printf(Msg(MSG_JOGO_DESISTENCIA), jogadores[jogadorDaVez].nome, jogadores[1 - jogadorDaVez].nome);
ganhou = true;
return false;
}
if (strcmp(input, "empatar") == 0 || strcmp(input, "EMPATAR") == 0 || strcmp(input, "draw") == 0 || strcmp(input, "DRAW") == 0){
printf(Msg(MSG_JOGO_EMPATE_SUGESTAO), jogadores[jogadorDaVez].nome, jogadores[1 - jogadorDaVez].nome);
char resposta[2];
scanf("%1s", resposta);
limpezaBuffer();
if((strcmp(resposta, "y") == 0 || strcmp(resposta, "Y") == 0) || (strcmp(resposta, "s") == 0 || strcmp(resposta, "S") == 0)){
printf(Msg(MSG_JOGO_EMPATE_ACEITO), jogadores[1 - jogadorDaVez].nome);
ganhou = true;
return false;
} else if(strcmp(resposta, "n") == 0 || strcmp(resposta, "N") == 0){
continue;
} else {
printf(Msg(MSG_JOGO_JOGADA_INVALIDA));
continue;
}
}
//Para notação sem separação (ex: e2e4)
if(strlen(input) == 4){
if(tolower(input[0]) < 'a' || tolower(input[0]) > 'h'){
printf(Msg(MSG_JOGO_COLUNA_ORIGEM_INVALIDA));
continue;
}
*colunaOrigem = tolower(input[0]) - 'a';
if(input[1] < '1' || input[1] > '8'){
printf(Msg(MSG_JOGO_LINHA_ORIGEM_INVALIDA));
continue;
}
int conversaoLinhaOrigem = input[1] - '0';
*linhaOrigem = 8 - conversaoLinhaOrigem;
if(tolower(input[2]) < 'a' || tolower(input[2]) > 'h'){
printf(Msg(MSG_JOGO_COLUNA_DESTINO_INVALIDA));
continue;
}
*colunaDestino = tolower(input[2]) - 'a';
if(input[3] < '1' || input[3] > '8'){
printf(Msg(MSG_JOGO_LINHA_DESTINO_INVALIDA));
continue;
}
int conversaoLinhaDestino = input[3] - '0';
*linhaDestino = 8 - conversaoLinhaDestino;
break;
}
//Notação com separador (ex: e2-e4)
else if (strlen(input) == 5){
if ((input[2] != ' ') && (input[2] != '-')){
printf(Msg(MSG_JOGO_SEPARADOR_COORDENADAS_INVALIDO));
continue;
}
if(tolower(input[0]) < 'a' || tolower(input[0]) > 'h'){
printf(Msg(MSG_JOGO_COLUNA_ORIGEM_INVALIDA));
continue;
}
*colunaOrigem = tolower(input[0]) - 'a';
if(input[1] < '1' || input[1] > '8'){
printf(Msg(MSG_JOGO_LINHA_ORIGEM_INVALIDA));
continue;
}
int conversaoLinhaOrigem = input[1] - '0';
*linhaOrigem = 8 - conversaoLinhaOrigem;
if(tolower(input[3]) < 'a' || tolower(input[3]) > 'h'){
printf(Msg(MSG_JOGO_COLUNA_DESTINO_INVALIDA));
continue;
}
*colunaDestino = tolower(input[3]) - 'a';
if(input[4] < '1' || input[4] > '8'){
printf(Msg(MSG_JOGO_LINHA_DESTINO_INVALIDA));
continue;
}
int conversaoLinhaDestino = input[4] - '0';
*linhaDestino = 8 - conversaoLinhaDestino;
break;
} else{
printf(Msg(MSG_JOGO_FORMATO_COORDENADAS_INVALIDO));
continue;
}
}
return true;
}
/*Função para a promoção de peão.
Ela solicita a peça para a qual o usuário vai querer promover.*/
static char PromocaoPeao(int linhaDestino, int colunaDestino, int jogadorDaVez) {
char escolha;
printf(Msg(MSG_JOGO_PROMOCAO_PEAO_ESCOLHA_PECA));
while (1) {
scanf(" %c", &escolha);
limpezaBuffer();
if(jogadorDaVez == 0) {
escolha = toupper(escolha);
} else {
escolha = tolower(escolha);
}
if (((escolha == 'Q' || escolha == 'C' || escolha == 'B' || escolha == 'T') && jogadorDaVez == 0) ||
((escolha == 'q' || escolha == 'c' || escolha == 'b' || escolha == 't') && jogadorDaVez == 1)) {
return escolha;
} else {
printf(Msg(MSG_JOGO_PROMOCAO_PEAO_PECA_INVALIDA));
}
}
}
struct Salvamento
{
char tabuleiro[8][8];
int jogadorDaVez;
int movimentosFeitos;
int movimentosSemCapturaouPiao;
Jogador jogadores[2];
};
static bool SalvarJogo() {
FILE *arquivo = fopen("salvamento.dat", "wb");
if (arquivo == NULL) {
printf(Msg(MSG_JOGO_SALVAR_ERRO_ABERTURA_ARQUIVO));
return false;
}
struct Salvamento salvamento;
memcpy(salvamento.tabuleiro, tabuleiro, sizeof(tabuleiro));
salvamento.jogadorDaVez = jogadorDaVez;
salvamento.movimentosFeitos = movimentosFeitos;
salvamento.movimentosSemCapturaouPiao = movimentosSemCapturaouPiao;
memcpy(salvamento.jogadores, jogadores, sizeof(jogadores));
fwrite(&salvamento, sizeof(salvamento), 1, arquivo);
fclose(arquivo);
return true;
}
static bool CarregarJogo() {
FILE *arquivo = fopen("salvamento.dat", "rb");
if (arquivo == NULL) {
printf(Msg(MSG_JOGO_CARREGAR_ERRO));
return false;
}
struct Salvamento salvamento;
fread(&salvamento, sizeof(salvamento), 1, arquivo);
fclose(arquivo);
memcpy(tabuleiro, salvamento.tabuleiro, sizeof(tabuleiro));
jogadorDaVez = salvamento.jogadorDaVez;
movimentosFeitos = salvamento.movimentosFeitos;
movimentosSemCapturaouPiao = salvamento.movimentosSemCapturaouPiao;
memcpy(jogadores, salvamento.jogadores, sizeof(jogadores));
return true;
}
static bool capturaOuPiao = false;
static void atualizarPontuacao(int *pontos, char pecaCapturada){
switch(toupper(pecaCapturada)){
case 'P':
*pontos += 1; // Incrementa o ponto do jogador que capturou
capturaOuPiao = true;
break;
case 'C':
case 'B':
*pontos += 3; // Incrementa 3 pontos para cavalo ou bispo
capturaOuPiao = true;
break;
case 'T':
*pontos += 5; // Incrementa 5 pontos para torre
capturaOuPiao = true;
break;
case 'Q':
*pontos += 9; // Incrementa 9 pontos para rainha
capturaOuPiao = true;
break;
default:
break; // Nenhuma peça capturada
}
}
static void reiniciarJogo(){
memcpy(tabuleiro, TABULEIRO_INICIAL, sizeof(TABULEIRO_INICIAL));
jogadorDaVez = 0;
movimentosSemCapturaouPiao = 0;
movimentosFeitos = 0;
capturaOuPiao = false;
ganhou = false;
}
int iniciarJogo(int opcao) {
limpezaBuffer();
reiniciarJogo();
printf("--------------------------------------------\n\n");
if (opcao == 1){
for(int i = 0; i < 2; i++){
printf(Msg(MSG_JOGO_DIGITE_JOGADOR), i + 1);
scanf("%19s", jogadores[i].nome);
jogadores[i].pontos = 0;
}
movimentosSemCapturaouPiao = 0;
movimentosFeitos = 0;
} else {
if(!CarregarJogo()){
for(int i = 0; i < 2; i++){
printf(Msg(MSG_JOGO_DIGITE_JOGADOR), i + 1);
scanf("%19s", jogadores[i].nome);
jogadores[i].pontos = 0;
}
movimentosSemCapturaouPiao = 0;
movimentosFeitos = 0;
}
}
while(!ganhou){
capturaOuPiao = false;
printf("\n");
ExibirTabuleiro();
printf(Msg(MSG_JOGO_VEZ_JOGADOR), jogadores[jogadorDaVez].nome, (jogadorDaVez == 0)
? Msg(MSG_JOGO_MAIUSCULAS) : Msg(MSG_JOGO_MINUSCULAS));
int linhaOrigem, colunaOrigem, linhaDestino, colunaDestino;
if(!obterCoordenada(&linhaOrigem, &colunaOrigem, &linhaDestino, &colunaDestino)){
break; // Sai do loop principal do jogo se o jogador desistir
}
if(tabuleiro[linhaOrigem][colunaOrigem] == ' '){
printf(Msg(MSG_JOGO_POSICAO_ORIGEM_VAZIA));
continue;
}
const char* resultadoJogadaValida = JogadaValida(tabuleiro, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino, jogadorDaVez);
if(strcmp(resultadoJogadaValida, "OK") == 0){
movimentosFeitos++;
if(toupper(tabuleiro[linhaOrigem][colunaOrigem]) == 'P'){
capturaOuPiao = true;
}
//Verifica a captura de peças e atualiza a pontuação
atualizarPontuacao(&jogadores[jogadorDaVez].pontos, tabuleiro[linhaDestino][colunaDestino]);
if(toupper(tabuleiro[linhaDestino][colunaDestino]) == 'K'){
ganhou = true;
printf(Msg(MSG_JOGO_XEQUEMATE_REI_CAPTURADO_TITULO));
printf(Msg(MSG_JOGO_XEQUEMATE_VENCEDOR), jogadores[jogadorDaVez].nome);
printf(Msg(MSG_JOGO_XEQUEMATE_PLACAR), jogadores[0].nome, jogadores[0].pontos, jogadores[1].nome, jogadores[1].pontos);
printf(Msg(MSG_JOGO_XEQUEMATE_TOTAL_MOVIMENTOS), movimentosFeitos);
break; // Sai do loop principal do jogo
}
if(capturaOuPiao){
movimentosSemCapturaouPiao = 0;
} else {
movimentosSemCapturaouPiao++;
}
if(movimentosSemCapturaouPiao >= 100){
printf(Msg(MSG_JOGO_EMPATE_50MOVIMENTOS_TITULO));
printf(Msg(MSG_JOGO_XEQUEMATE_PLACAR), jogadores[0].nome, jogadores[0].pontos, jogadores[1].nome, jogadores[1].pontos);
printf(Msg(MSG_JOGO_XEQUEMATE_TOTAL_MOVIMENTOS), movimentosFeitos);
ganhou = true;
break; // Sai do loop principal do jogo
}
if(ganhou){
break; // Sai do loop principal do jogo se alguém ganhou
}
tabuleiro[linhaDestino][colunaDestino] = tabuleiro[linhaOrigem][colunaOrigem];
tabuleiro[linhaOrigem][colunaOrigem] = ' ';
if((tabuleiro[linhaDestino][colunaDestino] == 'p' && linhaDestino == 7) || (tabuleiro[linhaDestino][colunaDestino] == 'P' && linhaDestino == 0)){
tabuleiro[linhaDestino][colunaDestino] = PromocaoPeao(linhaDestino, colunaDestino, jogadorDaVez);
}
jogadorDaVez = 1 - jogadorDaVez; // Alterna entre 0 e 1, trocando o jogador da vez
if(XequeMate(tabuleiro, jogadorDaVez)){
ganhou = true;
printf(Msg(MSG_JOGO_XEQUEMATE_TITULO));
printf(Msg(MSG_JOGO_XEQUEMATE_VENCEDOR), jogadores[1 - jogadorDaVez].nome);
printf(Msg(MSG_JOGO_XEQUEMATE_PLACAR), jogadores[0].nome, jogadores[0].pontos, jogadores[1].nome, jogadores[1].pontos);
printf(Msg(MSG_JOGO_XEQUEMATE_TOTAL_MOVIMENTOS), movimentosFeitos);
break; // Sai do loop principal do jogo
}
if(Afogamento(tabuleiro, jogadorDaVez)){
ganhou = true;
printf(Msg(MSG_JOGO_AFOGAMENTO_TITULO));
printf(Msg(MSG_JOGO_EMPATE_TEXTO));
printf(Msg(MSG_JOGO_XEQUEMATE_PLACAR), jogadores[0].nome, jogadores[0].pontos, jogadores[1].nome, jogadores[1].pontos);
printf(Msg(MSG_JOGO_XEQUEMATE_TOTAL_MOVIMENTOS), movimentosFeitos);
break; // Sai do loop principal do jogo
}
} else {
printf(Msg(MSG_JOGO_JOGADA_INVALIDA), resultadoJogadaValida);
}
}
printf("-----------------------------------------------\n\n");
return 0;
}
#ifndef JOGO_H
#define JOGO_H
int iniciarJogo(int opcao);
#endif // JOGO_H
#include <stdio.h>
#include "traducao.h"
static Lingua linguaAtual = PORTUGUES;
static const char* tabela_traducoes [TOTAL_STRINGS][TOTAL_LINGUAS] = {
//menu.c
{
"==============================================\n XADREZ EM C\n==============================================",
"==============================================\n CHESS IN C\n=============================================="
},
{
"\n1. Nova Partida\n",
"\n1. New Game\n"
},
{
"2. Carregar Partida Salva\n",
"2. Load Saved Game\n"
},
{
"3. Ajuda\n",
"3. Help\n"
},
{
"4. Sair\n\n",
"4. Exit\n\n"
},
{
"Escolha uma opção: ",
"Choose an option: "
},
{
"Opção inválida! Por favor, insira um número entre 1 e 4: ",
"Invalid option! Please enter a number between 1 and 4: "
},
{
"Fechando o programa...\n",
"Closing the program...\n"
},
//menu.c - Ajuda
{
"\nAJUDA:\n",
"\nHELP:\n"
},
{
"Este é um jogo de xadrez para dois jogadores. Cada jogador controla um conjunto de pecas, uma em MAIÚSCULAS e a outra em minúsculas.\n",
"This is a chess game for two players. Each player controls a set of pieces, one in UPPERCASE and the other in lowercase.\n"
},
{
"O objetivo do jogo é capturar o rei do oponente. As peças se movem de acordo com as regras tradicionais do xadrez.\n",
"The objective of the game is to capture the opponent's king. The pieces move according to traditional chess rules.\n"
},
{
"Para fazer uma jogada, você precisará inserir as coordenadas de origem e destino no formato de notação algébrica (ex: e2e4, e2-e4).\n",
"To make a move, you will need to enter the source and destination coordinates in algebraic notation (e.g., e2e4, e2-e4).\n"
},
{
"Você também pode salvar o jogo a qualquer momento digitando 'salvar' quando solicitado a inserir uma jogada.\n",
"You can also save the game at any time by typing 'save' when prompted to enter a move.\n"
},
{
"Digite 'desistir' para abandonar o jogo atual e conceder a vitória ao oponente.\n",
"Type 'resign' to abandon the current game and concede victory to the opponent.\n"
},
{
"Boa sorte e divirta-se!\n\n",
"Good luck and have fun!\n\n"
},
//jogo.c
{
"\n%s, digite a jogada em notação algébrica (ex: e2e4): ",
"\n%s, enter your move in algebraic notation (e.g., e2e4): "
},
{
"Fim do arquivo (EOF) detectado. Encerrando a partida...\n",
"End of file (EOF) detected. Ending the game...\n"
},
{
"Jogo salvo com sucesso!\n",
"Game saved successfully!\n"
},
{
"Erro ao salvar o jogo.\n",
"Error saving the game.\n"
},
{
"%s desistiu do jogo. %s é o vencedor!\n",
"%s resigned from the game. %s is the winner!\n"
},
{
"%s deseja um empate. %s aceita? (s/n): ",
"%s offers a draw. Does %s accept? (y/n): "
},
{
"%s aceitou o empate. O jogo termina empatado!\n",
"%s accepted the draw. The game ends in a draw!\n"
},
{
"ERRO: Coluna origem inválida. Use letras de a-h.\n",
"ERROR: Invalid source column. Use letters a-h.\n"
},
{
"ERRO: Linha origem inválida. Use números de 1-8.\n",
"ERROR: Invalid source row. Use numbers 1-8.\n"
},
{
"ERRO: Coluna destino inválida. Use letras de a-h.\n",
"ERROR: Invalid destination column. Use letters a-h.\n"
},
{
"ERRO: Linha destino inválida. Use números de 1-8.\n",
"ERROR: Invalid destination row. Use numbers 1-8.\n"
},
{
"ERRO: Dígito inválido. Para separar, use espaço ou hífen.\n",
"ERROR: Invalid character. To separate, use space or hyphen.\n"
},
{
"ERRO: Formato inválido. Use 4 caracteres (ex: e2e4) ou use 5 caracteres (ex: e2-e4)\n",
"ERROR: Invalid format. Use 4 characters (e.g., e2e4) or use 5 characters (e.g., e2-e4)\n"
},
{
"Seu peão chegou na última linha! Escolha a peça para promover (Q, C, B, T): ",
"Your pawn has reached the last row! Choose the piece to promote to (Q, C, B, T): "
},
{
"Escolha inválida. Por favor, escolha entre Q, C, B, T: ",
"Invalid choice. Please choose between Q, C, B, T: "
},
{
"Erro ao abrir o arquivo para salvar o jogo.\n",
"Error opening file to save the game.\n"
},
{
"Nenhum jogo salvo encontrado.\n",
"No saved game found.\n"
},
{
"Digite o nome do %d jogador: ",
"Enter the name of player %d: "
},
{
"E a vez de %s!\n (%s)",
"It's %s's turn!\n (%s)"
},
{
"MAIÚSCULAS",
"UPPERCASE"
},
{
"minúsculas",
"lowercase"
},
{
"Jogada inválida! Não há peça na posição de origem.\n",
"Invalid move! There is no piece at the source position.\n"
},
{
"\n=== XEQUE-MATE (REI CAPTURADO) ===\n",
"\n=== CHECKMATE (KING CAPTURED) ===\n"
},
{
"O jogador %s ganhou o jogo!\n",
"Player %s wins the game!\n"
},
{
"Placar: %s: %d pontos, %s: %d pontos\n",
"Score: %s: %d points, %s: %d points\n"
},
{
"Total de movimentos feitos: %d\n",
"Total moves made: %d\n"
},
{
"\n=== EMPATE (REGRA DOS 50 MOVIMENTOS SEM CAPTURA OU PEÃO) ===\n",
"\n=== DRAW (50-MOVE RULE WITHOUT CAPTURE OR PAWN MOVE) ===\n"
},
{
"\n=== XEQUE-MATE ===\n",
"\n=== CHECKMATE ===\n"
},
{
"=== AFOGAMENTO ===\n",
"=== STALEMATE ===\n"
},
{
"Houve um empate! Nenhum jogador tem movimentos válidos, mas o rei não está em xeque.\n",
"It's a draw! Neither player has valid moves, but the king is not in check.\n"
},
{
"Jogada inválida! %s.\n",
"Invalid move! %s.\n"
},
//jogadasvalidas.c
{
"Movimento para a mesma posição",
"Move to the same position"
},
{
"Tentativa de capturar própria peça",
"Attempt to capture own piece"
},
{
"Tentativa de mover peça do oponente",
"Attempt to move opponent's piece"
},
{
"Movimento deixaria rei em xeque",
"Move would leave king in check"
},
{
"Movimento inválido para o peão",
"Invalid move for the pawn"
},
{
"Movimento inválido para a torre",
"Invalid move for the rook"
},
{
"Movimento inválido para o cavalo",
"Invalid move for the knight"
},
{
"Movimento inválido para o bispo",
"Invalid move for the bishop"
},
{
"Movimento inválido para a rainha",
"Invalid move for the queen"
},
{
"Casa de destino em xeque",
"Destination square is in check"
},
{
"Movimento inválido para o rei",
"Invalid move for the king"
},
{
"Peça inválida",
"Invalid piece"
}
};
void definirIdioma(Lingua novoIdioma){
linguaAtual = novoIdioma;
}
const char* Msg(Texto ID_Texto){
return tabela_traducoes[ID_Texto][linguaAtual];
}
#ifndef TRADUCAO_H
#define TRADUCAO_H
typedef enum {
//menu.c
MSG_MENU_TITULO,
MSG_MENU_OPCAO_NOVA_PARTIDA,
MSG_MENU_OPCAO_CARREGAR_PARTIDA,
MSG_MENU_OPCAO_AJUDA,
MSG_MENU_OPCAO_SAIR,
MSG_MENU_OPCAO_ESCOLHA_OPCAO,
MSG_MENU_OPCAO_INVALIDA,
MSG_MENU_FECHANDO_PROGRAMA,
MSG_MENU_AJUDA_TITULO,
MSG_MENU_AJUDA_LINHA1,
MSG_MENU_AJUDA_LINHA2,
MSG_MENU_AJUDA_LINHA3,
MSG_MENU_AJUDA_LINHA4,
MSG_MENU_AJUDA_LINHA5,
MSG_MENU_AJUDA_LINHA6,
//jogo.c
MSG_JOGO_DIGITE_JOGADA,
MSG_JOGO_ENCERRAMENTO_EOF,
MSG_JOGO_SALVAR_SUCESSO,
MSG_JOGO_SALVAR_ERRO,
MSG_JOGO_DESISTENCIA,
MSG_JOGO_EMPATE_SUGESTAO,
MSG_JOGO_EMPATE_ACEITO,
MSG_JOGO_COLUNA_ORIGEM_INVALIDA,
MSG_JOGO_LINHA_ORIGEM_INVALIDA,
MSG_JOGO_COLUNA_DESTINO_INVALIDA,
MSG_JOGO_LINHA_DESTINO_INVALIDA,
MSG_JOGO_SEPARADOR_COORDENADAS_INVALIDO,
MSG_JOGO_FORMATO_COORDENADAS_INVALIDO,
MSG_JOGO_PROMOCAO_PEAO_ESCOLHA_PECA,
MSG_JOGO_PROMOCAO_PEAO_PECA_INVALIDA,
MSG_JOGO_SALVAR_ERRO_ABERTURA_ARQUIVO,
MSG_JOGO_CARREGAR_ERRO,
MSG_JOGO_DIGITE_JOGADOR,
MSG_JOGO_VEZ_JOGADOR,
MSG_JOGO_MAIUSCULAS,
MSG_JOGO_MINUSCULAS,
MSG_JOGO_POSICAO_ORIGEM_VAZIA,
MSG_JOGO_XEQUEMATE_REI_CAPTURADO_TITULO,
MSG_JOGO_XEQUEMATE_VENCEDOR,
MSG_JOGO_XEQUEMATE_PLACAR,
MSG_JOGO_XEQUEMATE_TOTAL_MOVIMENTOS,
MSG_JOGO_EMPATE_50MOVIMENTOS_TITULO,
MSG_JOGO_XEQUEMATE_TITULO,
MSG_JOGO_AFOGAMENTO_TITULO,
MSG_JOGO_EMPATE_TEXTO,
MSG_JOGO_JOGADA_INVALIDA,
//jogadasvalidas.c
MSG_JOGADAS_MOVIMENTO_MESMA_POSICAO,
MSG_JOGADAS_PECA_MESMO_JOGADOR,
MSG_JOGADAS_MOVER_PECA_OPONENTE,
MSG_JOGADAS_DEIXA_REI_XEQUE,
MSG_JOGADAS_MOVIMENTO_INVALIDO_PEAO,
MSG_JOGADAS_MOVIMENTO_INVALIDO_TORRE,
MSG_JOGADAS_MOVIMENTO_INVALIDO_CAVALO,
MSG_JOGADAS_MOVIMENTO_INVALIDO_BISPO,
MSG_JOGADAS_MOVIMENTO_INVALIDO_RAINHA,
MSG_JOGADAS_MOVIMENTO_REI_XEQUE,
MSG_JOGADAS_CASA_DESTINO_XEQUE,
MSG_JOGADAS_MOVIMENTO_INVALIDO_REI,
MSG_JOGADAS_PECA_INVALIDA,
TOTAL_STRINGS //Apenas um indicador da quantidade.
} Texto;
typedef enum {
PORTUGUES = 0,
INGLES = 1,
TOTAL_LINGUAS //Apenas um indicador da quantidade.
} Lingua;
void definirIdioma(Lingua novoIdioma);
const char* Msg(Texto ID_Texto);
#endif
#include <stdio.h>
#include "jogo.h"
#include "traducao.h"
/*Note: The source code is entirely written in Portuguese now.*/
// ✅ Ativa UTF-8 automaticamente no Windows
#ifdef _WIN32
#include <windows.h>
#endif
int main(){
#ifdef _WIN32
SetConsoleCP(65001);
SetConsoleOutputCP(65001);
#endif
int opcao;
Lingua opcao_lingua;
while(1){
printf("Escolha a língua/Choose the language (0 = Português, 1 = English): ");
if(scanf("%d", &opcao_lingua) != 1 || opcao_lingua >= TOTAL_LINGUAS || opcao_lingua < 0){
printf("Opcao inválida!/Invalid option!\n");
int c;
while((c = getchar()) != '\n' && c != EOF); // Limpa o buffer de entrada
continue;
}
definirIdioma(opcao_lingua);
break;
}
printf(Msg(MSG_MENU_TITULO));
printf("\nVersion/Versão: 1.4\n");
while (1){
printf(Msg(MSG_MENU_OPCAO_NOVA_PARTIDA));
printf(Msg(MSG_MENU_OPCAO_CARREGAR_PARTIDA));
printf(Msg(MSG_MENU_OPCAO_AJUDA));
printf(Msg(MSG_MENU_OPCAO_SAIR));
printf(Msg(MSG_MENU_OPCAO_ESCOLHA_OPCAO));
if(scanf("%d", &opcao) != 1){
printf(Msg(MSG_MENU_OPCAO_INVALIDA));
int c;
while((c = getchar()) != '\n' && c != EOF); // Limpa o buffer de entrada
continue;
}
if(opcao < 1 || opcao > 4){
printf(Msg(MSG_MENU_OPCAO_INVALIDA));
} else if(opcao == 4){
printf(Msg(MSG_MENU_FECHANDO_PROGRAMA));
return 0;
} else if (opcao == 3)
{
printf(Msg(MSG_MENU_AJUDA_TITULO));
printf(Msg(MSG_MENU_AJUDA_LINHA1));
printf(Msg(MSG_MENU_AJUDA_LINHA2));
printf(Msg(MSG_MENU_AJUDA_LINHA3));
printf(Msg(MSG_MENU_AJUDA_LINHA4));
printf(Msg(MSG_MENU_AJUDA_LINHA5));
printf(Msg(MSG_MENU_AJUDA_LINHA6));
} else{
iniciarJogo(opcao);
}
}
return 0;
}
#include "jogadasvalidas.h"
#include "traducao.h"
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
/*Note: The source code is entirely written in Portuguese now.*/
bool CasaAtacada(char tabuleiro[8][8], int linha, int coluna, int oponente){
//Verificação de ataque de peões
if(oponente == 0){
if(linha + 1 < 8 && coluna - 1 >= 0 && tabuleiro[linha + 1][coluna - 1] == 'P') return true;
if(linha + 1 < 8 && coluna + 1 < 8 && tabuleiro[linha + 1][coluna + 1] == 'P') return true;
} else{
if(linha - 1 >= 0 && coluna - 1 >= 0 && tabuleiro[linha - 1][coluna - 1] == 'p') return true;
if(linha - 1 >= 0 && coluna + 1 < 8 && tabuleiro[linha - 1][coluna + 1] == 'p') return true;
}
char torre = (oponente == 0) ? 'T': 't';
char rainha = (oponente == 0) ? 'Q' : 'q';
//Verificação de ataques verticais (Torre ou rainha)
for(int i = linha + 1; i < 8; i++){// Ataque de cima
char peca = tabuleiro[i][coluna];
if(peca != ' '){
if (peca == torre || peca == rainha) return true;
break;
}
}
for(int i = linha - 1; i >= 0; i--){// Ataque de baixo
char peca = tabuleiro[i][coluna];
if(peca != ' '){
if (peca == torre || peca == rainha) return true;
break;
}
}
//Verificação de ataques horizontais (Torre ou rainha)
for(int i = coluna + 1; i < 8; i++){// Ataque da direita
char peca = tabuleiro[linha][i];
if(peca != ' '){
if (peca == torre || peca == rainha) return true;
break;
}
}
for(int i = coluna - 1; i >= 0; i--){// Ataque da esquerda
char peca = tabuleiro[linha][i];
if(peca != ' '){
if (peca == torre || peca == rainha) return true;
break;
}
}
//Verifica se há ataque de cavalo
int movimentosCavalo[8][2] = {
{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2},
{1, -2}, {1, 2}, {2, -1}, {2, 1}
};
char cavalo = (oponente == 0) ? 'C' : 'c';
/*Verifica as 8 possíveis posições de um cavalo,
com base em movimentosCavalo[8][2]*/
for(int i = 0; i < 8; i++){
int linhaNova = linha + movimentosCavalo[i][0];
int colunaNova = coluna + movimentosCavalo[i][1];
if(linhaNova >= 0 && linhaNova < 8 && colunaNova >= 0 && colunaNova < 8){
if (tabuleiro[linhaNova][colunaNova] == cavalo){
return true;
}
}
}
//Verificação de ataques na diagonal (Bispo ou rainha)
char bispo = (oponente == 0) ? 'B' : 'b';
for(int i = 1; linha + i < 8 && coluna + i < 8; i++){//Para ver ataque a sudeste
char peca = tabuleiro[linha + i][coluna + i];
if(peca != ' '){
if(peca == bispo || peca == rainha) return true;
break;
}
}
for(int i = 1; linha - i >= 0 && coluna + i < 8; i++){//Para ver ataque a nordeste
char peca = tabuleiro[linha - i][coluna + i];
if(peca != ' '){
if(peca == bispo || peca == rainha) return true;
break;
}
}
for(int i = 1; linha + i < 8 && coluna - i >= 0; i++){//Para ver movimento para sudoeste
char peca = tabuleiro[linha + i][coluna - i];
if(peca != ' '){
if(peca == bispo || peca == rainha) return true;
break;
}
}
for(int i = 1; linha - i >= 0 && coluna - i >= 0; i++){//Para ver movimento para noroeste
char peca = tabuleiro[linha - i][coluna - i];
if(peca != ' '){
if(peca == bispo || peca == rainha) return true;
break;
}
}
//Verifica ataques do rei inimigo
char reiInimigo = (oponente == 0) ? 'K' : 'k';
int movimentosRei[8][2] = {
{-1, -1}, {-1, 0}, {-1, 1}, // Noroeste, Norte, Nordeste
{0, -1}, {0, 1}, // Oeste, Leste
{1, -1}, {1, 0}, {1, 1} // Sudoeste, Sul, Sudeste
};
/*Verifica as 8 possíveis posições de um rei,
com base em movimentosRei[8][2]*/
for(int i = 0; i < 8; i++){
int linhaNova = linha + movimentosRei[i][0];
int colunaNova = coluna + movimentosRei[i][1];
if(linhaNova >= 0 && linhaNova < 8 && colunaNova >= 0 && colunaNova < 8){
if (tabuleiro[linhaNova][colunaNova] == reiInimigo){
return true;
}
}
}
//Caso nenhuma das condições acima se aplicarem...
return false;
}
bool movimentoDeixaReiemXeque(char tabuleiro[8][8], int jogadorDaVez, int linhaOrigem, int colunaOrigem, int linhaDestino, int colunaDestino){
char tabuleiroTemp[8][8];
memcpy(tabuleiroTemp, tabuleiro, sizeof(char) * 8 * 8);
tabuleiroTemp[linhaDestino][colunaDestino] = tabuleiroTemp[linhaOrigem][colunaOrigem];
tabuleiroTemp[linhaOrigem][colunaOrigem] = ' ';
char ReiDoJogador = (jogadorDaVez == 0) ? 'K' : 'k';
int CoordenadaLinhaRei = -1;
int CoordenadaColunaRei = -1;
for(int i = 0; i < 8; i++){
for(int j = 0; j < 8; j++){
if (tabuleiroTemp[i][j] == ReiDoJogador){
CoordenadaLinhaRei = i;
CoordenadaColunaRei = j;
}
}
}
return CasaAtacada(tabuleiroTemp, CoordenadaLinhaRei, CoordenadaColunaRei, (jogadorDaVez + 1) % 2);
}
bool ReiEmXeque(char tabuleiro[8][8], int jogadorDaVez){
char ReiDoJogador = (jogadorDaVez == 0) ? 'K' : 'k';
int CoordenadaLinhaRei = -1;
int CoordenadaColunaRei = -1;
for(int i = 0; i < 8; i++){
for(int j = 0; j < 8; j++){
if (tabuleiro[i][j] == ReiDoJogador){
CoordenadaLinhaRei = i;
CoordenadaColunaRei = j;
}
}
}
return CasaAtacada(tabuleiro, CoordenadaLinhaRei, CoordenadaColunaRei, (jogadorDaVez + 1) % 2);
}
/*A função verifica se há algum movimento em que o jogador possa impedir o xeque-mate.*/
bool XequeMate(char tabuleiro[8][8], int JogadorDaVez){
// 1️⃣ Primeiro verifica se está em xeque
if(!ReiEmXeque(tabuleiro, JogadorDaVez)){
return false; //O rei pode ficar na posição, se protegendo de um xeque-mate.
}
//Verifica todas as peças e possíveis movimentos.
for(int linha = 0; linha < 8; linha++){
for(int coluna = 0; coluna < 8; coluna++){
char peca = tabuleiro[linha][coluna];
if(peca == ' ') continue;
if((JogadorDaVez == 0 && !isupper(peca)) || (JogadorDaVez == 1 && isupper(peca)))
continue;
for (int linhaDestino = 0; linhaDestino < 8; linhaDestino++)
{
for (int colunaDestino = 0; colunaDestino < 8; colunaDestino++)
{
const char* resultado = JogadaValida(tabuleiro, linha, coluna, linhaDestino, colunaDestino, JogadorDaVez);
//Verifica se é um movimento válido.
if(strcmp(resultado, "OK") == 0){
//Verifica se esse movimento ESCAPA do xeque
if(!movimentoDeixaReiemXeque(tabuleiro, JogadorDaVez, linha, coluna, linhaDestino, colunaDestino)){
return false; //Tal movimento não deixa o rei em xeque-mate
}
}
}
}
}
}
return true; //É xeque-mate.
}
bool Afogamento(char tabuleiro[8][8], int JogadorDaVez){
// 1️⃣ Primeiro verifica se está em xeque
if(ReiEmXeque(tabuleiro, JogadorDaVez)){
return false; //O rei deveria poder ficar na mesma posição para ser um afogamento.
}
//Verifica todas as peças e possíveis movimentos.
for(int linha = 0; linha < 8; linha++){
for(int coluna = 0; coluna < 8; coluna++){
char peca = tabuleiro[linha][coluna];
if(peca == ' ') continue;
if((JogadorDaVez == 0 && !isupper(peca)) || (JogadorDaVez == 1 && isupper(peca)))
continue;
for (int linhaDestino = 0; linhaDestino < 8; linhaDestino++)
{
for (int colunaDestino = 0; colunaDestino < 8; colunaDestino++)
{
const char* resultado = JogadaValida(tabuleiro, linha, coluna, linhaDestino, colunaDestino, JogadorDaVez);
//Verifica se é um movimento válido.
if(strcmp(resultado, "OK") == 0){
//Verifica se esse movimento ESCAPA do xeque
if(!movimentoDeixaReiemXeque(tabuleiro, JogadorDaVez, linha, coluna, linhaDestino, colunaDestino)){
return false; //Tal movimento não deixa o rei em xeque-mate
}
}
}
}
}
}
return true; //É afogamento.
}
/*A função retorna alguns valores de acordo com o seu resultado:
- "OK" para jogadas válidas;
- Outros textos para jogadas inválidas, para mostrar ao usuário o erro dele
(Por exemplo, "Peça do mesmo jogador" quando ocorre tentativa de capturar uma peça do mesmo jogador)
*/
const char* JogadaValida(char tabuleiro[8][8], int linhaOrigem, int colunaOrigem, int linhaDestino, int colunaDestino, int jogadorDaVez) {
char peca = tabuleiro[linhaOrigem][colunaOrigem];
if(linhaOrigem == linhaDestino && colunaOrigem == colunaDestino) {
return Msg(MSG_JOGADAS_MOVIMENTO_MESMA_POSICAO); // Movimento para a mesma posição
} else if((jogadorDaVez == 0 && isupper(tabuleiro[linhaDestino][colunaDestino])) || ((jogadorDaVez == 1 && islower(tabuleiro[linhaDestino][colunaDestino])))) {
return Msg(MSG_JOGADAS_PECA_MESMO_JOGADOR); // Tentativa de capturar uma peça do mesmo jogador
} else if ((jogadorDaVez == 0 && islower(tabuleiro[linhaOrigem][colunaOrigem])) || (jogadorDaVez == 1 && isupper(tabuleiro[linhaOrigem][colunaOrigem]))) {
return Msg(MSG_JOGADAS_MOVER_PECA_OPONENTE); // Tentativa de mover a peça do oponente
} else {
switch (toupper(peca))
{
case 'P':
/* Código para movimento do peão */
if(jogadorDaVez == 0) {
if ((linhaDestino == linhaOrigem - 1 && colunaDestino == colunaOrigem - 1 && tabuleiro[linhaDestino][colunaDestino] != ' ')) {
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento diagonal para capturar
} else if ((linhaDestino == linhaOrigem - 1 && colunaDestino == colunaOrigem + 1 && tabuleiro[linhaDestino][colunaDestino] != ' ')) {
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento diagonal para capturar
} else if (linhaDestino == linhaOrigem - 1 && colunaDestino == colunaOrigem && tabuleiro[linhaDestino][colunaDestino] == ' '){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento para frente
} else if (linhaOrigem == 6 && linhaDestino == linhaOrigem - 2 && colunaDestino == colunaOrigem && tabuleiro[linhaDestino + 1][colunaDestino] == ' ' && tabuleiro[linhaDestino][colunaDestino] == ' ') {
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento de início para frente (duas casas)
} else {
return Msg(MSG_JOGADAS_MOVIMENTO_INVALIDO_PEAO); // Movimento inválido para o peão
}
} else {
if ((linhaDestino == linhaOrigem + 1 && colunaDestino == colunaOrigem - 1 && tabuleiro[linhaDestino][colunaDestino] != ' ')) {
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento diagonal para capturar
} else if ((linhaDestino == linhaOrigem + 1 && colunaDestino == colunaOrigem + 1 && tabuleiro[linhaDestino][colunaDestino] != ' ')) {
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento diagonal para capturar
} else if (linhaDestino == linhaOrigem + 1 && colunaDestino == colunaOrigem && tabuleiro[linhaDestino][colunaDestino] == ' '){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento para frente
} else if (linhaOrigem == 1 && linhaDestino == linhaOrigem + 2 && colunaDestino == colunaOrigem && tabuleiro[linhaDestino - 1][colunaDestino] == ' ' && tabuleiro[linhaDestino][colunaDestino] == ' ') {
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento de início para frente (duas casas)
} else {
return Msg(MSG_JOGADAS_MOVIMENTO_INVALIDO_PEAO); // Movimento inválido para o peão
}
}
break;
case 'T':
/* Código para movimento da torre */
for(int i = 1; i + linhaOrigem < 8; i++){ //verifica se é movimento para baixo
if(linhaDestino == linhaOrigem + i && colunaDestino == colunaOrigem){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem + i][colunaOrigem] != ' '){
break;
}
}
for(int i = -1; i + linhaOrigem >= 0; i--){ //verifica se é movimento para cima
if(linhaDestino == linhaOrigem + i && colunaDestino == colunaOrigem){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem + i][colunaOrigem] != ' '){
break;
}
}
for(int i = 1; i + colunaOrigem < 8; i++){ //verifica se é movimento para direita
if(colunaDestino == colunaOrigem + i && linhaDestino == linhaOrigem){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem][colunaOrigem + i] != ' '){
break;
}
}
for(int i = -1; i + colunaOrigem >= 0; i--){ //verifica se é movimento para esquerda
if(colunaDestino == colunaOrigem + i && linhaDestino == linhaOrigem){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem][colunaOrigem + i] != ' '){
break;
}
}
return Msg(MSG_JOGADAS_MOVIMENTO_INVALIDO_TORRE); // Movimento inválido para a torre
case 'C':
/* Código para movimento do cavalo */
if(linhaDestino == linhaOrigem + 2 && colunaDestino == colunaOrigem - 1){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento em "L" em pé para sudoeste
} else if (linhaDestino == linhaOrigem - 2 && colunaDestino == colunaOrigem - 1){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento em "L" em pé para noroeste
} else if(linhaDestino == linhaOrigem + 2 && colunaDestino == colunaOrigem + 1){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento em "L" em pé para sudeste
} else if (linhaDestino == linhaOrigem - 2 && colunaDestino == colunaOrigem + 1){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento em "L" em pé para nordeste
} else if(linhaDestino == linhaOrigem + 1 && colunaDestino == colunaOrigem - 2){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento em "L" deitado para sudoeste
} else if (linhaDestino == linhaOrigem - 1 && colunaDestino == colunaOrigem - 2){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento em "L" deitado para noroeste
} else if(linhaDestino == linhaOrigem + 1 && colunaDestino == colunaOrigem + 2){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento em "L" deitado para sudeste
} else if (linhaDestino == linhaOrigem - 1 && colunaDestino == colunaOrigem + 2){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK"; // Movimento em "L" deitado para nordeste
} else {
return Msg(MSG_JOGADAS_MOVIMENTO_INVALIDO_CAVALO); // Movimento inválido para o cavalo
}
break;
case 'B':
/* Código para movimento do bispo */
for(int i = 1; linhaOrigem + i < 8 && colunaOrigem + i < 8; i++){//Para ver movimento para sudeste
if(linhaDestino == linhaOrigem + i && colunaDestino == colunaOrigem + i){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem + i][colunaOrigem + i] != ' '){
break;
}
}
for(int i = 1; linhaOrigem - i >= 0 && colunaOrigem + i < 8; i++){//Para ver movimento para nordeste
if(linhaDestino == linhaOrigem - i && colunaDestino == colunaOrigem + i){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem - i][colunaOrigem + i] != ' '){
break;
}
}
for(int i = 1; linhaOrigem + i < 8 && colunaOrigem - i >= 0; i++){//Para ver movimento para sudoeste
if(linhaDestino == linhaOrigem + i && colunaDestino == colunaOrigem - i){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem + i][colunaOrigem - i] != ' '){
break;
}
}
for(int i = 1; linhaOrigem - i >= 0 && colunaOrigem - i >= 0; i++){//Para ver movimento para noroeste
if(linhaDestino == linhaOrigem - i && colunaDestino == colunaOrigem - i){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem - i][colunaOrigem - i] != ' '){
break;
}
}
return Msg(MSG_JOGADAS_MOVIMENTO_INVALIDO_BISPO);
case 'Q':
/* Código para movimento da rainha */
//Junção dos movimentos da torre e do bispo
// Movimento da torre
for(int i = 1; i + linhaOrigem < 8; i++){ //verifica se é movimento para baixo
if(linhaDestino == linhaOrigem + i && colunaDestino == colunaOrigem){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem + i][colunaOrigem] != ' '){
break;
}
}
for(int i = -1; i + linhaOrigem >= 0; i--){ //verifica se é movimento para cima
if(linhaDestino == linhaOrigem + i && colunaDestino == colunaOrigem){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem + i][colunaOrigem] != ' '){
break;
}
}
for(int i = 1; i + colunaOrigem < 8; i++){ //verifica se é movimento para direita
if(colunaDestino == colunaOrigem + i && linhaDestino == linhaOrigem){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem][colunaOrigem + i] != ' '){
break;
}
}
for(int i = -1; i + colunaOrigem >= 0; i--){ //verifica se é movimento para esquerda
if(colunaDestino == colunaOrigem + i && linhaDestino == linhaOrigem){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem][colunaOrigem + i] != ' '){
break;
}
}
// Movimento do bispo
for(int i = 1; linhaOrigem + i < 8 && colunaOrigem + i < 8; i++){//Para ver movimento para sudeste
if(linhaDestino == linhaOrigem + i && colunaDestino == colunaOrigem + i){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem + i][colunaOrigem + i] != ' '){
break;
}
}
for(int i = 1; linhaOrigem - i >= 0 && colunaOrigem + i < 8; i++){//Para ver movimento para nordeste
if(linhaDestino == linhaOrigem - i && colunaDestino == colunaOrigem + i){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem - i][colunaOrigem + i] != ' '){
break;
}
}
for(int i = 1; linhaOrigem + i < 8 && colunaOrigem - i >= 0; i++){//Para ver movimento para sudoeste
if(linhaDestino == linhaOrigem + i && colunaDestino == colunaOrigem - i){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem + i][colunaOrigem - i] != ' '){
break;
}
}
for(int i = 1; linhaOrigem - i >= 0 && colunaOrigem - i >= 0; i++){//Para ver movimento para noroeste
if(linhaDestino == linhaOrigem - i && colunaDestino == colunaOrigem - i){
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)) {
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE);
}
return "OK";
} else if (tabuleiro[linhaOrigem - i][colunaOrigem - i] != ' '){
break;
}
}
return Msg(MSG_JOGADAS_MOVIMENTO_INVALIDO_RAINHA);
case 'K':
/* Código para movimento do rei */
if((linhaDestino == linhaOrigem + 1 || linhaDestino == linhaOrigem - 1 || linhaDestino == linhaOrigem) &&
(colunaDestino == colunaOrigem + 1 || colunaDestino == colunaOrigem - 1 || colunaDestino == colunaOrigem)) {
if(CasaAtacada(tabuleiro, linhaDestino, colunaDestino, 1 - jogadorDaVez)){
return Msg(MSG_JOGADAS_CASA_DESTINO_XEQUE); // Casa de destino está sob ataque
} else{
if(movimentoDeixaReiemXeque(tabuleiro, jogadorDaVez, linhaOrigem, colunaOrigem, linhaDestino, colunaDestino)){
return Msg(MSG_JOGADAS_DEIXA_REI_XEQUE); // Movimento colocaria o rei em xeque
} else {
return "OK"; // Movimento válido
}
}
} else {
return Msg(MSG_JOGADAS_MOVIMENTO_INVALIDO_REI); // Movimento inválido para o rei
}
break;
default: //Se não for nenhuma peça válida
return Msg(MSG_JOGADAS_PECA_INVALIDA);
}
}
}
#ifndef JOGADASVALIDAS_H
#define JOGADASVALIDAS_H
#include <stdbool.h>
const char* JogadaValida(char tabuleiro[8][8], int linhaOrigem, int colunaOrigem, int linhaDestino, int colunaDestino, int jogadorDaVez);
bool XequeMate(char tabuleiro[8][8], int JogadorDaVez);
bool Afogamento(char tabuleiro[8][8], int JogadorDaVez);
#endif // JOGADASVALIDAS_H