Este guia detalha a criação de um jogo de Campo Minado básico em C, abordando a estrutura do projeto, a lógica do jogo e a resolução de desafios comuns.
Estrutura do Projeto
O projeto é organizado em três arquivos principais:
- Um arquivo de cabeçalho (.h): Para declarações de funções e definições globais.
- Um arquivo de implementação (.c): Contém a definição das funções.
- Um arquivo main (.c): Implementa a função principle (
main) e orquestra o fluxo do jogo.
Inicialização e Configuração do Tabuleiro
Dois arrays bidimensionais são essenciais:
mine_board: Representa a disposição das minas. '1' indica uma mina, '0' indica um local seguro.display_board: O tabuleiro que o jogador vê. Inicializado com '*' para representar células não reveladas.
A inicialização de ambos os tabuleiros é realizada por uma função dedicada. Esta função recebe o array, suas dimensões (linhas e colunas) e o caractere de inicialização.
void initialize_board(char board[ROWS][COLS], int rows, int cols, char fill_char) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
board[i][j] = fill_char;
}
}
}
Exemplo de uso:
initialize_board(mine_board, ROWS, COLS, '0');
initialize_board(display_board, ROWS, COLS, '*');
Colocação de Minas
As minas são distribuídas aleatoriamente no mine_board, marcadas com o caractere '1'.
Interação do Jogador
O jogador insere coordenadas (linha e coluna) para revelar uma célula.
- Se a célula contiver uma mina (
mine_board[row][col] == '1'), o jogo termina em derrota. - Se a célula for segura, o jogo continua.
Revelando Células Seguras e Contagem de Minas Adjacentes
Quando uma célula segura é revelada, é necessário exibir o número de minas em suas células adjacentes. Uma função static é utilizada para calcular esta contagem. Ela verifica as 8 células vizinhas e soma seus valores (convertendo os caracteres '0' e '1' para seus valores numéricos ASCII). O carcatere '0' tem valor ASCII 48, e '1' tem 49.
static int count_adjacent_mines(char mine_board[ROWS][COLS], int row, int col) {
int count = 0;
// Verifica a vizinhança
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (i == 0 && j == 0) continue; // Ignora a própria célula
int neighbor_row = row + i;
int neighbor_col = col + j;
// Verifica se as coordenadas vizinhas estão dentro dos limites do tabuleiro
if (neighbor_row >= 0 && neighbor_row < ROWS && neighbor_col >= 0 && neighbor_col < COLS) {
if (mine_board[neighbor_row][neighbor_col] == '1') {
count++;
}
}
}
}
return count;
}
A lógica original usando subtração de ASCII pode ser substituída por uma verificação direta, que é mais legível:
// Exemplo de como usar a função para exibir o número de minas
int mines_nearby = count_adjacent_mines(mine_board, reveal_row, reveal_col);
display_board[reveal_row][reveal_col] = mines_nearby + '0'; // Converte o inteiro de volta para caractere
Gerenciamento de Erros e Dificludades
Um problema comum é o erro de "símbolos redefinidos" em múltiplos arquivos. Isso pode ser resolvido removendo o arquivo fonte problemático do projeto e recriando-o, ou garantindo que as declarações em arquivos de cabeçalho sejam únicas (usando diretivas #ifndef, #define, #endif).
A navegação entre múltiplos arquivos fonte pode ser confusa. Manter o código bem comentado e praticar a escrita de código frequentemente ajuda a mitigar essa dificuldade.
O jogo continua até que todas as minas sejam descobertas ou uma mina seja acionada.