O jogo de campo minado envolve uma grade onde o jogador deve revelar células sem acionar minas. A implementação em C requer a definição de estruturas de dados para o tabuleiro, lógica para posicionamento aleatório de minas e interação do jogador.
Inicialmente, define-se um menu para o usuário escolher entre jogar ou sair. O menu é implementado com uma função que exibe opções e um loop do-while para controlar o fluxo do programa.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void exibir_menu() {
printf("********** 1. Iniciar Jogo **********\n");
printf("********** 0. Sair **********\n");
}
int main() {
int escolha = 0;
srand((unsigned int)time(NULL));
do {
exibir_menu();
printf("Selecione uma opcao: ");
scanf("%d", &escolha);
switch (escolha) {
case 1:
iniciar_jogo();
break;
case 0:
printf("Encerrando o programa.\n");
break;
default:
printf("Opcao invalida. Tente novamente.\n");
}
} while (escolha != 0);
return 0;
}
A função iniciar_jogo encapsula a lógica principal. Define-se um tabuleiro de 9x9 com bordas adicionais para evitar acessos inválidos, usando constantes para as dimensões.
#define LINHAS 9
#define COLUNAS 9
#define LINHAS_TOTAL (LINHAS + 2)
#define COLUNAS_TOTAL (COLUNAS + 2)
#define TOTAL_MINAS 10
Duas matrizes de caracteres são criadas: uma para armazenar a posição das minas (com '0' para vazio e '1' para mina) e outra para exibir ao jogador (com '*' para células ocultas).
void iniciar_jogo() {
char tabuleiro_minas[LINHAS_TOTAL][COLUNAS_TOTAL] = {0};
char tabuleiro_visivel[LINHAS_TOTAL][COLUNAS_TOTAL] = {0};
inicializar_matriz(tabuleiro_minas, LINHAS_TOTAL, COLUNAS_TOTAL, '0');
inicializar_matriz(tabuleiro_visivel, LINHAS_TOTAL, COLUNAS_TOTAL, '*');
posicionar_minas(tabuleiro_minas, LINHAS, COLUNAS);
exibir_tabuleiro(tabuleiro_visivel, LINHAS, COLUNAS);
jogador_interagir(tabuleiro_minas, tabuleiro_visivel, LINHAS, COLUNAS);
}
A inicialização da matriz utiliza uma função genérica para preencher todos os elementos com um caractere especificado, iterando com laços aninhados.
void inicializar_matriz(char matriz[LINHAS_TOTAL][COLUNAS_TOTAL], int linhas, int colunas, char valor) {
for (int i = 0; i < linhas; i++) {
for (int j = 0; j < colunas; j++) {
matriz[i][j] = valor;
}
}
}
O posicionamento aleatório de minas emprega a biblioteca rand para gerar coordenadas dentro dos limites do tabuleiro, garantindo que não haja sobreposição.
void posicionar_minas(char tabuleiro[LINHAS_TOTAL][COLUNAS_TOTAL], int linhas, int colunas) {
int minas_restantes = TOTAL_MINAS;
while (minas_restantes > 0) {
int linha = rand() % linhas + 1;
int coluna = rand() % colunas + 1;
if (tabuleiro[linha][coluna] == '0') {
tabuleiro[linha][coluna] = '1';
minas_restantes--;
}
}
}
A exibição do tabuleiro inclui índices de linhas e colunas para facilitar a navegação, percorrendo apanas as áreas internas do tabuleiro.
void exibir_tabuleiro(char matriz[LINHAS_TOTAL][COLUNAS_TOTAL], int linhas, int colunas) {
printf(" ");
for (int i = 1; i <= colunas; i++) {
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= linhas; i++) {
printf("%d ", i);
for (int j = 1; j <= colunas; j++) {
printf("%c ", matriz[i][j]);
}
printf("\n");
}
}
A interação do jogador ocorre em um loop até que todas as células sem minas sejam reveladas ou uma mina seja acionada. O cálculo de minas adjacentes soma os valores dos oito vizinhos e subtrai o caractere '0' para obter a contagem numérica.
int contar_minas_adjacentes(char tabuleiro[LINHAS_TOTAL][COLUNAS_TOTAL], int linha, int coluna) {
return (tabuleiro[linha-1][coluna] + tabuleiro[linha-1][coluna-1] + tabuleiro[linha][coluna-1] +
tabuleiro[linha+1][coluna] + tabuleiro[linha][coluna+1] + tabuleiro[linha+1][coluna+1] +
tabuleiro[linha+1][coluna-1] + tabuleiro[linha-1][coluna+1] - 8 * '0');
}
void jogador_interagir(char minas[LINHAS_TOTAL][COLUNAS_TOTAL], char visivel[LINHAS_TOTAL][COLUNAS_TOTAL], int linhas, int colunas) {
int x, y;
int celulas_reveladas = 0;
int total_celulas_seguras = linhas * colunas - TOTAL_MINAS;
while (celulas_reveladas < total_celulas_seguras) {
printf("Digite as coordenadas (linha coluna): ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= linhas && y >= 1 && y <= colunas) {
if (minas[x][y] == '1') {
printf("Voce acionou uma mina! Fim de jogo.\n");
exibir_tabuleiro(minas, linhas, colunas);
break;
} else {
int minas_proximas = contar_minas_adjacentes(minas, x, y);
visivel[x][y] = '0' + minas_proximas;
exibir_tabuleiro(visivel, linhas, colunas);
celulas_reveladas++;
}
} else {
printf("Coordenadas invalidas. Tente novamente.\n");
}
}
if (celulas_reveladas == total_celulas_seguras) {
printf("Parabens! Voce completou o jogo.\n");
}
}
A separação em arquivos de cabeçalho e implementação promove modularidade, com declarações em jogo.h e definições em jogo.c.