Find and show the way - labyrinth in C

4

Well, someone can help me. I need to implement a recursive function that gets a labyrinth and a current position.

  

The maze is given by a char array where 'X' represents a wall, '0' represents a path, 'E' represents the input, and 'S' represents the output. The goal is to print on the screen a valid path leading from the entrance to the exit, this path does not have to be the shortest, but it can not pass twice through the same house. The labyrinth is indexed by% w / w, where width and height are the number of houses on the X axis and the Y axis respectively, for example, the labyrinth below is width 5 and height 6. The entry is in the house (3, 0) and the exit in the house (2,5):

XOSXX
OOOXX
OXXXX
OXXOX
OXXOX
OOOEX
     

An example of a workaround for this problem would be the following path:   (0.4) (1.0) (1.0) (0, 1) (0, 2) (0, 3) (0.4) (1, 4) (1, 5) (2, 5)

My question is how can I be printing on the screen a path leading from the entrance to the exit. Code so far:

#include <stdio.h>
#include <stdlib.h>
void print_position(int x, int y);
void print_maze(char **maze, int largura, int altura);
int labirinto(int x_atual, int y_atual, char **maze, int largura, int 
altura){
int imaior = x_atual;
int imenor = x_atual;
int ybaixo = y_atual;
int ycima = y_atual;
while ( imaior < largura - 1){
if(maze[x_atual + 1][y_atual] != 'X' && maze[x_atual + 1][y_atual] != 
'P'){
       maze[x_atual][y_atual] = 'P';
       x_atual += 1;
}
imaior++;
}
while(imenor > 0){
if(maze[x_atual - 1][y_atual] != 'X'  && maze[x_atual -1][y_atual] != 
'P') {
     maze[x_atual][y_atual] = 'P';
       x_atual -= 1;
   }
imenor--;
}
while(ycima > 0){
if(maze[x_atual][y_atual - 1] != 'X' && maze[x_atual][y_atual - 1] != 
'P'){
    maze[x_atual][y_atual] = 'P';
    y_atual -= 1;
}
ycima--;
}
while(ybaixo < altura - 1){
if(maze[x_atual][y_atual + 1] != 'X' && maze[x_atual][y_atual + 1] != 
'P'){
    maze[x_atual][y_atual] = 'P';
    y_atual += 1;
}
ybaixo++;
}
maze = labirinto(x_atual , y_atual,maze , largura , altura);
}
int main(void){
int largura, altura, x_saida, y_saida, x, y;
scanf("%d %d\n", &largura, &altura);
char ** a = malloc(largura * sizeof(char*));
for(x = 0; x < largura; x++){
a[x] = malloc(altura * sizeof(char));
}
for(y = altura - 1; y >= 0; y--){
for(x = 0; x < largura; x++){
  a[x][y] = getchar();
  if(a[x][y] == 'S'){
    x_saida = x;
    y_saida = y;
  }
}
getchar(); //pegar a quebra de linha
}
print_maze(a, largura, altura);
 //eu acredito que seja mais facil comecar a busca pela saida
labirinto(x_saida, y_saida, a, largura, altura);
printf("\n");
return 0;
}
void print_maze(char **maze, int largura, int altura){
int x, y;
for(y = altura - 1; y >= 0; y--){
for(x = 0; x < largura; x++){
  printf("%c", maze[x][y]);
}
printf("\n");
}
}
void print_position(int x, int y){
  printf("(%d, %d)", x, y);
}
    
asked by anonymous 26.08.2018 / 00:40

1 answer

0

I did not study your code thoroughly, but it seemed to me much more complicated than necessary. Running it in this little maze you gave, it bursts the timeout.

A simpler approach is to use the search in depth . She is especially good at solving mazes.

The idea of searching in depth is to do more or less like the Greek legend of Theseus in the Cretan maze. With a ball of wool, trace the path traveled and when you want to go back to try another path, collect the wool back to the ball.

The search algorithm in depth is recursive: In a given place, try to follow a path as far as it can, returning whenever it can not proceed. If you do not go that way, try for another, returning whenever you can not proceed. If no path from where you are leads to nowhere, then step back to try another path.

I will use < , > , v and ^ to plot the path.

The implementation looks like this:

int labirinto(int x_atual, int y_atual, char **maze, int largura, int altura) {
    // Se tentou sair do labirinto, este não é o caminho certo.
    if (x_atual < 0 || x_atual >= largura || y_atual < 0 || y_atual >= altura) return 0;

    char aqui = maze[x_atual][y_atual];

    // Verifica se achou a saída.
    if (aqui == 'S') return 1;

    // Se bateu na parede ou voltou para algum lugar que já esteve,
    // então este não é o caminho certo.
    if (aqui == 'X' || aqui == '>' || aqui == '<' || aqui == 'v' || aqui == '^') return 0;

    // Tenta ir para cima.
    maze[x_atual][y_atual] = '^';
    if (labirinto(x_atual, y_atual + 1, maze, largura, altura)) return 1;

    // Tenta ir para baixo.
    maze[x_atual][y_atual] = 'v';
    if (labirinto(x_atual, y_atual - 1, maze, largura, altura)) return 1;

    // Tenta ir para a esquerda.
    maze[x_atual][y_atual] = '<';
    if (labirinto(x_atual - 1, y_atual, maze, largura, altura)) return 1;

    // Tenta ir para a direita.
    maze[x_atual][y_atual] = '>';
    if (labirinto(x_atual + 1, y_atual, maze, largura, altura)) return 1;

    // Não deu, então volta.
    maze[x_atual][y_atual] = 'O';   
    return 0;
}

In% w / w, only a few changes are required:

int main(void) {
    int largura, altura, x_entrada, y_entrada;
    scanf("%d %d\n", &largura, &altura);
    char **a = malloc(largura * sizeof(char*));
    for (int x = 0; x < largura; x++) {
        a[x] = malloc(altura * sizeof(char));
    }
    for (int y = altura - 1; y >= 0; y--) {
        for (int x = 0; x < largura; x++) {
            a[x][y] = getchar();
            if (a[x][y] == 'E') {
                x_entrada = x;
                y_entrada = y;
            }
        }
        getchar(); //pegar a quebra de linha
    }
    printf("Entrada:\n");
    print_maze(a, largura, altura);
    labirinto(x_entrada, y_entrada, a, largura, altura);
    printf("\nSaída:\n");
    print_maze(a, largura, altura);
    return 0;
}

The result was this:

Entrada:
XOSXX
OOOXX
OXXXX
OXXOX
OXXOX
OOOEX

Saída:
X>SXX
>^OXX
^XXXX
^XXOX
^XXOX
^<<<X

See here working on ideone.

The way you need to print is still missing. But having the labyrinth just the way it is, you just have to crawl the main , < , > and ^ and you should get it easily.

I also tried a larger labyrinth and it worked out too:

Entrada:
OOOOOOOOOO
OXXOXXOXXO
OOXOOXOXXX
XOXXXXSXOO
OOOXOXXXOX
XOXXOOOOOX
OOXXOXXXEX
OXXXOOOXXX
OXOXOXOOOO
OOOOOXOXOX

Saída:
>>>>>>vOOO
^XXOXXvXXO
^<XOOXvXXX
X^XXXXSXOO
O^OXOXXXOX
X^XXv<<<<X
>^XXvXXX^X
^XXXvOOXXX
^XOXvXOOOO
^<<<<XOXOX

See here working on ideone.

    
26.08.2018 / 06:07