#include "HEAD.h"

#include <cstdlib>

#include <stack>







int main()

{

      column stroki [str_count];

      column stolbzi [stb_count];

      ifstream in("text4.txt");

      int cnt = 0;

      while(cnt < str_count)

      {

         stroki [cnt++] = GetInfoColumn(in);

      }

      cnt = 0;

      while(cnt < stb_count)

      {

         stolbzi[cnt++] = GetInfoColumn(in);

      }

      //Прием данных завершен

      char testm [str_count][stb_count];

      for(int x = 0; x < str_count; x++)//Начальная инициализация массива (. - это неопределеная клетка)

      {

        for(int y = 0; y < stb_count; y++)

        {

            testm [x][y] = '.';

        }

      }

      SetRangeStr(stroki, str_count, testm);//Начальная расстановка диапазонов

      SetRangeStb(stolbzi, stb_count, testm);

      ///

      //Storager storage;

      std::stack <pack> storage;//Стек для пакетов состояний (стек функций, черт бы его побрал, не смог справиться с их хранением)

      pack data;//Он тут, вроде как, не нужен

      char testm_copy [str_count][stb_count];//Это копия поля для ПРОВЕРКИ ШАГА.

      kletka_pack temp;

      bool check_shag_checker = false;//Флаг "сделан ли шаг?"

      column stroki_copy [str_count];//Две копии массивов колонок

      column stolbzi_copy [stb_count];

      int counter = 0;

      /*Итак, суть цикла.

      Сначала он решает кроссворд логически.

      Если, в определенный момент решения предоставленые средства (алг. функции)

      не могут изменить состояние поля - цикл переходит к rand-способу решения:

      выдается неопределенная клетка, в ней ставится x (символ закр. клетки)

      и цикл идет дальше.

      Если, в определенный момент решения (а он рано или поздно наступит в ЛЮБОМ случае)

      функция CheckRight выдает false ИЛИ ловится исключение ИЛИ неопределенные клетки кончаются,

      а функция CheckAll выдала false - (короче выясняется, что цикл пошел по неправильно ветке состояний)

      происходит ОТКАТ к предыдущему состоянию с установкой выданой ему функцией GetKletka клеткой в '0'.

      Теперь проблема: программа БЕСКОНЕЧНО обрабатывает файлы text6 и text8.

      (И после того, как я написал все эти комментарии, она начала ТОЖЕ БЕСКОНЕЧНО обрабатывать остальные файлы

       (вот это ПРИКОЛ, да?(001010100xAD2Fff90?!77!char e'6')!!))

      Что, что, ЧТО, черт бы его побрал, не так?! Неужели комментарии теперь начали влиять на исх. код программы?!

      Все.

      */



      while(1)

      {

      try

      {

      while(1)

      {

      for(int x = 0; x < str_count; x++)

      {

          for(int y = 0; y < stb_count; y++)

          {

              testm_copy[x][y] = testm [x][y];

          }

      }

      for(int x = 0; x < str_count; x++)

          stroki_copy[x] = stroki[x];

      for(int x = 0; x < stb_count; x++)

          stolbzi_copy[x] = stolbzi[x];



      if(!CheckRight(stroki, stolbzi, testm))

      {

      const pack to_restore = storage.top();

      storage.pop();

      for(int x = 0; x < str_count; x++)

      {

          for(int y = 0; y < stb_count; y++)

          {

              testm[x][y] = to_restore.testm_copy_rand [x][y];

          }

      }

      for(int x = 0; x < str_count; x++)

        stroki[x] = to_restore.str[x];

      for(int x = 0; x < stb_count; x++)

        stolbzi[x] = to_restore.stb[x];

      testm [to_restore.wcords.stroka] [to_restore.wcords.stolbez] = '0';

      cout << "The data has been restored: " << to_restore.wcords.stroka << " "

      << to_restore.wcords.stolbez << endl;

      cout << "NOW: " << --counter << endl;

      }//if



      monolithstr(stroki, str_count, testm);

      monolithstb(stolbzi, stb_count, testm);

      CycleStr(stroki, str_count, testm);

      CycleStb(stolbzi, stb_count, testm);



      if(CheckAll(stroki, stolbzi, testm))

      {

      for(int x = 0; x < str_count; x++)

      {

        for(int y = 0; y < stb_count; y++)

        {

           if(testm [x] [y] == '0')

           testm [x][y] = ' ';

           if(testm [x][y] == 'x')

            testm [x][y] = 2;

        }

      }

      cout << endl << endl;

      cout << ' ' << ' ';

      for(int x = 0; x < 5; x++)

        cout << '|' << ' ';

      cout << endl;

      for(int x = 0; x < str_count; x++)

      {

          cout << '-' << '-';

        for(int y = 0; y < stb_count; y++)

        {

            cout << testm [x][y] << " ";

        }

        cout << endl;

      }

      for(int x = 0; x < str_count; x++)

      {

        for(int y = 0; y < stb_count; y++)

        {

           if(testm [x] [y] == ' ')

           testm [x][y] = '0';

           if(testm [x][y] == 2)

            testm [x][y] = 'x';

        }

      }

      exit(EXIT_SUCCESS);

      }



      if(!CheckRight(stroki, stolbzi, testm))

      {

      const pack to_restore = storage.top();

      storage.pop();

      for(int x = 0; x < str_count; x++)

      {

          for(int y = 0; y < stb_count; y++)

          {

              testm[x][y] = to_restore.testm_copy_rand [x][y];

          }

      }

      for(int x = 0; x < str_count; x++)

        stroki[x] = to_restore.str[x];

      for(int x = 0; x < stb_count; x++)

        stolbzi[x] = to_restore.stb[x];

      testm [to_restore.wcords.stroka] [to_restore.wcords.stolbez] = '0';

      cout << "The data has been restored: " << to_restore.wcords.stroka << " "

      << to_restore.wcords.stolbez << endl;

      cout << "NOW: " << --counter << endl;

      }//if



      if(!CheckShag(testm, testm_copy, stroki, stroki_copy, stolbzi, stolbzi_copy))

      {

        check_shag_checker = true;

        break;

      }

      }

      }



      catch(column::bad_access & wrong)

      {

      const pack to_restore = storage.top();

      storage.pop();

      for(int x = 0; x < str_count; x++)

      {

          for(int y = 0; y < stb_count; y++)

          {

              testm[x][y] = to_restore.testm_copy_rand [x][y];

          }

      }

      for(int x = 0; x < str_count; x++)

        stroki[x] = to_restore.str[x];

      for(int x = 0; x < stb_count; x++)

        stolbzi[x] = to_restore.stb[x];

      testm [to_restore.wcords.stroka] [to_restore.wcords.stolbez] = '0';

      cout << "NOW: " << --counter << endl;

      }//catch



      while(check_shag_checker)

      {

      temp = GetKletka(testm);

      //all

      if(temp.stolbez == -1 && temp.stroka == -1)

      {

      if(CheckAll(stroki, stolbzi, testm))

      {

      for(int x = 0; x < str_count; x++)

      {

        for(int y = 0; y < stb_count; y++)

        {

           if(testm [x] [y] == '0')

           testm [x][y] = ' ';

           if(testm [x][y] == 'x')

            testm [x][y] = 2;

        }

      }

      cout << endl << endl;

      cout << ' ' << ' ';

      for(int x = 0; x < 5; x++)

        cout << '|' << ' ';

      cout << endl;

      for(int x = 0; x < str_count; x++)

      {

          cout << '-' << '-';

        for(int y = 0; y < stb_count; y++)

        {

            cout << testm [x][y] << " ";

        }

        cout << endl;

      }

       for(int x = 0; x < str_count; x++)

      {

        for(int y = 0; y < stb_count; y++)

        {

           if(testm [x] [y] == ' ')

           testm [x][y] = '0';

           if(testm [x][y] == 2)

            testm [x][y] = 'x';

        }

      }

      exit(EXIT_SUCCESS);

      }

      const pack to_restore = storage.top();

      storage.pop();

      for(int x = 0; x < str_count; x++)

      {

          for(int y = 0; y < stb_count; y++)

          {

              testm[x][y] = to_restore.testm_copy_rand [x][y];

          }

      }

      for(int x = 0; x < str_count; x++)

        stroki[x] = to_restore.str[x];

      for(int x = 0; x < stb_count; x++)

        stolbzi[x] = to_restore.stb[x];

      testm [to_restore.wcords.stroka] [to_restore.wcords.stolbez] = '0';

      cout << "Kletok net " << check_shag_checker << endl;

      cout << "NOW: " << --counter << endl;

      check_shag_checker = false;

      break;

      }



      pack to_save;

      for(int x = 0; x < str_count; x++)

        to_save.str[x] = stroki[x];

      for(int x = 0; x < stb_count; x++)

        to_save.stb[x] = stolbzi[x];

      for(int x = 0; x < str_count; x++)

      {

          for(int y = 0; y < stb_count; y++)

          {

              to_save.testm_copy_rand[x][y] = testm[x][y];

          }

      }

      to_save.wcords = temp;

      storage.push(to_save);

      testm [temp.stroka] [temp.stolbez] = 'x';

      cout << temp.stroka << " " << temp.stolbez << endl;

      cout << "NOW: " << ++counter << endl;

      check_shag_checker = false;

      break;

      }



      }//while

      ///



     //for(int x = 0; x < str_count; x++)

       // stroki[x].show();

      //for(int x = 0; x < stb_count; x++)

       // stolbzi[x].show();

/*

      for(int x = 0; x < str_count; x++)

      {

        for(int y = 0; y < stb_count; y++)

        {

           if(testm [x] [y] == '0')

           testm [x][y] = ' ';

           if(testm [x][y] == 'x')

            testm [x][y] = 2;

        }

      }

      cout << endl << endl;

      cout << ' ' << ' ';

      for(int x = 0; x < 20; 