Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

O mapa funciona apenas 1x quando o comando é 'a' e não funciona para os demais comandos

O código compila sem erros; O primeiro mapa é impresso ok; Ao dar o comando 'a' os personagens movem-se normalmente (caso seja outro comando não consigo imprimir um novo mapa); Insira aqui a descrição dessa imagem para ajudar na acessibilidade Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Caso o primeiro comando seja diferente de 'a' o jogo não prossegue - também não encerra, fica carregando eternamente; Insira aqui a descrição dessa imagem para ajudar na acessibilidadeEstou usando outro compilador (Falcom C++) pois o computador disponibilizado para o curso não permite a instalação do programa recomendado

Seguem meus arquivos

fogefoge.c

#include<stdio.h>
#include<stdlib.h>
#include "fogefoge.h"
#include<time.h>
#include "mapa.h"
#include "mapa.c"

MAPA m;
POSICAO heroi;
int i,j;

int praondeofantasmavai(int xatual, int yatual, int* xdestino, int* ydestino){
    //As opções de deslocamento que o fantasma tem
    int opcoes[4][2] = {
    { xatual, yatual+1},
    { xatual+1, yatual},
    { xatual, yatual-1},
    { xatual-1, yatual}
    };
    srand(time(0));
    //Há 10 chances do fantasma ter um deslocamento para uma posição válida
    for(i=0;i<10;i++){
        //Adquirindo um número randômico qualquer de 0 a 3
        int posicao = rand() % 4;
        //Se for uma posicao válida
        //Nós então atribuímos valores a xdestino e ydestino
        if(podeandar(&m, FANTASMA, opcoes[posicao][0], opcoes[posicao][1])){
            *xdestino = opcoes[posicao][0];
            *ydestino = opcoes[posicao][1];
            //Retorna verdadeiro quando a atribuição ocorre de forma correta
            return 1;
        }
    }
    
    return 0;
}
void fantasmas(){
    MAPA copia;
    
    copiamapa(&copia,&m);
    
    for(i=0;i<m.linhas;i++){
        for(j=0;j<m.colunas;j++){
            
            if (copia.matriz[i][j]==FANTASMA){
                
                int xdestino;
                int ydestino;
                
                int encontrou = praondeofantasmavai(i,j,&xdestino, &ydestino);
                
                if(encontrou){
                    andanomapa(&m, i, j, xdestino, ydestino);
                }
                
                if(ehvalida(&m, i, j+1) && ehvazia(&m, i, j+1)){
                    andanomapa(&m, i, j, i, j+1);
                }
            }
        }
    }
    liberamapa(&copia);
}

int acabou(){
    POSICAO pos;
    int fogefogenomapa = encontramapa(&m, &pos, HEROI);
    return !fogefogenomapa;
}

// Validar a entrada do usuário
// Caso o usuário digite uma letra diferente daquelas usadas para comando então
// o pacman não vai se movimentar
int ehdirecao(char direcao){
    return direcao == 'a' || direcao == 'w' || direcao == 's' || direcao == 'd';
}

void move(char direcao){
    
    // Se não for uma direção válida então o pacman não se movimenta
    if(!ehdirecao(direcao) )
        return;
    
    // Descobrindo o que tem na 'casa' para qual o comando do usuário levaria o pacman
    int proximox = heroi.x;
    int proximoy = heroi.y;
    
    switch(direcao){
        case ESQUERDA:
            proximoy--;
            break;
        case CIMA:
            proximox--;
            break;
        case BAIXO:
            proximox++;
            break;
        case DIREITA:
            proximoy++;
            break;
    }

    // Valida a posicao para a qual o comando do usuário 'aponta'
    // Se a proxima posição não for vazia '.' então o pacman não pode se deslocar
    if(!podeandar(&m, HEROI, proximox, proximoy))
        return;
    
    andanomapa(&m, heroi.x, heroi.y, proximox, proximoy);
    // Atualizando a posição do heroi no mapa
    heroi.x = proximox;
    heroi.y = proximoy;
}

int main(){
    
    lemapa(&m);
    encontramapa(&m,&heroi, HEROI);
    
    do {
        
    imprimemapa(&m);
    
    char comando;
    scanf(" %c", &comando);
    
    move(comando);
    fantasmas();
        
    } while (!acabou());
    
    liberamapa(&m);
    
    return 0;
}

fogefoge.h

//HEADER DEMAIS FUNÇÕES DO JOGO*************************************************
#define CIMA 'w'
#define BAIXO 's'
#define DIREITA 'd'
#define ESQUERDA 'a'

int acabou();
void move(char direcao);
int ehdirecao(char direcao);
void fantasmas();
int praondeofantasmavai(int xatual, int yatual, int* xdestino, int* ydestino);

CONTINUA NOS COMENTÁRIOS

2 respostas

mapa.c

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

int i,j;

void copiamapa(MAPA* destino, MAPA* origem){
    destino->linhas = origem->linhas;
    destino->colunas = origem->colunas;
    
    alocamapa(destino);
    for(i=0;i<origem->linhas;i++){
        strcpy(destino->matriz[i], origem->matriz[i]);
    }
}

void andanomapa(MAPA* m, int xorigem, int yorigem, int xdestino, int ydestino){
    char personagem = m->matriz[xorigem][yorigem];
    //Movimenta qualquer que seja o personagem em uma determinada posição
    m->matriz[xdestino][ydestino] = personagem;
    //Coloca a posição anterior como vazia '.'
    m->matriz[xorigem][yorigem] = VAZIO;
}

int ehvalida(MAPA* m, int x, int y){
    // Se o comando 'apontar' para uma linha maior do que o limite de linhas da matriz
    if(x >= m->linhas)
        return 0;
    // Se o comando 'apontar' para uma coluna maior que o limite de colunas da matriz
    if(y >= m->colunas)
        return 0;
    
    return 1;
}

int ehvazia(MAPA* m, int x, int y){
    return m->matriz[x][y] == VAZIO;
}

int encontramapa(MAPA* m, POSICAO* p, char c){

    for (i=0;i<m->linhas;i++){
        for (j=0;j<m->colunas;j++){
            if(m->matriz[i][j] == c){
                p->x=i;
                p->y=j;
                return 1;
            }
        }
    }
    return 0;
}

int ehparede(MAPA* m, int x, int y){
    return m->matriz[x][y] == PAREDE_VERTICAL || m->matriz[x][y] == PAREDE_HORIZONTAL;
}

int ehpersonagem(MAPA* m, char personagem, int x, int y){
    return m->matriz[x][y] == personagem;
}

int podeandar(MAPA* m, char personagem, int x, int y){
    return
        ehvalida(m, x, y) && !ehparede(m, x, y) &&  !ehpersonagem(m, personagem, x, y);
}

void liberamapa(MAPA* m){
    
   for(i=0;i<m->linhas;i++){
          free(m->matriz[i]);
    }
    
    free(m->matriz);
    
}

void alocamapa(MAPA* m){
    
    m->matriz = (char**)malloc(sizeof(char*) * m->linhas);
    
    for(i=0;i< m->linhas;i++){
        m->matriz[i] = (char*)malloc(sizeof(char) * (m->colunas + 1));
    }
    
}

void lemapa(MAPA* m){
// Abre o arquivo***************************************************************	
    FILE* f;
    f = fopen("mapa.txt", "r");
// Informa se tiver erro na leitura*********************************************    
    if(f==0){
        printf("Erro na leitura do mapa\n");
        exit(1); 
    }
// Lê a quantidade de linhas****************************************************   
    fscanf(f,"%d %d", &(m->linhas), &(m->colunas));
// Aloca o tamanho do array*****************************************************
    alocamapa(m);
// Lê as várias linhas**********************************************************
    for(i=0;i<m->linhas;i++){
        fscanf(f,"%s", m->matriz[i]); 
    }
    fclose(f);
}

void imprimemapa(MAPA* m){
    for(i=0;i<m->linhas;i++){
        printf("%s\n", m->matriz[i]);
    }
}

mapa.h

//HEADER DAS FUNÇÕES RELACIONADAS AO MAPA**************************************
#define HEROI '@'
#define FANTASMA 'F'
#define VAZIO '.'
#define PAREDE_VERTICAL '|'
#define PAREDE_HORIZONTAL '-'

struct mapa{
    char** matriz; 
    int linhas;
    int colunas;
};
typedef struct mapa MAPA;

struct posicao{
    int x;
    int y;
};
typedef struct posicao POSICAO;

void liberamapa(MAPA* m);
void lemapa(MAPA* m);
void alocamapa(MAPA* m);
void imprimemapa(MAPA* m);
int encontramapa(MAPA* m, POSICAO* p, char c);
int ehvalida(MAPA* m, int x, int y);
int ehvazia(MAPA* m, int x, int y);
void andanomapa(MAPA* m, int xorigem, int yorigem, int xdestino, int ydestino);
void copiamapa(MAPA* destino, MAPA* origem);
int podeandar(MAPA* m, char personagem, int x, int y);
int ehparede(MAPA* m, int x, int y);
int ehpersonagem(MAPA* m, char personagem, int x, int y);

