Help me find a mistake in the code.
-
Help me find a mistake. He was texting the Life Cell. Whenever I did, I found that algorithm was actually working wrong. For example, it can be seen when a file like goes in.
10 10 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
The logic of the game is that the quadratic has a stable position and should not change, the "poly" has to turn, and the figure from the bottom should be a glider. But that's not happening. At first, I thought it was a mistake that I didn't overload the assigning operator, and the standard did not assign the two-storey weight, but the index to it (this is how both objects referred to the same mass and came out of the bilibard). But after I've overloaded the attributor, the behavior of the program hasn't changed.
/** \file * \brief Клеточный автомат "Жизнь" * * Программа реализует клеточный автомат "Жизнь"("Life"). * Дано поле, в котормо каждая клетка может быть либо "живой", либо "мертвой". * Пользователь задает начальные условия - первое поколение. Программа генерирует новое поколения (состояние поля) по таким правилам: * Если клетка имеет более 3 или менее 2 соседей, она становится/остается мертвой. * Если клетка имеет строго 3 соседя, она становится/остается живой. * Новые поколения генерируется до тех пор, пока все клетки клетки не умрут либо не образуют стабильное состояние (перестанут меняться). */
#include <iostream>
#include <fstream>
#include <iomanip>
#include <ctime>
#include <random>
#include <windows.h>//#include <chrono>
//#include <thread>using namespace std;
class Fields {
/* Класс описывает состояние поля ("Поколения жизни"). */
private:
int n; // количество рядков поля
int m; // количество столбцов поля
bool **array; //игровое поле. Если клетка поля true - она жива, если false - мертва.
public:
Fields(int a, int b);
Fields(const Fields& );
Fields(ifstream &);
Fields& operator= (const Fields&);
void print();
void run( const Fields last);
};int countOfChanges = 1; //счетчик изменений состояния игрового поля .
int main(){
int countLife = 0; //счетчик состояний игрового поля("Поколений жизни")
int n, m; //длинна и ширина поля
cout << "Hello. This is game of life. " << endl
<< "1. Create the random generated field" << endl
<< "2. Create the field with file" << endl;
int choice;
cin >> choice;Fields current(0, 0); // текущее поколение switch(choice){ case 1:{ cout << "Enter the number of rows and columns of field" << endl; cout << setw(9) << "Rows: "; cin >> n; cout << setw(9) << "Columns: "; cin >> m; Fields randomField = Fields(n, m); current = randomField; break; } case 2:{ ifstream fin("1.txt"); Fields fileField = Fields(fin); current = fileField; break; } } Fields next(current); // следующее поколение cout << "Field: "<< endl; current.print(); while (countOfChanges != 0){ //system("cls"); cout << ++countLife << "st generation: " << endl; countOfChanges = 0; next.run(current); current = next; current.print(); Sleep(1000); //std::this_thread::sleep_for (std::chrono::seconds(1)); } //system("cls"); cout << endl << "This system has been alive for " << countLife - 1 << " steps." << endl; return 0;
}
void Fields:: run( const Fields last ){
/* Метод реализует логику игры. Проходит по всем клеткам поля last, считает количество соседей у каждой клетки и устанавливает новое состояние аналогичной клетки своего поля. Если изменения происходят, счетчик изменений увеличивается. */ int neighbors = 0; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ /* Вот здесь при некоторых [i][j] без всякой видимой причины почему-то меняются array[i][j] и last.array[i][j], хотя это ни в коем случаи происходить не должно. */ neighbors = 0; //количество живых клеток-соседей if ( j - 1 > 0 ){ //тут и далее: проверка, не выходит ли "сосед" за пределы массива, чтобы можно было к нему обратиться if(last.array[i][j-1]){ neighbors++; } } if ( i + 1 < n && j - 1 > 0) { if(last.array[i+1][j-1]){ neighbors++; } } if ( i + 1 < n) { if(last.array[i+1][j] ){ neighbors++; } } if ( i + 1 < n && j + 1 < m) { if(last.array[i+1][j+1]){ neighbors++; } } if ( j + 1 < m) { if(last.array[i][j+1]){ neighbors++; } } if ( i - 1 > 0 && j + 1 < m ){ if(last.array[i-1][j+1]){ neighbors++; } } if ( i - 1 > 0 ){ if(last.array[i-1][j]){ neighbors++; } } if ( i -1 > 0 && j - 1 > 0){ if(last.array[i-1][j-1]){ neighbors++; } } if (neighbors == 3 && last.array[i][j] == false){ //если соседей строго 3, мертвая клетка оживает array[i][j] = true; ::countOfChanges++; continue; } else if (neighbors == 3 && last.array[i][j] == true){ continue; } else if ( (neighbors <= 2 || neighbors > 3 ) && last.array[i][j] == true) { //если соседей меньше или равно 2 или больше 3, живая клетка умирает array[i][j] = false; ::countOfChanges++; continue; } else if ( (neighbors <=2 || neighbors > 3) && last.array[i][j] ==false ){ continue; } else{ continue; } } }
}
Fields:: Fields(int a, int b): n(a), m(b){
array = new bool* [n]; // объявление динамического двумерного массива for(int count = 0; count < n; count ++){ // array[count] = new bool [m]; // } // mt19937 gen(time(0)); // генератор псевдо-случайных чисел из с++11 uniform_int_distribution <> dist(0, 1); // распределение рандомайзера - целые числа 0 и 1 for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ array[i][j] = dist(gen); // рандомное заполнение двумерного массива 0 и 1 } }
}
Fields:: Fields(const Fields& last){
/* Конструктор копирования */n = last.n; m = last.m; array = new bool* [n]; // объявление динамического двумерного массива for(int count = 0; count < n; count ++){ // array[count] = new bool [m]; // } for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ array[i][j] = last.array[i][j]; } }
}
Fields:: Fields(ifstream & fin){
/* Создание поля с файла*/
fin >> n;
fin >> m;array = new bool * [n]; // объявление динамического двумерного массива for(int count = 0; count < n; count ++){ // array[count] = new bool [m]; // } for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ fin >> array[i][j]; } }
}
Fields& Fields:: operator = (const Fields &right){
n = right.n;
m = right.m;delete []array; array = new bool * [n]; // объявление динамического двумерного массива for(int count = 0; count < n; count ++){ // array[count] = new bool [m]; // } for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ array[i][j] = right.array[i][j]; } } return *this;
}
void Fields:: print(){
for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ if(array[i][j]){ cout << "*"; } else{ cout << " "; } } cout << endl; } cout << endl;
}
UPD: The mistake in the method run. The commentators pointed out that the mistake was that the matrix was being rewritten by living, but it was definitely not. Algorithm corroborates past value and records it.
But there's one nuance that I can't explain and, accordingly, fix:
In the method, run in the cycle at a certain point (e.g. when i = 1, j =0 at the initial data I indicated) and the array[i][j] and, most importantly, last.array[i][j] change their value without any apparent reason (they do not enter the bloc that changes the value). When last.array[i][j] is transmitted as a constant, and logically things cannot change. In other cases where the programme enters the unit where the value changes, everything works correctly.This is the code of method itself, indicating where it occurs:
void Fields:: run( const Fields last ){
/* Метод реализует логику игры. Проходит по всем клеткам поля last, считает количество соседей у каждой клетки и устанавливает новое состояние аналогичной клетки своего поля. Если изменения происходят, счетчик изменений увеличивается. */ int neighbors = 0; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ /* Вот здесь при некоторых [i][j] без всякой видимой причины почему-то меняются array[i][j] и last.array[i][j], хотя это ни в коем случаи происходить не должно. */ neighbors = 0; //количество живых клеток-соседей if ( j - 1 > 0 ){ //тут и далее: проверка, не выходит ли "сосед" за пределы массива, чтобы можно было к нему обратиться if(last.array[i][j-1]){ neighbors++; } } if ( i + 1 < n && j - 1 > 0) { if(last.array[i+1][j-1]){ neighbors++; } } if ( i + 1 < n) { if(last.array[i+1][j] ){ neighbors++; } } if ( i + 1 < n && j + 1 < m) { if(last.array[i+1][j+1]){ neighbors++; } } if ( j + 1 < m) { if(last.array[i][j+1]){ neighbors++; } } if ( i - 1 > 0 && j + 1 < m ){ if(last.array[i-1][j+1]){ neighbors++; } } if ( i - 1 > 0 ){ if(last.array[i-1][j]){ neighbors++; } } if ( i -1 > 0 && j - 1 > 0){ if(last.array[i-1][j-1]){ neighbors++; } } if (neighbors == 3 && last.array[i][j] == false){ //если соседей строго 3, мертвая клетка оживает array[i][j] = true; ::countOfChanges++; continue; } else if (neighbors == 3 && last.array[i][j] == true){ continue; } else if ( (neighbors <= 2 || neighbors > 3 ) && last.array[i][j] == true) { //если соседей меньше или равно 2 или больше 3, живая клетка умирает array[i][j] = false; ::countOfChanges++; continue; } else if ( (neighbors <=2 || neighbors > 3) && last.array[i][j] ==false ){ continue; } else{ continue; } } }
}
UPD2:I found a mistake. Type code
> for(int i = 0; i < n; i++){
> for(int j = 0; j < m; j++){} }
In any place of the programme, at some [i][j][j] vacate itself the array[i][j] and last.array[i][j]
For those input data, this occurs at points [1][0] [1][7] [2][0] [2][7]
What is this black magic?
-
You have one mass. You write a new cell condition in it, so these changes directly affect other cells.
You can have another mass. We're coping with an old body, and we're already using a new set to determine the stakes of living cells, and the new condition of the cells to the old body. So cell changes will only be taken into account in the next step of life.