0

So I have to scan a maze number of rows and columns for a file, bit I got that part.

File have a form like this

3
4
....
.#.#
....

Where the first number is a number of rows and the second is the number of columns. Character '#' is a wall and I can't go there but I can go through '.' Now I have to, using structures and pointers, find a shortest path to any point in a maze. Example structure is in my code (Cell).

I have no idea how to do this. I've created a array 'visited' to track which cell I've been to and function to check if a point is valid.

Somehow I have to point to other points in NORTH, WEST, EAST, SOUTH directions.

#include "stdafx.h"
#include "stdlib.h"

//Starting point
#define START_X 0
#define START_Y 0

//example structure I have to use
struct Cell
{
    struct Cell *north;
    struct Cell *east;
    struct Cell *south;
    struct Cell *west;
    char value;
    int distance;
};

//function that prints a maze
void printMap(char **charMaze, int row, int col)
{

    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            printf_s("%c", charMaze[i][j]);
        }
        printf_s("\n");
    }

}

// functions that check if a point is valid
bool isValid(int x, int y, int row, int col)
{
    if (x < row && y < col && x >= 0 && y >= 0)
        return true;

    return false;
}

bool isSafe(char **charMaze, int **visited, int x, int y)
{
    if (charMaze[x][y] == '#' || visited[x][y]==true)
        return false;

    return true;
}

//My attempt at solving this
int BFS(char **maze,int END_X, int END_Y,int row, int col, bool **visited)
{
    isValid(END_X, END_Y, row, col);    
}

int main()
{

    FILE *map;
    int row, col;

    // I open a file with a maze
    fopen_s(&map, "test1.txt", "r");
    // I scan a row number and column number
    fscanf_s(map, "%d", &row);
    fscanf_s(map, "\n%d\n", &col);

    char** charMaze;
    charMaze = (char**)malloc(row * sizeof(char*));

    for (int i = 0; i < row; i++)
        charMaze[i] =(char*)malloc(col * sizeof(char));

    bool** visited;
    visited = (bool**)malloc(row * sizeof(bool*));

    for (int i = 0; i < row; i++)
        visited[i] = (bool*)malloc(col * sizeof(bool));
    //set staring point as true and other points as false
    visited[START_X][START_Y] = true;
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            visited[i][j] = false;
        }
    }
    // I scan a maze and I put it in a array
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            fscanf_s(map, "%c", &charMaze[i][j],1);
        }
        fscanf_s(map, "\n");
    }

    fclose(map);
    //printMap(charMaze, row, col);

    return 0;

}

EsmaeelE
  • 2,331
  • 6
  • 22
  • 31

2 Answers2

0

You could use the Dijkstra algorithm to find the shortest path.

As result, suppose you have to return a path from the starting point to every dot in the maze.

You have here an implementation of the Dijkstra algorithm.

You would need to adapt it your maze map.

You could use a matrix of structs where each struct contains the x,y coordinate of the previous node, the distance to the starting node, and the flag done.

Edit

If fact you don’t even need to implement the Dijkstra algorithm. A simple flooding algorithm will do because the weight of all vertex of the graph is one.

Here is how I would do it.

#include <stdbool.h>
#include <stdlib.h>


enum State { Wall, Unvisited, WaveBorder, NewWaveBorder, Done };

// define the structure holding coordinates of previous cell in path and state
typedef struct Cell {
    int i,j; // coordinates of predecessor in path
    enum State state;
} Cell; 

// visit cell (vi,vj) from neighbor cell (i,j)
void visitCell(Cell **m, int vi, int vj, int i, int j) {
    if m[vi][vj].state == Unvisited {
        m[vi][vj].state = NewWaveBorder;
        m[vi][vj].i = i;  
        m[vi][vj].j = j;
    }
}

Cell** findShortestPath(char **maze, int row, int col, int iStart, int jStart) {
    Cell **m = malloc(sizeof(Cell*)*row);
    for (int i = 0; i < row; i++)
        m[i] = malloc(sizeof(Cell)*col);
    for (int i = 0; i < row; i++)
        for (int j = 0; j < col; j++)
            if (maze[i][j] == '.') {
                m[i][j].state = Unvisited;
                m[i][j].i = m[i][j].j = -1;
            } else {
                m[i][j].state = Wall;
                m[i][j].i = m[i][j].j = -2;
            }

    m[iStart][jStart].state = WaveBorder;
    bool done = false;
    while (!done) {
        for (int i = 0; i < row; i++)
            for (int j = 0; j < col; j++) {
                if (m[i][j].state != waveBorder)
                    continue;
                if (i > 0)
                    visitCell(m, i-1, j, i, j);
                if (j > 0)
                    visitCell(m, i, j-1, i, j);
                if (i < row)
                    visitCell(m, i+1, j, i, j);
                if (j < col)
                    visitCell(m, i, j+1, i, j);
                m[i][j].state = Done;
            }
        done = true;
        for (int i = 0; i < row; i++)
            for (int j = 0; j < col; j++)
                if (m[i][j].state == Unvisited)
                    done = false;
                else if (m[i][j].state == NewWaveBorder)
                    m[i][j].state == WaveBorder;
    }
    return m;
}

The path from cell (i,j) is stored in the matrix of Cell structures. Each cell has the coordinates of the predecessor in the path toward (iStart, jStart). The cell (iStart,jStart) will have (-1,-1) as predecessor in the path. Walls will have (-2,-2) as predecessors.

Eliahu Aaron
  • 4,103
  • 5
  • 27
  • 37
chmike
  • 20,922
  • 21
  • 83
  • 106
  • Oh, I think I will try that. But I have no idea how this struct would look like. And how can I adapt my maze to dijkstra algorithm? – Glitterfrost Jan 21 '20 at 16:15
  • There is no need to adapt your maze. You just need a second matrix to keep track of the paths, the distance and which cell has been done. The distance is just to a neighbor cell and is one. – chmike Jan 22 '20 at 07:31
  • @Glitterfrost I have provided a suggested solution to build the shortest path matrix. I didn’t test it, but it should be ok. – chmike Jan 22 '20 at 09:07
  • @chmike Is `malloc()` need `free()` before return from function? – EsmaeelE Jan 22 '20 at 10:24
  • @EsmaeelE no, `free` is not needed because the matrix of structs is returned by the function. – chmike Jan 22 '20 at 10:28
0

Okay I did something like this. But it doesn't work for some reason.

#include "stdafx.h"
#include "stdlib.h"

//Starting point
#define START_X 0
#define START_Y 0
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))

//example structure I have to use
struct Cell
{
    struct Cell *north;
    struct Cell *east;
    struct Cell *south;
    struct Cell *west;
    char value;
    int distance;


};


//function that prints a maze
void printMap(char **charMaze, int row, int col)
{

    for (int i = 0; i < row; i++)
    {

        for (int j = 0; j < col; j++)
        {
            printf_s("%c", charMaze[i][j]);
        }
        printf_s("\n");
    }

}

void printMap2(int **intMaze, int row, int col)
{

    for (int i = 0; i < row; i++)
    {

        for (int j = 0; j < col; j++)
        {
            printf_s("%d", intMaze[i][j]);
        }
        printf_s("\n");
    }

}

// functions that check if a point is valid
bool isValid(int x, int y, int row, int col)
{
    if (x < row && y < col && x >= 0 && y >= 0)
    {

        printf("Dobry punkt");
        return true;
    }
    else
    {
        printf("Nieprawidlowy");
    }

    return false;
}

bool isSafe(char **charMaze, int **visited, int x, int y)
{
    //char wall = '#';
    //char character = charMaze[x][y];
    if (charMaze[x][y] =='#' || visited[x][y])
    {

        printf("unsafe");
        return false;
    }
    else
    {
        printf("safe");
    }

    return true;
}

bool canGo(Cell *cell, int d)
{
    if (cell == NULL)
    {
        return 0;
    }
    if (cell->value == '#')
        return 0;
    if (cell->value == '.')
        return 1;
    if (cell->distance > d)
        return 1;

        return 0;
}

void findShortestPath(char **maze, int start_X, int start__Y, int i, int j, int row, int col, int **visited, int minDist, int dist)
{
    if (j = start__Y && i == start_X)
    {
        minDist = MIN(dist, minDist);
        return;
    }
    visited[start_X][start__Y] = 1;

    //bottom
    if (isValid(start_X + 1, start__Y, row, col) && isSafe(maze, visited, start_X + 1, start__Y))
        findShortestPath(maze, start_X + 1, start__Y, i, j, row, col, visited, minDist, dist + 1);
    //right
    if (isValid(start_X, start__Y + 1, row, col) && isSafe(maze, visited, start_X, start__Y + 1))
        findShortestPath(maze, start_X, start__Y + 1, i, j, row, col, visited, minDist, dist + 1);
    //top
    if (isValid(start_X - 1, start__Y, row, col) && isSafe(maze, visited, start_X + 1, start__Y))
        findShortestPath(maze, start_X + 1, start__Y, i, j, row, col, visited, minDist, dist + 1);
    //left
    if (isValid(start_X, start__Y - 1, row, col) && isSafe(maze, visited, start_X, start__Y - 1))
        findShortestPath(maze, start_X, start__Y - 1, i, j, row, col, visited, minDist, dist + 1);
    visited[start_X, start__Y] = 0;

}

int main()
{
    FILE *map;
    int start_X = 0;
    int start_Y = 0;
    int row, col;
    struct Cell cell;
    // I open a file with a maze
    fopen_s(&map, "test1.txt", "r");
    // I scan a row number and column number
    fscanf_s(map, "%d", &row);
    fscanf_s(map, "\n%d\n", &col);


    char** charMaze;
    charMaze = (char**)malloc(row * sizeof(char*));

    for (int i = 0; i < row; i++)
        charMaze[i] = (char*)malloc(col * sizeof(char));

    int** visited;
    visited = (int**)malloc(row * sizeof(int*));

    for (int i = 0; i < row; i++)
        visited[i] = (int*)malloc(col * sizeof(int));

    memset(visited, 0, sizeof visited);
    int minDist = INT_MAX;

    // I scan a maze and I put it in a array
    for (int i = 0; i < row; i++)
    {

        for (int j = 0; j < col; j++)
        {
            fscanf_s(map, "%c", &charMaze[i][j], 1);
        }
        fscanf_s(map, "\n");
    }

    findShortestPath(charMaze, start_X, start_Y, 2, 3, row, col, visited, minDist, 0);

    if (minDist != INT_MAX)
    {
        printf("Najkrotsza droga z poczatku do konca to %d", minDist);

    }
    else
    {
        printf("Can't get to the point");
    }


    printMap(charMaze, row, col);

    fclose(map);

return 0;

}
EsmaeelE
  • 2,331
  • 6
  • 22
  • 31