quarta-feira, 3 de janeiro de 2018

Problema da recursão para analisar posições vizinhas em um mapa ou tabuleiro


Compartilhe!

Neste laboratório, devemos criar um programa que explore a recursão em que, dado um mapa de um setor, seja capaz de determinar quantas bases do Império e quantas bases rebeldes estão presentes naquela região.

Na matriz, o caractere '*' representa parte de uma base do Império, o caractere '#' representa parte de uma base dos rebeldes e o caractere '-' representa uma área não construída; as bases não possuem uma forma geométrica definida.

Duas bases de um mesmo grupo (Império ou Aliança/rebelde) não podem estar encostadas uma na outra, por exemplo: não há duas posições vizinhas que pertençam a duas bases diferentes do Império (ou da Aliança).

Dada uma posição (l,c) do mapa, definimos como sendo suas posições vizinhas aquelas que estão imediatamente acima (l-1,c), abaixo (l+1,c), à esquerda (l,c-1), à direita (l,c+1), nas diagonais superiores (l-1,c-1) e (l-1,c+1), e nas diagonais inferiores (l+1,c-1) e (l+1,c+1). Uma base é determinada pelo conjunto de caracteres '#' (ou '*') que são alcançáveis entre si.

Exemplo de entrada:
10 10
- - - - - * - * * -
* - * * - - * * * -
* * * * * * * * * -
- * - - * # - - - *
# * * - * - * - - *
- - - - * * - * - -
- * * * * - - * * -
- - - * - - * - * *
* - - - * - - * * *
* * * - - - - * * -

Saída correspondente:
Bases rebeldes: 2
Bases do imperio: 2

#include <stdio.h>
#include <stdlib.h>

//Esta função recebe uma matriz de char, uma posição (linha e coluna) e sua dimensão.
void destrua(char id, char **mapa, int linha, int coluna, int linhas, int colunas){

    //Nenhum dos casos pode ser verdadeiro:
    if (!(linha<0 || linha>=linhas || coluna<0 || coluna>=colunas))
  if(mapa[linha][coluna]==id){

   mapa[linha][coluna] = '-';//Substitua a posição atual da matriz por 'área não construída'.

   //Destruindo as posições vizinhas chamando a própria função:
   //À esquerda:
   destrua(id, mapa, linha, coluna-1, linhas, colunas);
   
   //À direita:
   destrua(id, mapa, linha, coluna+1, linhas, colunas);

   //Abaixo:
   destrua(id, mapa, linha+1, coluna, linhas, colunas);
   
   //Acima:
   destrua(id, mapa, linha-1, coluna, linhas, colunas);
   
   //Diagonais superiores:
   destrua(id, mapa, linha-1, coluna-1, linhas, colunas);
   destrua(id, mapa, linha-1, coluna+1, linhas, colunas);

   //Diagonais inferiores:
   destrua(id, mapa, linha+1, coluna-1, linhas, colunas);
   destrua(id, mapa, linha+1, coluna+1, linhas, colunas);

  }

}

int main(){

 int linhas, colunas, imperio = 0, rebelde = 0;
 char **mapa;//Um apontador para um apontador, onde no conteúdo constará um char.

 scanf("%d %d ", &linhas, &colunas);//Leia as dimensões do mapa.

 //Alocação da memória da matriz que representará o mapa.
 //1º a alocação das linhas (que é uma "coluna"):
 mapa = (char**) malloc(linhas*sizeof(char*));
 //2º a alocação das colunas (que são vetores)
 for(int i=0; i<linhas; i++)
  mapa[i] = (char*) malloc(colunas * sizeof(char));

 //Leitura do mapa. Cada char é adicionado a uma posição da matriz:
 for(int i=0; i<linhas; i++)
  for(int j=0; j<colunas; j++)
   scanf("%c ", &mapa[i][j]);

 //Agora percorra a matriz comparando seu conteúdo num switch:
 for(int i=0; i<linhas; i++)
  for(int j=0; j<colunas; j++){
   switch (mapa[i][j]){
    case '#'://Caso #, incrementa as bases rebeldes e destrua/substitua a posição e as vizinhas por '-':
    rebelde++, destrua('#', mapa, i, j, linhas, colunas);
    break;
    
    case '*'://Semelhante ao caso anterior:
    imperio++, destrua('*', mapa, i, j, linhas, colunas);
    break;
    
    default: break;
   }
    }
 //Imprima o resultado:
 printf("Bases rebeldes: %d\n", rebelde);
 printf("Bases do imperio: %d\n", imperio);

 return 0;

}