Enviado em 12/05/2016 - 01:31h
Boa noite pessoal,#include <stdio.h>
#include <stdlib.h>
#include "labirinto.h"
int main(int argc, char *argv[]){
labirinto L;
VariaveisLabirinto Variaveis;
TPilha Pilha_de_coordenadas;
Variaveis.m1 = 0; Variaveis.m2 = 0; Variaveis.p1 = 0; Variaveis.p2 = 0; //Inicia com 0 todas as variáveis que serão contadas.
L = leLabirintoDeArquivo(argv);
Pilha_de_coordenadas = achaSaida (L,&Variaveis);
Variaveis.p2 = Tamanho(Pilha_de_coordenadas)-1;
ImprimePilha(Pilha_de_coordenadas,Variaveis,argv);
return 0;
}
labirinto leLabirintoDeArquivo(char **argv){ //A função lê o arquivo e guarda o número de linhas e colunas, o os caracteres do arquivo em uma matriz.
labirinto L;
FILE *fpin = fopen(argv[1], "r"); //abre o arquivo no modo leitura
if (fpin == NULL){ //Testa se o arquivo foi aberto com sucesso.
printf("Abertura do arquivo de entrada falhou.\n");
exit(1);
}
int i,j,k=0; //A variável k dirá se as linhas já foram lidas, para poder ler então as colunas.
L.linhas=0 ; L.colunas=0;
char string [BUFSIZ]; //Esta string conterá a primeira linha do arquivo, onde está escrito a quantidade de linhas e colunas presentes.
fgets (string, BUFSIZ, fpin);
for(i=0;;i++){ //Este for é responsável por transformar os caracteres da primeira linha do arquivo em números, indicando a quantidade de linhas e colunas que o labirinto possui.
if (string[i]>='0' && string[i]<='9' && k==0) L.linhas = (L.linhas * 10) + (string[i] - 48);
else{
if (string[i] == ' ') k=1;
else{
if (string[i]>='0' && string[i]<='9' && k==1) L.colunas = (L.colunas * 10) + (string[i] - 48);
else{
if (string[i]== '\n' || '\0') break;
}
}
}
}
for (i=0 ; i<=L.linhas ; i++){ //Este for é responsável por escrever os caracteres do labirinto na matriz.
for (j=0 ; j<=L.colunas ; j++){
L.matriz[i][j] = fgetc(fpin);
}
}
fclose(fpin);
return L;
}
TPilha achaSaida (labirinto L,VariaveisLabirinto *Variaveis){ //Esta função irá ler o labirinto para tentar achar a saída.
int i=1,j=1;
int operacao; //A variável operacao mostra: 1=Empilhar 2=Desembilhar;
int direcao=1; // A variável mostra: 1=direita; 2=baixo; 3=esquerda; 4=cima.
TPilha Pilha_de_coordenadas;
TItem Coordenada_atual;
TItem auxiliar;
auxiliar.linha = 0 ; auxiliar.coluna = 0;
FPVazia(&Pilha_de_coordenadas); //Função que cria a pilha vazia.
Coordenada_atual.linha = i; Coordenada_atual.coluna = j;
Empilha(Coordenada_atual,&Pilha_de_coordenadas);
while(L.matriz[i][j]!='s'){
switch (direcao){
case 1: //último passo para a direita; Deverá verificar na seguinte ordem: i++, j++, i--, j--;
if (L.matriz[i+1][j]!='#') {
i++; direcao=2;
if ((auxiliar.linha==i)&&(auxiliar.coluna==j)) operacao=2; //Esta condição compara se o novo valor de coordenadas já está presente na pilha.
else operacao=1;} //Verifica à sua direita atual.
else{
if (L.matriz[i][j+1]!='#') {
j++; direcao=1;
if ((auxiliar.linha==i)&&(auxiliar.coluna==j)) operacao=2;
else operacao=1;} //Verifica à sua frente
else {
if (L.matriz[i-1][j]!='#') {
i--; direcao=4;
if ((auxiliar.linha==i)&&(auxiliar.coluna==j)) operacao=2;
else operacao=1;} //Vereficia à sua esquerda
else{
if (L.matriz[i][j-1]!='#') {j--; direcao=3 ; operacao=2;} //Verifica atrás.
else direcao=0; //Se todas as posições em volta forem #, o labirinto nao tem saída.
}
}
}
break;
case 2://último passo para baixo; Deverá verificar na seguinte ordem: j--,i++,j++,i--;
if (L.matriz[i][j-1]!='#') {
j--; direcao=3;
if ((auxiliar.linha==i)&&(auxiliar.coluna==j)) operacao=2;
else operacao=1;}
else{
if (L.matriz[i+1][j]!='#') {
i++; direcao=2;
if ((auxiliar.linha==i)&&(auxiliar.coluna==j)) operacao=2;
else operacao=1;}
else{
if (L.matriz[i][j+1]!='#') {
j++; direcao=1;
if ((auxiliar.linha==i)&&(auxiliar.coluna==j)) operacao=2;
else operacao=1;}
else{
if (L.matriz[i-1][j]!='#') { i--; direcao=4 ; operacao=2; }
else direcao=0; //Se todas as posições em volta forem #, o labirinto nao tem saída.
}
}
}
break;
case 3://último passo para esquerda; Deverá verificar na seguinte ordem: i--,j--,i++,j++;
if (L.matriz[i-1][j]!='#') {
i--; direcao=4;
if ((auxiliar.linha==i)&&(auxiliar.coluna==j)) operacao=2;
else operacao=1;}
else{
if (L.matriz[i][j-1]!='#') {
j--; direcao=3;
if ((auxiliar.linha==i)&&(auxiliar.coluna==j)) operacao=2;
else operacao=1;}
else{
if (L.matriz[i+1][j]!='#') {
i++; direcao=2 ;
if ((auxiliar.linha==i)&&(auxiliar.coluna==j)) operacao=2;
else operacao=1;}
else{
if (L.matriz[i][j+1]!='#') { j++; direcao=1 ; operacao=2; }
else direcao=0; //Se todas as posições em volta forem #, o labirinto nao tem saída.
}
}
}
break;
case 4: //Último passo para cima; Deverá verificar na ordem: j++; i--; j--; i++
if (L.matriz[i][j+1]!='#') {
j++; direcao=1;
if ((auxiliar.linha==i)&&(auxiliar.coluna==j)) operacao=2;
else operacao=1;}
else{
if (L.matriz[i-1][j]!='#') {
i--; direcao=4;
if ((auxiliar.linha==i)&&(auxiliar.coluna==j)) operacao=2;
else operacao=1;}
else{
if (L.matriz[i][j-1]!='#') {
j--; direcao=3;
if ((auxiliar.linha==i)&&(auxiliar.coluna==j)) operacao=2;
else operacao=1;}
else{
if (L.matriz[i+1][j]!='#') { i++; direcao=2 ; operacao=2; }
else direcao=0; //Se todas as posições em volta forem #, o labirinto nao tem saída.
}
}
}
break;
}
if (direcao == 0) break;
switch (operacao){ //Caso a operacao seja: 1=Empilha ; 2=Desempilha
case 1:
if (L.matriz[i][j]=='m') {Variaveis->m1++ ; Variaveis->m2++;}
Coordenada_atual.linha = i; //Coloca as coordenadas no ítem que será adicionado à célula da pilha.
Coordenada_atual.coluna = j;
Empilha(Coordenada_atual,&Pilha_de_coordenadas);
auxiliar = Pilha_de_coordenadas.Topo->Prox->Prox->Item; //Coloca o penúltimo valor da pilha no item auxiliar para que seja comparado no primeiro switch.
Variaveis->p1++; //A variável p1 conta todos os passos dados.
break;
case 2:
Desempilha(&Pilha_de_coordenadas,&Coordenada_atual);
if (L.matriz[Coordenada_atual.linha][Coordenada_atual.coluna]=='m') Variaveis->m2--; //Se o item desempilhado for moeda, retira-se 1 de m2.
L.matriz[Coordenada_atual.linha][Coordenada_atual.coluna] = '#'; //A posição desempilhada deve virar # para que não entre mais nela.
Variaveis->p1++; //A variável p1 conta todos os passos dados.
if ((auxiliar.linha==1) && (auxiliar.coluna=1)) break;
auxiliar = Pilha_de_coordenadas.Topo->Prox->Prox->Item;
break;
}
}
if (direcao==0) Variaveis->saidaEncontrada=0; //Se tiver saído do while por conta da direcao==0, não tem saída.
else Variaveis->saidaEncontrada=1; //Se tiver saído do while porque achou o 's', tem saída.
return Pilha_de_coordenadas;
}
void FPVazia(TPilha *Pilha){ //Cria uma pilha vazia
Pilha->Topo = malloc(sizeof(TCelula));
Pilha->Fundo = Pilha->Topo;
Pilha->Topo->Prox = NULL;
Pilha->Tamanho = 0;
}
int Vazia (TPilha Pilha){ //Testa se a pilha está vazia
return (Pilha.Topo == Pilha.Fundo);
}
void Empilha (TItem x,TPilha *Pilha){ //Coloca um item na pilha
Apontador Aux = malloc(sizeof(TCelula));
Pilha->Topo->Item = x;
Aux->Prox = Pilha->Topo;
Pilha->Topo = Aux;
Pilha->Tamanho++;
}
void Desempilha (TPilha *Pilha, TItem *Item){ //Retora um item da pilha
if (Vazia(*Pilha)) {
printf("Erro: Pilha vazia");
return;
}
Apontador q = Pilha->Topo;
Pilha->Topo = q->Prox;
*Item = q->Prox->Item;
free(q);
Pilha->Tamanho--;
}
int Tamanho(TPilha Pilha){ //Retorna o tamanho da pilha
return Pilha.Tamanho;
}
TPilha InvertePilha (TPilha Pilha){ //Inverte os valores da pilha
TPilha PilhaAux;
FPVazia(&PilhaAux);
TItem x;
while(!Vazia(Pilha)){
Desempilha(&Pilha,&x);
Empilha(x,&PilhaAux);
}
return PilhaAux;
}
void ImprimePilha (TPilha Pilha, VariaveisLabirinto Variaveis, char **argv){ //Imprime os valores da pilha.
FILE *fpout = fopen(argv[2],"w");
if (fpout == NULL){ //Testa se o arquivo foi aberto com sucesso.
printf("Abertura do arquivo de saida falhou.\n");
exit(2);
}
if (Variaveis.saidaEncontrada==1) {
fprintf(fpout,"%i passos no total\n%i moedas no total\n%i passos ate a saida\n%i moedas no caminho certo\n",Variaveis.p1,Variaveis.m1,Variaveis.p2,Variaveis.m2);
Pilha = InvertePilha (Pilha); //Deve-se inverter os valores para que sejam impressos na ordem crescente.
TItem x;
while(!Vazia(Pilha)){
Desempilha(&Pilha,&x);
fprintf(fpout,"%i %i\n",x.linha,x.coluna);
}
}
else fprintf(fpout,"%i passos no total\n%i moedas no total\nSaida nao existente",Variaveis.p1,Variaveis.m1);
}
#ifndef __LAB_HEADER__
#define __LAB_HEADER__
// Mais funcoes e estruturas podem ser definidas caso voce ache que
// va ajudar o seu trabalho
typedef struct {
// numero de linhas
int linhas;
// numero de colunas
int colunas;
char matriz[BUFSIZ][BUFSIZ];
} labirinto;
typedef struct {
// numero total de movimentos durante a busca,
// incluindo movimentos na direcao errada
int p1;
// passos dados na posição certa
int p2;
// numero de moedas encontradas na caminhada total,
int m1;
// numero de moedas encontradas apenas no caminho da posicao
// inicial ate a saida, ignorando as moedas encontradas em
// caminhos errados
int m2;
// 0 caso o labirinto nao tenha saida
// 1 caso ele tenha saida
// Se o labirinto nao tiver saida, moedasEncontradasNoCaminhoCerto
// deve ser zero, assim como o vetor de posicoes deve conter apenas
// a posicao inicial
int saidaEncontrada;
} VariaveisLabirinto ;
// Retorna Uma estrutura representando o labirinto
// especificado no arquivo de entrada. a primeira linha do arquvo
// deve conter dois inteiros especificando o numero L de
// linhas e o numero C de colunas do labirinto. as proximas L linhas devem
// conter C caracteres representando o labirinto.
labirinto leLabirintoDeArquivo(char **argv);
//AS próximas estruturas e funções são utilizadas para criação da pilha;
//A struct TItem contém os ítens que serão guardados em cada célula da pilha.
//Neste caso precisamos gravar qual a posição da matriz (linha e coluna).
typedef struct{
int linha;
int coluna;
} TItem;
typedef struct Celula *Apontador;
typedef struct Celula {
TItem Item;
Apontador Prox;
} TCelula;
typedef struct {
Apontador Fundo;
Apontador Topo;
int Tamanho;
} TPilha;
//A função a seguir cria uma pilha vazia.
void FPVazia (TPilha *Pilha);
//Retorna verdadeiro se a pilha for vazia.
int Vazia (TPilha Pilha);
//A função a seguir adiciona um item à pilha.
void Empilha (TItem x,TPilha *Pilha);
//A função a seguir retira um item da pilha.
void Desempilha (TPilha *Pilha, TItem *Item);
//A função retorna o tamanho da pilha;
int Tamanho(TPilha Pilha);
//Inverte a ordem dos elementos da pilha e retorna a pilha invertida.
TPilha InvertePilha (TPilha Pilha);
//Imprime os elementos da pilha.
void ImprimePilha (TPilha Pilha,VariaveisLabirinto Variaveis,char **argv);
// Retorna uma pilha contendo as coordenadas de saída do labirinto.
// Esta função lê toda a matriz do labirinto e verifica se há saída.
TPilha achaSaida(labirinto L,VariaveisLabirinto *Variaveis);
#endif
13 40
########################################
#i..............m.........#.#...#......#
#.#.#.#.#.##.#.#.######.#.#...#.#.####.#
#.#.#####.##.#.#.....######.##.#..#....s
#.#...#.#.####.#.####........#.#.#.#####
#.######.....##.#......####.##.#.#...#.#
#.############.#.##.#######.##.#.###.#.#
#.#............m..........#.#...m......#
#.##.####.#########.#.#.#.#.###.#.#.##.#
#.#...#...#....#....#.....#.#.#.m.#.##.#
#.#.#######################.#.########.#
#.............#m.......................#
########################################