Gostaria de implementar um programa de um jogo que com certeza marcou sua infância? Aprenda aqui a fazer de maneira bem simples seu próprio jogo de batalha naval! Você além de aprender e treinar os conceitos básicos da linguagem C, também poderá se divertir com seus amigos!
Índice
- 1 Visão geral da abordagem ao problema
- 1.1 Guia de funções
- 1.2 Como será criado as variáveis
- 1.3 Como serão criadas as funções
- 1.4 Visão do jogo rodando
- 2 Código main – Criando variáveis e chamando funções
- 3 Inicializando o Tabuleiro
- 4 Mostrando o tabuleiro
- 5 Preenchendo o tabuleiro com navios
- 6 Atirando (Interação com o jogador)
- 7 Verificando se acertou
- 8 Alterando o tabuleiro depois da ação
- 9 Inspiração
Visão geral da abordagem ao problema
Para começar, irei fazer uma abordagem geral de como será implementado o código desse jogo. Esse jogo é bem simples, consiste basicamente na criação de funções que representarão cada ação do programa no decorrer do jogo.
Guia de funções
As funções que serão utilizadas são as seguintes:
1. void inicializaTabuleiro() – inicialmente coloca o valor -1 em todas as partes do tabuleiro
2. void mostraTabuleiro() – recebe o tabuleiro de inteiros e os exibe
3. void iniciaNavios() – essa função sorteia 3 pares de inteiros, que são a localização dos 3 navios
4. void darTiro() – recebe um tiro (linha e coluna) do usuário, e armazena na variável tiro[]
5. boolean acertou() – checa se o tiro dado acertou um navio
6. void alteraTabuleiro() – após o tiro ser dado, o tabuleiro é alterado, mostrando o tiro que foi dado(se acertou ou errou)
Como será criado as variáveis
Começaremos com a criação das variáveis dentro do código main. Será criada uma variável ‘tabuleiro[5][5]’ que irá armazenar o tabuleiro do jogo, uma variável ‘navio[3][2]’ que irá armazenar a posição (linha e coluna) dos 3 navios que estão escondidos no tabuleiro, a variável ‘tiro[2]’ que vai armazenar a posição (linha e coluna) do tiro que o jogador vai dar a cada rodada, além da variável ‘tentativa’, que vai armazenar o número de tentativas que o jogador fez até acertar os 3 navios e, por fim, a variável ‘acertos’ que contabiliza o número de navios que você acertou.
Como serão criadas as funções
A função ‘inicializaTabuleiro()’ é acionado, pra criar o tabuleiro com o número ‘-1’ em todas as posições.
Depois é a função ‘iniciaNavios()’, que vai sortear a posição de 3 navios (linha e coluna). Essa função sorteia dois números, entre 0 e 4. Depois ele checa se esse número já saiu, pois não podem existir dois barcos na mesma posição. Caso já tenha saído, entra num laço do…while que fica sorteando números, e só sai quando sorteia outro par de números que ainda não é a localização de um navio.
Após isso, na main(), vamos iniciar o jogo. Os jogos geralmente se iniciam através de um laço do…while. No caso, a condição do while é ‘acertos!=3’. Ou seja, enquanto você não acertar os 3 navios, o jogo não para.
A primeira coisa que ocorre no laço é mostrar o tabuleiro, através do laço ‘mostraTabuleiro()’. Essa função checa cada posição o ‘tabuleiro’. Se for -1 ele exibe água, ‘~’. Se for 0, ele exibe o tiro que foi dado e errou ‘*’, e se for 1, ele exibe ‘X’ que indica que você acertou um navio naquela posição.
Após mostrar o tabuleiro, você vai dar seu tiro, através da função ‘darTiro()’, que recebe dois inteiros. Note que, o usuário vai digitar números de 1 até 5, pois ele conta de 1 até 5. Você, como programador C é que conta de 0 até 4. Portanto, quando o usuário entrar com a linha e com a coluna, SUBTRAIA 1 de cada valor desses. Ou seja, se usuário entrou com (1,1), no seu tabuleiro C 5×5 isso representa a posição (0,0).
Após o tiro ser dado, nosso jogo em C vai checar se esse tiro acertou algum navio. Isso é feito com a função ‘acertou()’, que retorna ‘true’ caso acerte e ‘false’ caso erre. Na função, ele simplesmente checa se esse par de valores – ‘tiro[2]’ – que definem seu tiro, batem com algum dos valores que definem a posição dos navios – navios[3][2]. Caso acerte, o valor de ‘acertos’ aumenta. Acertando ou errando, ‘tentativas’ aumenta, pois uma tentativa foi feita. Note que, a linha do seu tiro é ‘tiro[0]’ e a coluna é ‘tiro[1]’. A linha de cada navio é ‘navios[x][0]’ e a coluna de cada navio é ‘navios[x][1]’, onde ‘x’ é o número dos navios. No nosso caso, são 3 navios, ou seja, vai de 0 até 2.
Acertando ou errando, o tabuleiro vai ser alterado. O tiro que você deu vai alterar aquele local do tabuleiro, vai aparecer tiro dado ‘*’ ou tiro que acertou ‘X’. Vamos fazer isso através da função ‘alteraTabuleiro()’.
Aqui, usamos uma função dentro do outro. Checamos se o tiro dado ‘tiro[2]’ acertou através da função, que já usamos e explicamos, ‘acertou’. Caso acerte, a posição do tabuleiro referente ao tiro que você deu vai mudar de ‘-1’ para ‘1’. Caso erre, a posição do tabuleiro referente ao tiro que você deu vai mudar de ‘-1’ para ‘0’. Assim, quando o tabuleiro for exibido, já vai exibir com ‘*’ ou ‘X’ no lugar desse antigo ‘~’.
Visão do jogo rodando
Código main – Criando variáveis e chamando funções
Agora faremos o “main”, o código principal do programa. É aqui que iremos chamar as funçõe cujas quais foram citadas anteriormente e fazer uma série de condicionais para que as funções sejam chamadas nas ordens e condições certas para que funcione o nosso jogo.
int main() { int tabuleiro[5][5]; int navios[3][2]; int tiro[2]; int tentativas=0; int acertos=0;
Nesse primeiro trecho serão criadas as variáveis que utilizaremos como parâmetros nas chamadas das funções.
inicializaTabuleiro(tabuleiro); iniciaNavios(navios); printf("\n");
Na chamada dessas duas funções, inicializaremos o tabuleiro e sortearemos as posiçoes dos navios.
do{ mostraTabuleiro(tabuleiro); darTiro(tiro); tentativas++; if(acertou(tiro,navios)){ acertos++; } alteraTabuleiro(tiro,navios,tabuleiro); }while(acertos!=3); printf("\n\n\nJogo terminado. Você acertou os 3 navios em %d tentativas", tentativas); mostraTabuleiro(tabuleiro); }
No trecho acima, o programa fará a chamada de todas as outras funções e entrará em um laço através do “do-while” e o jogo só será encerrado quando a quantidade de acertos for igual a 3.
Como podem ver, o ‘main’ do nosso programa é bem pequeno e simples; consiste apenas na criação das variáveis e na chamada das funções. Agora iremos mostrar como serão implementadas essas funções.
Inicializando o Tabuleiro
Começaremos agora a criar as funções de inicialização que serão utilizadas no código principal de seu programa. Essas funções serão como se fossem a inteligência do jogo, ou seja, serão os passos que iremos automatizar para o jogo seguir rodando após cada jogada.
Primeiramente iremos criar uma função para inicializar o tabuleiro:
void inicializaTabuleiro(int tabuleiro[][5]) { int linha, coluna; for(linha=0 ; linha < 5 ; linha++ ) for(coluna=0 ; coluna < 5 ; coluna++ ) tabuleiro[linha][coluna]=-1; }
Como pode ser visto, utilizaremos um laço de “for” para fazer esse processo. O trecho “tabuleiro[linha][coluna]=-1;” corresponde ao complemento da matriz do tabuleiro do jogo com o caractere “-1”, que corresponde ao simbolo “~” e será a nossa representação à água.
-1 vai ser mostrado como “~” que indica que a posição tem “água”.
0 vai ser mostrado como “*” que indica que o tiro foi na “água”.
1 vai ser mostrado como “X” que indica que o tiro foi no “navio”.
Mostrando o tabuleiro
Agora iremos inicializar a função responsável por mostrar o tabuleiro na tela. Primeiro iremos imprimir os índices das colunas e das linhas:
void mostraTabuleiro(int tabuleiro[][5]) { int linha, coluna; printf("\t1 \t2 \t3 \t4 \t5"); printf("\n");
Agora iremos checar as condições para saber qual caractere será imprimido, depedendo da situação desenrolada pela escolha do jogador, lembrando que:
-1 correspondente ao “~”, agua
0 correspondente ao “*”, tiro na água
1 caractere correspondente ao “X”, tiro no navio.
for(linha=0 ; linha < 5 ; linha++ ){ printf("%d",linha+1); for(coluna=0 ; coluna < 5 ; coluna++ ){ if(tabuleiro[linha][coluna]==-1){ printf("\t~"); }else if(tabuleiro[linha][coluna]==0){ printf("\t*"); }else if(tabuleiro[linha][coluna]==1){ printf("\tX"); } } printf("\n"); } }
Utilizaremos os laços de “for” juntamente com as condicionais “if” para saber o que imprimir no tabuleiro depedendo da escolha do jogador.
Agora iremos preencher o tabuleiro com navios em posições aleatórias. Essa função irá sortear 3 pares de inteiros, que são a localização dos 3 navios. Para isso utilizaremos a função “srand”. O número sorteado será utilizado para definir o posicionamento dos navios. As matrizes “navios[navio][0]= rand()%5” e “navios[navio][1]= rand()%5” correspondem a linha e coluna que serão armazenados os números sorteados.
void iniciaNavios(int navios[][2]){ srand(time(NULL)); int navio, anterior; for(navio=0 ; navio < 3 ; navio++){ navios[navio][0]= rand()%5; navios[navio][1]= rand()%5;
Aagora vamos checar se esse par não foi sorteado. Se foi, faremos a saida do “do while” enquanto sortear um número diferente.
for(anterior=0 ; anterior < navio ; anterior++){ if( (navios[navio][0] == navios[anterior][0])&&(navios[navio][1] == navios[anterior][1]) ) do{ navios[navio][0]= rand()%5; navios[navio][1]= rand()%5; }while( (navios[navio][0] == navios[anterior][0])&&(navios[navio][1] == navios[anterior][1]) ); } } }
Atirando (Interação com o jogador)
Iremos começar agora a interação com o jogador. Vamos pedir para que ele entre com a linha e a coluna, respectivamente, e armazenaremos essa informação em um array. Utilizaremos após o armazenamento a expressão “tiro[0]–” e “tiro[1]–” para ordenar a posição da linha e da coluna escolhida pelo jogador.
void darTiro(int tiro[2]) { printf("Linha: "); scanf("%d",&tiro[0]); tiro[0]--; printf("Coluna: "); scanf("%d",&tiro[1]); tiro[1]--; }
Verificando se acertou
Nessa função iremos verificar se o tiro acertou o navio. Utilizaremos os parâmetros “int tiro[2] e int navios[][2]”, ou seja, o que faremos é utilizar os dados inseridos pelo jogador de linha e coluna, e iremos comparar com as posições sorteadas para posicionar os 3 navios no tabuleiro e iremos retornar 1 dessa função caso o tiro seja no navio.
int acertou(int tiro[2], int navios[][2]) { int navio; for(navio=0 ; navio < 3 ; navio++){ if( tiro[0]==navios[navio][0] && tiro[1]==navios[navio][1]){ printf("Você acertou o tiro (%d,%d)\n",tiro[0]+1,tiro[1]+1); return 1; } } return 0; }
Alterando o tabuleiro depois da ação
Essa função irá fazer a alteração do tabuleiro depois do tiro dado pelo jogador, alterando entre o número 1 (X – tiro no navio) e o número 0 (* – tiro na água). Utilizaremos como parâmetro a função “acertou” dentro dos condicionais de “if-else”.
void alteraTabuleiro(int tiro[2], int navios[][2], int tabuleiro[][5]){ if(acertou(tiro,navios)) tabuleiro[tiro[0]][tiro[1]]=1; else tabuleiro[tiro[0]][tiro[1]]=0; }
Inspiração
Você também poderá ver informações da construção de um código para a reprodução de um jogo de batalha naval em: