Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdbool.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdlib.h>
- #define strSize 1000 // число строк/столбцов
- #define upDown 4
- #define left 1
- #define right 2
- // структура карты
- typedef struct {
- int rows;
- int cols;
- unsigned char *cells;
- } Map;
- struct prirustek {
- int dr;
- int ds;
- };
- enum smery { vychod, sever, zapad, jih, POCET_SMERU };
- struct prirustek d[POCET_SMERU] = {
- {0, +1}, // vychod (0)
- {-1, 0}, // sever (1)
- {0, -1}, // zapad (2)
- {+1, 0}, // jih (3)
- };
- // является ли строка числом
- bool isCharNum(char *argument) {
- int len = strlen(argument);
- bool result = true;
- for (int i = 0; i < len; i++) {
- if (!isdigit(argument[i])) {
- result = false;
- }
- }
- return result;
- }
- // сколько слов в строке, без пробелов
- int wordsInStr(char *str) {
- int i;
- int words = 0;
- for (i = 0; i < strlen(str) - 1; i++) {
- if (str[i] == ' ' && str[i+1] != ' ') {
- words++;
- }
- if (str[0] != ' ' && i == 0) {
- words++;
- }
- }
- return words;
- }
- // является ли формат файла txt или нет
- bool fileTxt(char *fileName) {
- if (
- (fileName[strlen(fileName) - 4] == '.') &&
- (fileName[strlen(fileName) - 3] == 't') &&
- (fileName[strlen(fileName) - 2] == 'x') &&
- (fileName[strlen(fileName) - 1] == 't')
- )
- {
- return true;
- }
- else
- {
- fprintf(stderr, "Error: file is not '.txt'");
- return false;
- }
- }
- // получение значения из ячейки стуктуры
- char getCell(Map *map, int row, int col) {
- return map->cells[ row * map->cols + col ];
- }
- // проверка границы сверху или снизу
- bool hasBorderTopOrBottom(char cell) {
- return cell == '4' || cell == '5' || cell == '6' || cell == '7';
- }
- // проверка границы слева
- bool hasBorderLeft(char cell) {
- return cell == '1' || cell == '3' || cell == '5' || cell == '7';
- }
- //проверка границы справа
- bool hasBorderRight(char cell) {
- return cell == '2' || cell == '3' || cell == '6' || cell == '7';
- }
- // проверка конфликта двух рядом стоящих элементов по горизонтали
- bool hasHorizontalConflicts(char leftCell, char rightCell) {
- switch (rightCell){
- case '1' :
- case '3' :
- case '5' :
- case '7' : return leftCell == '1' || leftCell == '4' || leftCell == '5' || leftCell == '0';
- case '0' :
- case '2' :
- case '4' :
- case '6' : return leftCell == '2' || leftCell == '3' || leftCell == '6' || leftCell == '7';
- }
- }
- // проверка конфликта двух рядом стоящих элементов по вертикали
- bool hasVerticalConflicts(char downCell, char upCell) {
- switch (downCell){
- case '1' :
- case '2' :
- case '3' :
- case '0' : return upCell == '4' || upCell == '5' || upCell == '6' || upCell == '7';
- case '4' :
- case '5' :
- case '6' :
- case '7' : return upCell == '1' || upCell == '2' || upCell == '3' || upCell == '0';
- }
- }
- // проверка на конфликт значений элементов двух ячеек
- bool hasConflictCells(Map *map, int i, int j){
- bool error = false;
- if (j > 0){
- error = hasHorizontalConflicts(getCell(map, i, j-1), getCell(map, i, j));
- }
- if (i > 0 && (i + j) % 2 == 0 && !error){
- error = hasVerticalConflicts(getCell(map, i - 1, j), getCell(map, i, j));
- }
- return error;
- }
- // проверка карты
- bool readAndTestMap(Map *map, char *fileName)
- {
- FILE *fp;
- fp = fopen(fileName, "r");
- // проверка, что такой файл есть
- if (fp == NULL) {
- fprintf(stderr, "Can't open file '%s'\n", fileName); // не удалось открыть такой файл
- return false;
- } else {
- char str[strSize] = "";
- // считываем первую строку из файла
- fgets(str, strSize, fp);
- // проверяем, что в строке только 2 слова
- if (wordsInStr(str) == 2) {
- char *firstword = strtok(str, " ");
- char *secondword = strtok(NULL, "\n");
- // проверка, что считаные элементы являются цифрами
- if (isCharNum(firstword) && isCharNum(secondword)) {
- map->rows = atoi(firstword); // определяем количество строк
- map->cols = atoi(secondword); // определяем количество столбцов
- map->cells = malloc(map->rows * map->cols * sizeof(unsigned char) + 1); // выделяем память под структуру
- // начинаем считывать строки из файла
- for (int i = 0; i < map->rows; i++) {
- fgets(str, strSize, fp);
- // проверяем, что количество слов в строке соответствует количеству столбцов
- if (wordsInStr(str) != map->cols) {
- fprintf(stderr, "Invalid\n"); // не соответствует
- return false;
- }
- // меняем символ новой строки на символ конца строки
- if (str[strlen(str)-1] == '\n') {
- str[strlen(str)-1] = '\0';
- }
- int len = strlen(str);
- firstword = strtok(str, " "); // дробим строку по пробелам
- for (int j = 0; j < map->cols || firstword != NULL; j++) {
- // проверка, что число однозначное
- if (firstword[1] != NULL) {
- fprintf(stderr, "Invalid\n"); // в числе более одного знака
- return false;
- } else {
- // проверка, что значения лежат в пределах от 0 до 7
- if (firstword[0] >= '0' && firstword[0] <= '7') {
- char number = firstword[0];
- // запись элемента в структуру
- map->cells[i*map->cols+j] = number;
- firstword = strtok(NULL, " "); // переход к новому слову
- } else {
- fprintf(stderr, "Invalid\n");
- return false;
- }
- }
- }
- }
- // проверка, на соответствие массива количеству строк
- if (fgets(str, strSize, fp)) {
- fprintf(stderr, "Invalid\n");
- return false;
- }
- bool isClose = true; // переменная для проверки на закрытость лабиринта
- // проверяем только нечетные позиции первой и последней строки на закрытость
- for (int j = 0; j < map->cols; j = j + 2) {
- if (
- !hasBorderTopOrBottom(getCell(map, 0, j)) ||
- !hasBorderTopOrBottom(getCell(map, map->rows - 1, j))
- ) {
- isClose = false; // есть открытая граница
- }
- }
- // проверка на закрытость левой и правой границы массива
- for (int j = 0; j < map->rows; j = j + 1) {
- if (
- !hasBorderLeft(getCell(map, j, 0)) ||
- !hasBorderRight(getCell(map, j, map->cols - 1))
- ) {
- isClose = false; // есть открытая границы
- }
- }
- // если лабиринт закрыт, сообщаем об этом
- if (isClose) {
- fprintf(stderr, "Invalid\n");
- return false;
- }
- // проверка, что рядом стоящие числа не конфликтуют друг с другом
- for (int i = 0; i < map->rows; i++){
- for (int j = 0; j < map->cols; j++){
- if (hasConflictCells(map, i, j)){
- fprintf(stderr, "Invalid\n");
- return false;
- }
- }
- }
- } else {
- fprintf(stderr, "Invalid\n");
- return false;
- }
- }
- }
- return true;
- }
- bool isborder(Map *map, int r, int c, int border) {
- bool levo, pravo, verchNiz;
- levo = (getCell(map, r, c) - '0') & left;
- pravo = (getCell(map, r, c) - '0') & right;
- verchNiz = (getCell(map, r, c) - '0') & upDown;
- switch(border) {
- case sever :
- case jih : return verchNiz;
- case vychod : return pravo;
- case zapad : return levo;
- }
- }
- int start_border(Map *map, int r, int c, int leftright) {
- int smer;
- // right hand
- if (leftright == 0) {
- if ((r + c) % 2 == 0) {
- if (c == 0 && !isborder(map, r, c, zapad)) {
- smer = vychod;
- }
- else if (c == map->cols - 1 && !isborder(map, r, c, vychod)) {
- smer = sever;
- }
- else if (r == 0 && !isborder(map, r, c, sever)) {
- smer = zapad;
- }
- else {
- fprintf(stderr, "Bad vstup\n");
- }
- }
- else {
- if (c == 0 && !isborder(map, r, c, zapad)) {
- smer = jih;
- }
- else if (c == map->cols - 1 && !isborder(map, r, c, vychod)) {
- smer = zapad;
- }
- else if (r == map->rows -1 && !isborder(map, r, c, jih)) {
- smer = vychod;
- }
- else {
- fprintf(stderr, "Bad vstup\n");
- }
- }
- }
- // left hand
- return smer;
- }
- void walkInLabirinthRight(Map *map, int row, int col, int hand, int smer) {
- while ((row < map->rows && col < map->cols) && (row >= 0 && col >= 0)) {
- while (isborder(map, row, col, smer)) {
- smer = (smer + 1) % POCET_SMERU;
- if ((row + col) % 2 == 0 && smer == jih) {
- smer = (smer + 1) % POCET_SMERU;
- }
- else if ((row + col) % 2 != 0 && smer == sever) {
- smer = (smer + 1) % POCET_SMERU;
- }
- }
- printf("%d,%d\n", row + 1, col + 1);
- row = row + d[smer].dr;
- col = col + d[smer].ds;
- if (((row + col) % 2 == 0 && smer == vychod) || ((row + col) % 2 != 0 && smer == zapad)){
- }
- else {
- smer = (smer + 3) % POCET_SMERU;
- }
- }
- }
- void walkInLabirinthleft(Map *map, int row, int col, int hand, int smer) {
- while ((row < map->rows && col < map->cols) && (row >= 0 && col >= 0)) {
- while (isborder(map, row, col, smer)) {
- smer = (smer + 1) % POCET_SMERU;
- if ((row + col) % 2 == 0 && smer == jih) {
- smer = (smer + 1) % POCET_SMERU;
- }
- else if ((row + col) % 2 != 0 && smer == sever) {
- smer = (smer + 1) % POCET_SMERU;
- }
- }
- printf("%d,%d\n", row + 1, col + 1);
- row = row + d[smer].dr;
- col = col + d[smer].ds;
- if (((row + col) % 2 == 0 && smer == vychod) || ((row + col) % 2 != 0 && smer == zapad)){
- }
- else {
- smer = (smer + 3) % POCET_SMERU;
- }
- }
- }
- // int main(int argc, char *argv[]) {
- int main() {
- int argc = 5;
- char *argv3 = "0";
- char *argv1 = "--rpath";
- char *argv2 = "0";
- char *argv4 = "bludiste.txt";
- Map map;
- if (argc == 2 && (strcmp(argv1, "--help") == 0)) {
- printf("Napoveda!\nZadejte vstup, cislo radku a cislo sloupci!\nSpecialni komandy:\n");
- printf("--help - vypisuje napovedu\n");
- printf("--test nazev_souboru.txt - zkontroluje, ze soubor dany druhym argumentem programu obsahuje radnou definici mapy bludiste\n");
- printf("--rpath R C nazev_souboru.txt - hleda pruchod bludistem, zadanym z souboru txt, na vstupu na rádku R a sloupci C. Pruchod hleda pomoci pravidla prave ruky (prava ruka vzdy na zdi)\n");
- printf("--lpath R C nazev_souboru.txt - hleda pruchod bludistem, zadanym z souboru txt, na vstupu na rádku R a sloupci C. Pruchod hleda pomoci pravidla leve ruky (leva ruka vzdy na zdi)\n");
- printf("--shortest R C nazev_souboru.txt - hleda nejkratsi cestu z bludiste, zadanym z souboru txt, pri vstupu na radku R a sloupci C\n");
- return 0;
- }
- else if (argc == 3 && strcmp(argv1, "--test") == 0 && fileTxt(argv2)) {
- if (readAndTestMap(&map, argv2)) {
- printf("Valid\n");
- } else {
- printf("Invalid\n");
- return 0;
- }
- }
- // основной цикл
- else if (argc == 5 && fileTxt(argv4))
- {
- readAndTestMap(&map, argv4);
- int leftright;
- // правило правой руки
- if (isCharNum(argv2) && isCharNum(argv3))
- {
- int startRows = atoi(argv2);
- int startCols = atoi(argv3);
- if ((strcmp(argv1, "--rpath") == 0))// && (startRows > 0 && startRows <= map.rows) && (startCols > 0 && startCols <= map.cols))
- {
- leftright = 0; // правая рука
- int smer = start_border(&map, startRows, startCols, leftright);
- walkInLabirinthRight(&map, startRows, startCols, leftright, smer);
- return 0;
- }
- // правило левой руки
- else if ((strcmp(argv1, "--lpath") == 0) && (startRows > 0 && startRows <= map.rows) && (startCols > 0 && startCols <= map.cols))
- {
- leftright = 1; // левая рука
- return 0;
- }
- /* самый короткий путь
- else if((strcmp(argv1, "--shortest") == 0) && (startRows > 0 && startRows <= map.rows) && (startCols > 0 && startCols <= map.cols))
- {
- //leftright =1;
- return 0;
- }*/
- else
- {
- fprintf(stderr, "Error: chybna komanda\nPro napovedu napiste --help\n");
- return -1;
- }
- }
- else
- {
- fprintf(stderr, "Error: chybna komanda\nPro napovedu napiste --help\n");
- return -1;
- }
- }
- else
- {
- fprintf(stderr, "Error: chybna komanda\nPro napovedu napiste --help\n");
- return -1;
- }
- free(map.cells);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement