SHARE
TWEET

Untitled

a guest May 19th, 2019 60 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. #############################
  3. Код написан студентом группы КИУКИ-18-6 Зайцевым Дмитрием
  4. #############################
  5. */
  6.  
  7. #include <iostream> //Библиотека потока ввода/вывода
  8. #include <conio.h> //Из библиотеки взята только функция getch();
  9. #include <Windows.h> //Из библиотеки используется только задержка Sleep();
  10. #include <ctime> //Используется для рандомизации в зависимости от времени
  11. #include <string>
  12. using namespace std;
  13.  
  14. int Neighbors(char *mas[],int i,int j,int sizeY,int sizeX) { //Функция для определения количества соседей
  15.     int result = 0; //Результат, который функция вернёт при выполнении
  16.     for (int k = -1; k < 2; k++)
  17.     {
  18.         for (int l = -1; l < 2; l++)
  19.         {
  20.             int neighVarX = 0; int neighVarY = 0; //Координаты по Ох и по Оу окрестности точки, которая проверяется
  21.  
  22.             /* Проверка на границы поля */
  23.             if ((i == 0 && k == -1) || (i == sizeY - 1 && k == 1)) //Если проверяется точка выше верхней границы ИЛИ ниже нижней, то берется первая координата противоположной стороны
  24.             {
  25.                 neighVarY += (-k * sizeY);
  26.             }
  27.             if ((j == 0 && l == -1) || (j == sizeX - 1 && l == 1)) //Если проверяется точка левее левой границы ИЛИ правее правой, то берется первая координата противоположной стороны
  28.             {
  29.                 neighVarX += (-l * sizeX);
  30.             }
  31.             if (mas[i + k + neighVarY][j + l + neighVarX] == '@' && !(k == 0 && l == 0)) //Проверка на наличие жизни в клетке
  32.             {
  33.                 result += 1; //Результат увеличивается на +1 если клетка-сосед живая
  34.             }
  35.         }
  36.     }
  37.     return result;
  38. }
  39.  
  40. int gens, step = 0;
  41. void Nextgen(char **mas,int sizeY, int sizeX) { //Функция для определения следующего поколения
  42.     char**masCopy = new char*[sizeY];  /* Создание временного массива */
  43.     for (int i = 0; i < sizeY; i++)
  44.         masCopy[i] = new char[sizeX];
  45.  
  46.     for (int i = 0; i < sizeY; i++) /*перебор всех клеток поля*/
  47.     {
  48.         for (int j = 0; j < sizeX; j++)
  49.         {
  50.             /* Проверка правил игры Жизнь */
  51.             if (Neighbors(mas, i, j, sizeY, sizeX) == 2) { masCopy[i][j] = mas[i][j]; }  //Если у клетки 2 соседа, то состояние клетки не меняется
  52.             else if (Neighbors(mas, i, j, sizeY, sizeX) == 3) { masCopy[i][j] = '@'; } //Иначе если у клетки 3 соседа, то там зарождается жизнь
  53.             else { masCopy[i][j] = ' '; } //Иначе клетка погибает
  54.         }
  55.     }
  56.  
  57.     for (int i = 0; i < sizeY; i++) /* Перепись временного массива в основной */
  58.     {
  59.         for (int j = 0; j < sizeX; j++)
  60.         {
  61.             mas[i][j] = masCopy[i][j];
  62.         }
  63.     }
  64.     step++; //Счётчик генерации +1
  65. }
  66.  
  67. void fillSpace(char **mas, int sizeY, int sizeX) { /* Функция очистки поля */
  68.     for (int i = 0; i < sizeY; i++) //Перебор элементов поля
  69.     {
  70.         for (int j = 0; j < sizeX; j++)
  71.         {
  72.             mas[i][j] = ' '; //Присвоение элементу ' '
  73.         }
  74.     }
  75. }
  76.  
  77. void printArray(char *mas[], int sizeY, int sizeX) { /* Функция вывода поля на экран */
  78.     for (int i = 0; i < sizeY; i++) //Перебор элементов поля
  79.     {
  80.         for (int j = 0; j < sizeX; j++)
  81.         {
  82.             cout << mas[i][j]; //Вывод элемента
  83.         }
  84.         cout << "\n";
  85.     }
  86.     cout << "Generation: " << step << "\n"; //Счётчик генераций
  87. }
  88.  
  89. void fillManually(char **mas,int sizeY,int sizeX) { /* Функция ручного ввода клеток в поле */
  90.     fillSpace(mas, sizeY, sizeX); //Предварительная очистка
  91.     int tempX=0, tempY=0,key=0; //Координаты текущего положения метки; Ключ, который хранит значение нажатой клавиши
  92.     while (1) {
  93.         system("cls"); //Очистка экрана перед изменением выводимого поля
  94.         if (tempX == -1) { tempX = sizeX - 1; } //Если положение метки стремится за левую границу, то метка перемещается на правую
  95.         if (tempX == sizeX) { tempX = 0; } //Если положение метки стремится за правую границу, то метка перемещается на левую
  96.         if (tempY == -1) { tempY = sizeY - 1; } //Если положение метки стремится за верхнюю границу, то метка перемещается на нижнюю
  97.         if (tempY == sizeY) { tempY = 0; } //Если положение метки стремится за нижнюю границу, то метка перемещается на верхнюю
  98.         if (mas[tempY][tempX]!='@') { //Если метка на неживой клетке, то метка принимает вид "х"
  99.             mas[tempY][tempX] = 'x';
  100.  
  101.         }
  102.         else if(mas[tempY][tempX]=='@'){ mas[tempY][tempX] = 'X'; } //Иначе если метка уже на живой клетке, то она принимает значение "Х"
  103.         printArray(mas, sizeY, sizeX); //Вывод поля вместе с меткой
  104.         cout << "\'W\'-Up\t\'A\'-Left\t\'S\'-Down\t\'D\'-Right\t\'Space\'-Set\/Delete mark\t   \'Enter\'-Exit"; //Вывод клавиш, необходимых для управления меткой
  105.         key = _getch(); //Получение индивидуального кода нажатой клавиши
  106.         char prevChar = mas[tempY][tempX]; //Сохранение текущего положения метки
  107.         if (prevChar == 'X')mas[tempY][tempX] = '@'; //Если метка имеет вид "Х", то там будет жизнь
  108.         switch (key) {
  109.         case 119: if (prevChar!='@'&&prevChar!='X') mas[tempY][tempX] = ' '; tempY -= 1; break; //При нажатии клавиши "W" метка перемещается на 1 вверх. Если она была в положении "х", то она очищается
  110.         case  97: if (prevChar != '@'&&prevChar != 'X') mas[tempY][tempX] = ' '; tempX -= 1; break; //При нажатии клавиши "A" метка перемещается на 1 влево. Если она была в положении "х", то она очищается
  111.         case 115: if (prevChar != '@'&&prevChar != 'X') mas[tempY][tempX] = ' '; tempY += 1; break; //При нажатии клавиши "S" метка перемещается на 1 вниз. Если она была в положении "х", то она очищается
  112.         case 100: if (prevChar != '@'&&prevChar != 'X') mas[tempY][tempX] = ' '; tempX += 1; break; //При нажатии клавиши "D" метка перемещается на 1 вправо. Если она была в положении "х", то она очищается
  113.         case  32:  if (prevChar != 'X')mas[tempY][tempX] = '@'; else { mas[tempY][tempX] = 'x'; } break; //При нажатии клавиши "Space": если метка была в состоянии "х", то там зарождется жизнь, иначе метка принимает значение "x"
  114.         case  13: if (prevChar != '@'&&prevChar != 'X') mas[tempY][tempX] = ' '; return; //При нажатии клавиши "Enter" производится выход в меню
  115.         }
  116.     }
  117. }
  118.  
  119. void fillRandom(char **mas, int sizeY, int sizeX) { /* Функция рандомного заполнения поля */
  120.     fillSpace(mas, sizeY, sizeX); //Предварительная очистка поля
  121.     int density; //Плотность заполнения поля
  122.     string temp_density; //Временная переменная, в которую мы записываем значение плотности в строковом виде
  123.     bool error=0; //Переменная-флаг, которая хранит наличие ошибки
  124.     while (1) { //Цикл для исключения ошибок при вводе плотности
  125.         cout << "\nInput density (1-10): "; cin >> temp_density; //Выбор плотности заполнения от 1 до 10
  126.  
  127.         for (int i = 0; i < size(temp_density); i++) { if (!(temp_density[i] >= '0'&&temp_density[i] <= '9')) error = 1; } //Проверка введённой плотности на цифры
  128.         if (error) { error = 0; system("cls"); cout << "Only numbers!\n"; continue; } //Если флаг ошибки == 1, то он обнуляется, и после очистки поля выводится сообщение об ошибке, предлагается повторный ввод
  129.         density = stoi(temp_density); //Если всё хорошо, значение плотности переводится в целочисленный тип
  130.  
  131.         if (density < 1 || density>10) { cout << "Input again!\n"; continue; } //Проверка на границы плотности, просьба ввести ещё раз при выходе за границы
  132.         else { break; } //Выход из цикла при правильном вводе
  133.     }
  134.     for (int i = 0; i < sizeY; i++) //Перебор всех клеток поля
  135.     {
  136.         for (int j = 0; j < sizeX; j++)
  137.         {
  138.             int temp = rand() % (11-density); //Определение состояния клетки
  139.             if (temp != 1) { mas[i][j] = ' '; } //Присвоение элементу пробела с шансом ((11-density)/10)
  140.             else { mas[i][j] = '@'; }
  141.         }
  142.     }
  143. }
  144.  
  145. void fillArray(char **mas,int sizeY,int sizeX) { /* Функция заполнения поля (общая) */
  146.  
  147.     do {
  148.         cout << "How do you want to fill array?\n1-Manually\n2-Random\n0-Exit\nYour choose: "; //Выбор режима заполнения ручной/автоматический(рандомный) либо выход
  149.         int t_choose; t_choose = _getch();
  150.         if (t_choose != 48 && t_choose != 49 && t_choose != 50) { system("cls"); cout << "Make another choose!\n"; continue; } //Если выбор не совпадает ни с одним из вариантов выбора, то новая иттерация
  151.         else {
  152.             switch (t_choose) {
  153.             case 48: exit(0); //Выход из программы
  154.             case 49: fillManually(mas, sizeY, sizeX); break; //Вызов функции ручного заполнения
  155.             case 50: fillRandom(mas, sizeY, sizeX); break; //Вызов функции рандомного заполнения
  156.             }
  157.             system("cls"); return; //Очистка консоли после заполнения поля
  158.         }
  159.     } while (1);
  160. }
  161.  
  162. void eatline() { while (cin.get() != '\n'); } //Функция, которая принимает на себя поток ввода, очищает его
  163.  
  164. bool compare_arr(char **mas1, char**mas2, int sizeY, int sizeX) { //Функция сравнения массивов
  165.     for(int i=0;i<sizeY;i++) //Перебор элементов массива
  166.         for(int j=0;j<sizeX;j++)
  167.             if (mas1[i][j] != mas2[i][j]) { //Если есть несовпадение, выход из функции с кодом 0
  168.                 return 0;
  169.             }
  170.     return 1;
  171. }
  172.  
  173. int main()
  174. {
  175.     bool error; //Переменная флаг, хранит информацию об ошибке
  176.     int sizeY,sizeX;
  177.     bool exitCode = 0;
  178.     int counter = 0;
  179.     do { //Определение высоты поля
  180.         string temp_sizeY;
  181.         error = 0; //Обнуление флага-ошибки
  182.         cout << "Input height (min 10 \/ max 25): "; cin >> temp_sizeY; eatline(); //Запись высоты в переменную строкового типа, очистка потока ввода после первого пробела
  183.    
  184.         for (int i = 0; i < size(temp_sizeY); i++) { if (!(temp_sizeY[i] >= '0'&&temp_sizeY[i] <= '9')) error = 1; } //Проверка на наличие не цифр в о введённой строке
  185.         if (error) { error = 0; system("cls"); cout << "Only numbers!\n"; continue; } //Если есть ошибка, просьба ввести повторно
  186.        
  187.         if (size(temp_sizeY) > 4) { system("cls"); cout << "Too long, change height\n"; continue; } //Если введённая цифра очень длинная, просьба ввести повторно
  188.         else { sizeY = stoi(temp_sizeY); } //Если всё хорошо, запись высоты в переменную целочисленного типа
  189.  
  190.         if (sizeY < 10 || sizeY>25) { cout << "Change height\n"; } //Если введённая цифра не попадает в диапазон, просьба ввести повторно
  191.         else break; //Если всё хорошо, выход из цикла ввода высоты
  192.     } while (1);
  193.  
  194.     do { //Определение высоты поля
  195.         string temp_sizeX;
  196.         error = 0;//Обнуление флага-ошибки
  197.         cout << "Input width (min 10 \/ max 40): "; cin >> temp_sizeX; eatline();//Запись ширины в переменную строкового типа, очистка потока ввода после первого пробела
  198.  
  199.         for (int i = 0; i < size(temp_sizeX); i++) { if (!(temp_sizeX[i] >= '0'&&temp_sizeX[i] <= '9')) error = 1; } //Проверка на наличие не цифр в о введённой строке
  200.         if (error) { error = 0; system("cls"); cout << "Only numbers!\n"; continue; } //Если есть ошибка, просьба ввести повторно
  201.  
  202.         if (size(temp_sizeX) > 4) { system("cls"); cout << "Too long, change width\n"; continue; } //Если введённая цифра очень длинная, просьба ввести повторно
  203.         else { sizeX = stoi(temp_sizeX); }  //Если всё хорошо, запись высоты в переменную целочисленного типа
  204.  
  205.         if (sizeX < 10 || sizeX>40) { cout << "Change width\n"; } //Если введённая цифра не попадает в диапазон, просьба ввести повторно
  206.         else break; //Если всё хорошо, выход из цикла ввода ширины
  207.     } while (1);
  208.  
  209.     char** mas = new char*[sizeY]; //Создание поля
  210.     for (int i = 0; i < sizeY; i++)
  211.         mas[i] = new char[sizeX];
  212.  
  213.     char **temp_mas = new char*[sizeY]; //Создание поля, которое хранит состояние основного поля на 2 поколения назад
  214.     for (int i = 0; i < sizeY; i++)
  215.         temp_mas[i] = new char[sizeX] {' '};
  216.  
  217.     fillSpace(mas,sizeY,sizeX); //Заполнение поля пробелами
  218.     fillArray(mas, sizeY, sizeX); //Вызов функции для заполнения поля
  219.    
  220.  
  221.     do
  222.     {
  223.         int choose; //Переменная выбора
  224.         cout << "0-Exit\n1-Print some gens\n2-Fill again\nChoose your destiny: "; //Вывод меню
  225.         choose=_getch();
  226.         switch (choose) {
  227.         case 48:return 0; //Выход из программы
  228.         case 49:int delay; //Переменная задержки между выводами поколений
  229.  
  230.             do {
  231.                 error = 0; //Обнуления флага-ошибки
  232.                 string temp_delay;
  233.                 cout << "\nWhat's delay? (ms) (0-1000): "; eatline(); cin >> temp_delay;  //Ввод задержки между выводами поколений
  234.  
  235.                 for (int i = 0; i < size(temp_delay); i++) { if (!(temp_delay[i] >= '0'&&temp_delay[i] <= '9')) error = 1; } //Проверка на наличие букв
  236.                 if (error) { error = 0; system("cls"); cout << "Only numbers!\n"; continue; } //Если есть не числа, просьба ввести повторно
  237.  
  238.                 if (size(temp_delay) > 4) { system("cls"); cout << "Too long, please change\n"; continue; } //Если размер числа очень большой, просьба ввести повторно
  239.                 else { delay = stoi(temp_delay); } //Запись задержки в переменную целочисленного типа
  240.  
  241.                 if (delay < 0 || delay>1000) { cout << "From 0 to 1000 ms!\n"; } //Проверка на попадание в рамки
  242.                 else break; //Если всё хорошо, выход из цикла ввода задержки
  243.             } while (1);
  244.  
  245.             system("cls");
  246.            
  247.         while(!_kbhit()&&exitCode!=1){  //Цикл для вывода поколений, пока не нажата клавиша, либо не зациклена генерация поколений
  248.        
  249.             if (counter == 0){for (int i = 0; i < sizeY; i++) //Если это первое поколение, запись его во временный массив
  250.                 for (int j = 0; j < sizeX; j++)
  251.                     temp_mas[i][j] = mas[i][j]; }
  252.  
  253.                 Nextgen(mas, sizeY, sizeX); //генерация следующего поколения
  254.                 if (counter % 2 == 0&&counter!=0) { //Проверка на несоседнее поколение, и что оно не первое
  255.                     if (compare_arr(mas, temp_mas, sizeY, sizeX)) {
  256.                         exitCode = 1; //Если предпоследнее поколение совпадает с текущим, флаг для выхода устанавливается в 1
  257.                     }
  258.                     else {
  259.                         for (int i = 0; i < sizeY; i++) //Если не совпадает, запись его во временный массив
  260.                             for (int j = 0; j < sizeX; j++)
  261.                                 temp_mas[i][j] = mas[i][j];
  262.                     }
  263.                 }
  264.  
  265.                 printArray(mas, sizeY, sizeX); //Вывод только что сгенерированного поколения
  266.                 cout << "Press \'Any key\' to exit\n"; //Вывод комбинации для закрытия программы во время вывода
  267.                 Sleep(delay); //Задержка перед следующим выводом
  268.                 system("cls");
  269.                 counter++; //Увеличение счётчика поколений на +1
  270.             }
  271.         if (exitCode == 1) { cout << "All cells died or looped\n"; exitCode = 0; counter = 0; }
  272.             cout << "Press any button\n"; _getch(); system("cls"); break; //Ожидание нажатия клавиши для продолжения после вывода последнего поколения
  273.         case 50: system("cls"); fillArray(mas, sizeY, sizeX); step = 0; break; //Вызов функции для заполнения поля
  274.         default: system("cls"); cout << "Change your choose\n"; continue; //Просьба изменить выбор, если выбран несуществующий пункт меню
  275.         }
  276.            
  277.     } while (1);
  278. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top