Visão Geral do Projeto
Este projeto consiste no desenvolvimento de um jogo de Gomoku (Cinco em Linha) para console, implementado em Java, que integra elementos inspirados no Campo Minado. Diferente do Gomoku tradicional, o tabuleiro contém posições ocultas com efeitos especiais que são ativados quando um jogador realiza uma jogada nessas coordenadas.
Os efeitos especiais incluem:
- Célula Morta: A jogada falha e a posição torna-se permanentemente bloqueada.
- Bomba: A jogada falha e limpa todas as peças em uma área de 3x3 ao redor do ponto.
- Inversão de Cor: A peça jogada assume a cor do oponente.
- Recrutamento: Permite ao jogador converter uma peça adversária existente para sua própria cor.
- Reset de Posição: Remove uma peça de qualquer lugar do tabuleiro.
- Sorte: Concede uma jogada extra imediata ao jogador atual.
Além do modo multiplayer local, o sistema inclui um motor de IA que utiliza algoritmos de pontuação baseados em padrões para determinar a melhor jogada, embora a IA seja imune aos efeitos especiais das células ocultas.
Arquitetura do Sistema
O software foi estruturado seguindo princípios de modularidade para reduzir o acoplamento, dividindo-se em cinco camadas principais:
- mainProgram: Ponto de entrada da aplicação e gerenciamento de estados globais.
- ioStream: Responsável pela persistência de dados, como o histórico de vitórias e recordes.
- music: Gerencia a reprodução de áudio em segundo plano (BGM) e efeitos sonoros (SFX) via threads.
- service: Contém a lógica de negócio, regras do jogo e algoritmos da IA.
- view: Interface de usuário baseada em console e renderização do tabuleiro.
Destaques Técnicos de Implementação
1. Controle de Fluxo do Menu
A navegação principal utiliza uma estrutura de controle simplificada para gerenciar os diferentes modos de jogo e configurações:
switch (opcaoSelecionada) {
case MODO_PVP:
isContraIA = false;
executarFluxoJogo();
break;
case MODO_PVIA:
isContraIA = true;
executarFluxoJogo();
break;
case MOSTRAR_AJUDA:
exibirInstrucoes();
break;
case CONFIGURACOES:
ajustarPreferencias();
break;
case SAIR:
System.out.println("Encerrando aplicação...");
fecharRecursos();
statusSistema = false;
break;
default:
System.out.println("Comando inválido.");
}
2. Renderização Visual no Console
Para melhorar a experiência do usuário em um ambiente de texto, foram utilizados códigos de escape ANSI para colorir as peças no tabuleiro:
// Exemplo de impressão de peça Azul (Jogador 1) e Vermelha (Jogador 2)
System.out.print("\u001B[34m[X]\u001B[0m "); // Azul
System.out.print("\u001B[31m[O]\u001B[0m "); // Vermelho
3. Inicialização Aleatória de Efeitos
O tabuleiro é preenchido com efeitos especiais de forma randômica durante a inicialização, garantindo que a quantidade de cada efeito respeite os limites pré-definidos:
void distribuirEfeitosEspeciais(int tipoEfeito, int quantidade) {
Random gerador = new Random();
while (quantidade > 0) {
int linha = gerador.nextInt(TAMANHO_TABULEIRO);
int coluna = gerador.nextInt(TAMANHO_TABULEIRO);
if (gradeJogo[linha][coluna] == VAZIO) {
gradeJogo[linha][coluna] = tipoEfeito;
quantidade--;
}
}
}
4. Tratamento de Exceções na Entrada de Dados
Para evitar falhas causadas por entradas de tipos inválidos (como caracteres onde se esperam inteiros), foi implementado um mecanismo de captura de erro:
public static void capturarCoordenadas() {
boolean entradaValida = false;
while (!entradaValida) {
try {
System.out.print("Informe a Linha e Coluna: ");
coordX = scanner.nextInt();
coordY = scanner.nextInt();
entradaValida = true;
} catch (InputMismatchException e) {
System.out.println("Erro: Digite apenas números inteiros.");
scanner.nextLine(); // Limpeza do buffer
}
}
}
Estrutura de Dados Global
A classe GlobalVariable centraliza os estados críticos do jogo, permitindo que diferentes camadas acessem o tabuleiro, o contador de turnos e as configurações de áudio de maneira eficiente.
public class ConfigGlobais {
public static int[][] tabuleiro = new int[15][15];
public static int turnoAtual = 0;
public static boolean partidaAtiva = true;
// Constantes de Efeitos
public static final int EFEITO_BOMBA = 4;
public static final int EFEITO_REVERSO = 5;
// Caminhos de Recursos
public static final File AUDIO_BGM = new File("resources/trilha.wav");
public static final File EFEITO_SONORO = new File("resources/click.wav");
}
A lógica de vitória é verificada após cada movimento válido, analisando as quatro direções principais (horizontal, vertical e as duas diagonais) a partir do último ponto jogado. Caso um efeito especial seja ativado, a lógica de turno pode ser alterada (como no caso do efeito "Sorte") ou o tabuleiro pode sofrer modificações estruturais imediatas (como no efeito "Bomba").