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

O programa encerra depois do primeiro comando

Estou usando o site replit para executar o código, e estava funcionando normalmente até que modifiquei a minha função "acabou()" da mesma forma que no vídeo "Implementando a finalização do jogo", e então o meu programa encerra após o primeiro comando.

A única diferença que eu percebi do meu código para o da vídeo-aula são os nomes das variáveis e funções.

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

MAPA m;
POSICAO heroi;

int paraOndeFantasmaVai(int xAtual, int yAtual, 
  int* xDestino, int* yDestino) {

  int opcoes[4][2] = {
    { xAtual, yAtual +1},
    { xAtual +1, yAtual},
    { xAtual, yAtual -1},
    { xAtual -1, yAtual}
  };

  srand(time(0));
  for(int i = 0; i < 10; i++) {
    int posicao = rand() % 4;

    if(podeAndar(&m, FANTASMA, opcoes[posicao][0], opcoes[posicao][1])) {
      *xDestino = opcoes[posicao][0];
      *yDestino = opcoes[posicao][1];

      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 = paraOndeFantasmaVai(i, j, 
          &xDestino, &yDestino);
        
        if(encontrou) {
          andaNoMapa(&m, i, j, xDestino, yDestino);
        }
      }
      
    }
  }
  
  liberaMapa(&copia);
}

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

int ehDirecao(char direcao){
  return direcao == ESQUERDA || 
    direcao == CIMA || 
    direcao == BAIXO || 
    direcao == DIREITA;
}

void move(char direcao) {

  if(!ehDirecao(direcao)) {
    return;
  }

  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;
  }

  if(!ehValida(&m, proximoX, proximoY))
    return;
  
  if(!ehVazia(&m, proximoX, proximoY))
    return;

  andaNoMapa(&m, heroi.x, heroi.y, proximoX, proximoY);
  heroi.x = proximoX;
  heroi.y = proximoY;
  
  
}

int main(void) {

  
  leMapa(&m);
  encontraMapa(&m, &heroi, HEROI);

  do {
    imprimeMapa(&m);

    char comando;
    scanf(" %c", &comando);
    move(comando);
    fantasmas();
    
  } while (!acabou());

  

  liberaMapa(&m);
  return 0;
}
3 respostas

Oi Giovanna! Tudo bem?

Aparentemente o problema está na função acabou(). Ela verifica se o herói ainda está no mapa, e se não estiver, o jogo termina. Vamos dar uma olhada mais detalhada para ver onde pode estar o problema.

A função acabou() está assim:

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

A função encontraMapa() deve retornar 0 se não encontrar o herói no mapa, e um valor diferente de 0 se encontrar. Portanto, se encontraMapa() retornar 0 (não encontrou o herói), fogeFogeNoMapa será 0, e acabou() retornará 1, o que encerra o jogo.

Vamos verificar alguns pontos:

  1. Posição Inicial do Herói: Certifique-se de que o herói está sendo corretamente posicionado no mapa no início do jogo. Verifique se encontraMapa(&m, &heroi, HEROI) está encontrando o herói corretamente.

  2. Movimentação do Herói: Verifique se a função move() está atualizando corretamente a posição do herói. O herói pode estar sendo movido para fora do mapa ou para uma posição inválida.

  3. Mapa: Certifique-se de que o mapa está sendo lido corretamente e que o herói está presente no mapa inicial.

Para ajudar a depurar, você pode adicionar alguns printf para verificar o estado do herói e do mapa em diferentes pontos do código. Por exemplo:

int acabou() {
  POSICAO pos;
  int fogeFogeNoMapa = encontraMapa(&m, &pos, HEROI);
  printf("Herói encontrado: %d\n", fogeFogeNoMapa); // Adicione esta linha
  return !fogeFogeNoMapa;
}

E também no início do main():

int main(void) {
  leMapa(&m);
  encontraMapa(&m, &heroi, HEROI);
  printf("Posição inicial do herói: (%d, %d)\n", heroi.x, heroi.y); // Adicione esta linha

  do {
    imprimeMapa(&m);

    char comando;
    scanf(" %c", &comando);
    move(comando);
    fantasmas();
    
  } while (!acabou());

  liberaMapa(&m);
  return 0;
}

Esses printf ajudarão a entender se o herói está sendo encontrado corretamente e se está se movendo conforme esperado. Caso não consiga resolver, peço que envie todo o projeto para que eu faça testes, use o GitHub ou Drive do Google como meio de envio.

Espero ter ajudado e bons estudos!

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

Obrigada pela ajuda, ainda não consegui resolver. Segue o link para o repositório.

https://github.com/giovanna004/FogeFogeJogo

solução!

Boa tarde, Giovanna!

Peço desculpas pela demora em respondê-la.

O erro de "Segmentation fault" geralmente ocorre quando o programa tenta acessar uma área de memória que não foi alocada ou que não é permitida para o processo. No seu código, existem alguns pontos que podem causar esse erro.

Vou destacar a causa e outros pontos que você deve corrigir(todas as correções são no arquivo mapa.c):

  1. Erro na Função copiaMapa: Na função copiaMapa, você está atribuindo destino->linhas e destino->colunas a si mesmas. Isso deve ser feito com os valores de origem, como mostrado abaixo:

    destino->linhas = origem->linhas;
    destino->colunas = origem->colunas;
    
  2. Função leMapa: A função leMapa aloca a matriz de acordo com o valor das variáveis m->linhas e m->colunas. No entanto, ao ler o conteúdo do mapa do arquivo, você está assumindo que sempre haverá 5 linhas. Isso pode causar problemas se o número de linhas for diferente de 5.

    Você deve substituir o loop que lê o mapa para usar o número correto de linhas:

    for (int i = 0; i < m->linhas; i++) {
        fscanf(f, "%s", m->matriz[i]);
    }
    
  3. Função imprimeMapa: Similar ao ponto anterior, na função imprimeMapa, o número de linhas deve ser baseado em m->linhas:

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

Todo o código corrigido fica assim:

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


void copiaMapa(MAPA* destino, MAPA* origem){
  destino->linhas = origem->linhas;
  destino->colunas = origem->colunas;

  alocaMapa(destino);

  for (int 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];
  m->matriz[xDestino][yDestino] = personagem;
  m->matriz[xOrigem][yOrigem] = VAZIO;
}

int ehValida(MAPA* m, int x, int y) {
  if(x >= m->linhas)
    return 0;
  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 (int i = 0; i < m->linhas; i++){
    for (int 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 (int i = 0; i < m->linhas; i++){
    free(m->matriz[i]);
  }
  free(m->matriz);
}

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

void leMapa(MAPA* m) {
  FILE*  f;

  f = fopen("mapa.txt", "r");
  if(f == 0) {
    printf("Erro na leitura do mapa\n");
    exit(1);
  }

  fscanf(f, "%d %d", &(m->linhas), &(m->colunas));

  alocaMapa(m);

  for (int i = 0; i < m->linhas; i++) {
      fscanf(f, "%s", m->matriz[i]);
  }


  fclose(f);

}


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

Com essas correções, o código deve evitar o erro de segmentação.

Caso tenha outros problemas estarei aqui para ajudar!