Моя реализация волнового алгоритма Ли.
Лабиринт хранится в файле in.txt. (# - стена; S - старт; G - финиш; свободный сектор - точка или пробел)
В результате: в командную строку выводится количество шагов
в файл out.txt выводится лабиринт и все кратчайшие пути
Лабиринт хранится в файле in.txt. (# - стена; S - старт; G - финиш; свободный сектор - точка или пробел)
В результате: в командную строку выводится количество шагов
в файл out.txt выводится лабиринт и все кратчайшие пути
/* Входной файл: in.txt Выходной файл: out.txt Условные обозначения во входном и выходном файлах: '.' = доступная позиция '#' = стена 'S' = старт 'G' = финиш '+' = путь */ #include <string.h> #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <time.h> #include <dos.h> #include <windows.h> #include <stdio.h> #define FALSE 0 #define TRUE 1 //максимальный размер лабиринта #define MAX_NROWS 80 #define MAX_MCOLS 160 int nRows=0; int mCols=0; char maze[MAX_NROWS][MAX_MCOLS]={'#'}; //матрица-лабиринт int steps[MAX_NROWS][MAX_MCOLS]={0};//матрица расстояний от старта //до всех возможных точек int find_min_path(int x,int y); int find_path(int x, int y,int step); //функция загрузки лабиринта из файла в массив int load() { FILE *f; if ((f = fopen("in.txt","r"))==NULL) return FALSE; char ch; int i=0,j=0; do { do { ch = fgetc(f); if (ch==' ') //пробелы заменяем на точки ch='.'; maze[i][j]=ch; if (i>MAX_NROWS || j>MAX_MCOLS) return FALSE; if (j>mCols) mCols=j; j++; } while (ch!='\n' && ch!=EOF); j=0; i++; if (i>nRows ) nRows=i; } while (!feof(f)); fclose(f); return TRUE; } // функция сохранения результата в файл //(лабиринт со всеми кратчайшими путями) int save() { FILE *f; f = fopen("out.txt","a+"); for (int i = 0; i <nRows;i++ ) { for (int j = 0; j <mCols;j++ ) { fputc(maze[i][j],f); } fputc('\n',f); } fputs("\n\n",f); fclose(f); } //функция нахождения произвольного символа в лабиринте //(для нахождения координат старта и финиша) void findSymbol(int &x,int &y,char Symbol) { for (int i = 0; i <nRows;i++ ) { for (int j = 0; j <mCols;j++ ) { if (maze[i][j]==Symbol){ x=i; y=j; return; } } } } int num = 0; //минимальное количество шагов int main(void) { load(); int x=0,y=0; findSymbol(x,y,'S'); find_path(y, x,0); findSymbol(x,y,'G'); find_min_path(y,x); printf("Success!\n"); save(); printf("Steps: %i\n",num); getch(); return 0; } //рекурсивная функция заполнения матрицы расстояний int find_path(int x, int y,int step) { //если вышли за пределы лабиринта - возвращаемся if ( x < 0 || x > mCols - 1 || y < 0 || y > nRows - 1 ) return FALSE; //если дошли до финиша - возвращаемся if ( maze[y][x] == 'G' ) return FALSE; //если наткнулись на стену - возвращаемся if (maze[y][x] == '#') return FALSE; //если путь свободен - увеличиваем количество шагов //и запоминаем его в мацциве if (maze[y][x]!='S' && maze[y][x]!='G') { step++; if (steps[y][x]>step || steps[y][x]==0) { steps[y][x]=step; } } //4 напровления - 4 вызова //идем в определенном направлении если мы там еще не были //(расстояние м матрице расстояний==0) //или соблюдаются все условия: //1) расстояние там больше текущего+1 //2) расстояние там не рамно текущее-1 //(что бы не пойти обратно тому же пути) if (maze[y][x+1]!='S') if ((steps[y][x+1]>(step+1) && steps[y][x+1]!=(step-1)) || steps[y][x+1]==0) if ( find_path(x + 1, y,step) == TRUE ) return FALSE; if (maze[y][x-1]!='S') if ((steps[y][x-1]>(step+1) && steps[y][x-1]!=(step-1) ) || steps[y][x-1]==0) if ( find_path(x - 1, y,step) == TRUE ) return FALSE; if (maze[y+1][x]!='S') if ((steps[y+1][x]>(step+1) && steps[y+1][x]!=(step-1) ) || steps[y+1][x]==0) if ( find_path(x, y + 1,step) == TRUE ) return FALSE; if (maze[y-1][x]!='S') if ((steps[y-1][x]>(step+1) && steps[y-1][x]!=(step-1) ) || steps[y-1][x]==0) if ( find_path(x, y - 1,step) == TRUE ) return FALSE; return FALSE; } //рекурсивная функция, обходящаа лабиринт с финиша до старта //по кратчайшему пути int find_min_path(int x,int y) { //если вышли за пределы лабиринта - возвращаемся if ( x < 0 || x > mCols - 1 || y < 0 || y > nRows - 1 ) return FALSE; //если данная позиция - не старт и не финиш, то помечаем ее как путь if (maze[y][x]!='S' && maze[y][x]!='G') { maze[y][x] = '+'; } //если дошли до старта - возвращаемся if ( maze[y-1][x] == 'S' ) return FALSE; if ( maze[y+1][x] == 'S' ) return FALSE; if ( maze[y][x-1] == 'S' ) return FALSE; if ( maze[y][x+1] == 'S' ) return FALSE; //изнаем расстояния во всех 4-х направлениях int up = 0; int right =0; int left = 0; int down = 0; if (y!= 0) up = steps[y - 1][x]; if (x!= 0) left =steps[y][x - 1]; if (x!= mCols-1) right = steps[y][x+1]; if (y!= nRows-1) down = steps[y+1][x]; //и ищем минимальное int min = up; if ((right<min && right!=0) || min==0) min = right; if ((left<min && left!=0)|| min==0) min = left; if ((down<min && down!=0) || min==0) min = down; if (num==0 ) num=min; //там, где минимальное, туда и идём if (up==min && up!=0) if ( find_min_path(x,y - 1) == TRUE ) return TRUE; if (right==min && right!=0 ) if ( find_min_path(x + 1,y) == TRUE ) return TRUE; if (left==min && left!=0) if ( find_min_path(x - 1,y) == TRUE ) return TRUE; if (down==min && down!=0) if ( find_min_path(x,y + 1) == TRUE ) return TRUE; return FALSE; }