mapa.txt

5 10
|--------|
|.F.|..-.|
|..-|.@..|
|.F....-.|
|--------|
solução!

Olá Lorena, tudo bem?

Depois de um tempo testando e comparando com o código disponibilizado pelo curso, percebi que o seu código dá erro de segmentação pelo fato de você definir as variáveis i e j no começo do arquivo fogefoge.c, mas isso por se só não é o problema, o problema está no fato de você utilizar delas mais de uma vez no mesmo arquivo, sendo assim o contador não é zerado na segunda vez que é utilizado.

A solução para esse caso é excluir a declaração no começo do arquivo e declarar cada variável i e j quando for fazer uma nova estrutura for. Segue o código corrigido abaixo:

#include<stdio.h>
#include<stdlib.h>
#include "fogefoge.h"
#include "time.h"
#include "mapa.h"

MAPA m;
POSICAO heroi;

int acabou(){
    POSICAO pos;
    
    int perdeu = !encontramapa(&m, &pos, HEROI);
    int ganhou = !encontramapa(&m, &pos, FANTASMA);

    return ganhou || perdeu;
}
// Validar a entrada do usuário
// Caso o usuário digite uma letra diferente daquelas usadas para comando então
// o pacman não vai se movimentar
int ehdirecao(char direcao){
    return 
    direcao == ESQUERDA || 
    direcao == CIMA || 
    direcao == BAIXO || 
    direcao == DIREITA;
}

void move(char direcao){
    
    // Se não for uma direção válida então o pacman não se movimenta
    if(!ehdirecao(direcao) )
        return;
    
    // Descobrindo o que tem na 'casa' para qual o comando do usuário levaria o pacman
    int proximox = heroi.x;
    int proximoy = heroi.y;
    
    switch(direcao){
        case ESQUERDA:
            proximoy--;
            break;
        case CIMA:
            proximox--;
            break;
        case BAIXO:
            proximox++;
            break;
        case DIREITA:
            proximoy++;
            break;
    }

    // Valida a posicao para a qual o comando do usuário 'aponta'
    // Se a proxima posição não for vazia '.' então o pacman não pode se deslocar
    if(!podeandar(&m, HEROI, proximox, proximoy))
        return;
    
    andanomapa(&m, heroi.x, heroi.y, proximox, proximoy);
    // Atualizando a posição do heroi no mapa
    heroi.x = proximox;
    heroi.y = proximoy;
}

int praondeofantasmavai(int xatual, int yatual, 
    int* xdestino, int* ydestino){
    //As opções de deslocamento que o fantasma tem
    int opcoes[4][2] = {
    { xatual, yatual+1},
    { xatual+1, yatual},
    { xatual, yatual-1},
    { xatual-1, yatual}
    };
    srand(time(0));
    //Há 10 chances do fantasma ter um deslocamento para uma posição válida
    for(int i=0;i<10;i++){
        //Adquirindo um número randômico qualquer de 0 a 3
        int posicao = rand() % 4;
        //Se for uma posicao válida
        //Nós então atribuímos valores a xdestino e ydestino
        if(podeandar(&m, FANTASMA, opcoes[posicao][0], opcoes[posicao][1])){
            *xdestino = opcoes[posicao][0];
            *ydestino = opcoes[posicao][1];
            //Retorna verdadeiro quando a atribuição ocorre de forma correta
            return 1;
        }
    }
    
    return 0;
}
void fantasmas(){
    MAPA copia;
    
    copiamapa(&copia,&m);
    
    for(int i=0;i<m.linhas;i++){
        for(int j=0;j<m.colunas;j++){
            
            if (copia.matriz[i][j]==FANTASMA){
                
                int xdestino;
                int ydestino;
                
                int encontrou = praondeofantasmavai(i,j,&xdestino, &ydestino);
                
                if(encontrou){
                    andanomapa(&m, i, j, xdestino, ydestino);
                }
                
                if(ehvalida(&m, i, j+1) && ehvazia(&m, i, j+1)){
                    andanomapa(&m, i, j, i, j+1);
                }
            }
        }
    }
    liberamapa(&copia);
}


int main(){
    
    lemapa(&m);
    encontramapa(&m,&heroi, HEROI);
    
    do {
        
    imprimemapa(&m);
    
    char comando;
    scanf(" %c", &comando);
    
    move(comando);
    fantasmas();
        
    } while (!acabou());
    
    liberamapa(&m);

}

Note que a posição das funções estão um pouco diferente da que você enviou, fui ajustando para ficar mais fácil a visualização na comparação, mas não altera em nada a execução do mesmo, então não se preocupe.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.