Batalha naval

Batalha1
Batalha naval realizada em 1865 no Riachuelo (Argentina) , Guerra da Tr’plice Aliana (1864- 1870).

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

Batalha2

 

 

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.

 

 

Preenchendo o tabuleiro com navios

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:

http://www.cprogressivo.net/2012/09/batalha-naval-em-c.html