3
respostas

Continuando o jogo

Arquivo fogefoge.c:

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

MAPA m;
POSICAO heroi;

int praondeofantasmavai(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 = praondeofantasmavai(i, j, &xdestino, &ydestino);

                if(encontrou) {
                    andanomapa(&m, i, j, xdestino, ydestino);
                }
            }

        }
    }
    liberamapa(&copia);
}

int acabou() {
    POSICAO pos;

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

    return ganhou || perdeu;		
}

int ehdirecao(char direcao) {
    return
        direcao == 'a' || 
        direcao == 'w' ||
        direcao == 's' ||
        direcao == 'd';
}

void move(char direcao) {
    int x;
    int y;
    
    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(!podeandar(&m, HEROI, proximox, proximoy))
        return;
    
    andanomapa(&m, heroi.x, heroi.y, proximox, proximoy);
    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);
}
Arquivo fogefoge.h:

#define CIMA 'w'
#define BAIXO 's'
#define DIREITA 'd'
#define ESQUERDA 'a'

void move(char direcao);
int acabou();

int ehdirecao(char direcao);

void fantasmas();

int praondeofantasmavai(int xatual, int yatual, int* xdestino, int* ydestino);
3 respostas
Arquivo mapa.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mapa.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) {
        // acha a posição do foge foge
    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("mapas.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 < 5; i++) {
        fscanf(f, "%s", m->matriz[i]);
    }   

    fclose(f);

}

void imprimemapa(MAPA* m) {
    for(int i = 0; i < 5; i++) {
        printf("%s\n", m->matriz[i]);
    }
}
Arquivo mapa.h:

#define HEROI '@'
#define VAZIO '.'
#define PAREDE_VERTICAL '|'
#define PAREDE_HORIZONTAL '-'
#define FANTASMA 'F'

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 x);


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

O meu código está correto ?

Oi, Guilherme! Como vai?

Sobre sua dúvida: o código não está 100% correto ainda. Vamos resolver isso. Abaixo estão os ajustes objetivos que você precisa aplicar para o jogo funcionar de forma confiável:

  1. Assinatura incoerente de encontramapa no header
  • O .h declara uma versão com 4 parâmetros, mas a implementação usa 3.
    Corrija o mapa.h:

Veja este exemplo:
mapa.h (corrigido)

int encontramapa(MAPA* m, POSICAO* p, char c);
  1. Validação de limites incompleta (coordenadas negativas)
  • Sua ehvalida não verifica x &lt; 0 e y &lt; 0. Isso causa acesso inválido à memória.
    Corrija ehvalida assim:

mapa.c (corrigido)

int ehvalida(MAPA* m, int x, int y) {
    if (x &lt; 0) return 0;
    if (y &lt; 0) return 0;
    if (x &gt;= m-&gt;linhas) return 0;
    if (y &gt;= m-&gt;colunas) return 0;
    return 1;
}
  1. Leitura e impressão do mapa fixas em 5 linhas
  • Você está desconsiderando m-&gt;linhas e m-&gt;colunas. Isso quebra mapas com tamanhos diferentes.
    Use as dimensões lidas do arquivo:

mapa.c (corrigido)

void lemapa(MAPA* m) {
    FILE* f = fopen("mapas.txt", "r");
    if (f == 0) {
        printf("Erro na leitura do mapa\n");
        exit(1);
    }

    fscanf(f, "%d %d", &amp;(m-&gt;linhas), &amp;(m-&gt;colunas));
    alocamapa(m);

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

    fclose(f);
}

void imprimemapa(MAPA* m) {
    for (int i = 0; i &lt; m-&gt;linhas; i++) {
        printf("%s\n", m-&gt;matriz[i]);
    }
}
  1. Seed do gerador de números aleatórios em lugar indevido
  • Você chama srand(time(0)) dentro de praondeofantasmavai. Isso reinicializa a semente várias vezes no mesmo segundo, gerando movimentos repetitivos.
    Semeie uma única vez em main e remova de praondeofantasmavai.

fogefoge.c (trechos corrigidos)

/* Remova um dos #include &lt;stdio.h&gt; (linha duplicada) */

int praondeofantasmavai(int xatual, int yatual, int* xdestino, int* ydestino) {
    int opcoes[4][2] = {
        { xatual   , yatual + 1 },
        { xatual + 1 , yatual   },
        { xatual   , yatual - 1 },
        { xatual - 1 , yatual   }
    };

    /* &lt;-- REMOVIDO: srand(time(0)); */

    for (int i = 0; i &lt; 10; i++) {
        int posicao = rand() % 4;
        if (podeandar(&amp;m, FANTASMA, opcoes[posicao][0], opcoes[posicao][1])) {
            *xdestino = opcoes[posicao][0];
            *ydestino = opcoes[posicao][1];
            return 1;
        }
    }
    return 0;
}

int main() {
    /* Semente global uma única vez */
    srand((unsigned)time(NULL));

    lemapa(&amp;m);
    encontramapa(&amp;m, &amp;heroi, HEROI);

    do {
        imprimemapa(&amp;m);

        char comando;
        scanf(" %c", &amp;comando);
        move(comando);
        fantasmas();

    } while (!acabou());

    liberamapa(&amp;m);
    return 0;
}
  1. Pequenos ajustes de limpeza
  • Remova o bloco vazio após o while (!acabou()); em main.
  • Mantenha apenas um #include &lt;stdio.h&gt; em fogefoge.c.
  1. Sobre colisões FANTASMA x HEROI
  • Sua lógica atual permite que o fantasma se mova para a mesma célula do herói, substituindo-o na matriz. Isso é válido se a regra de jogo for “encostou, perdeu”.
  • Se quiser impedir que o fantasma “pise” no herói, altere podeandar para bloquear quando HEROI estiver no destino (mas aí precisa de uma checagem separada de derrota). Do jeito que você explicou, manter como está está correto para encerrar o jogo ao substituir o herói.

Resumo objetivo

  • Corrija a assinatura de encontramapa no header.
  • Conserte ehvalida para tratar negativos.
  • Use m-&gt;linhas/m-&gt;colunas em leitura e impressão.
  • Semente o RNG uma vez no main e remova de praondeofantasmavai.
  • Limpe includes duplicados e bloco vazio.

Ajuste seu código assim e o jogo vai ficar funcional e previsível.

Fico à disposição. Abraços e bons estudos!