Помогите найти ошибку.
Писал клеточный автомат "Жизнь"(описание можно посмотреть на википедии, либо в комментариях к коду ниже).
Когда все вроде бы сделал, обнаружил, что алгоритм на самом деле работает не правильно.
Например, это видно, когда на вход идет такой файл("1.txt"):
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
По логике игры, "квадратик" имеет стабильное положение и не должен меняться, "полоска" должна "вращаться", а фигура снизу представлять из себя глайдер. Но этого не происходит.
Сначала я думал, ошибка в том, что я не перегрузил оператор присваивания, а стандартный присваивал не значения двумерного массива, а указатель на него (таким образом, оба объекта ссылались на один и тот же массив, и выходила билиберда). Но после того как я оператор присваивания таки перегрузил, поведение программы не изменилось.
/** \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= (Fields&r);
void print();
void run( 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( Fields last ){
/* Метод реализует логику игры. Проходит по всем клеткам поля last,
считает количество соседей у каждой клетки и устанавливает новое состояние аналогичной клетки своего поля.
Если изменения происходят, счетчик изменений увеличивается.
*/
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
int 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 > 0) {
if(last.array[i+1][j-1]){
neighbors++;
}
}
if ( j - 1 > 0) {
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++;
}
if ( (neighbors <= 2 || neighbors > 3 ) && last.array[i][j] == true) {
//если соседей меньше или равно 2 или больше 3, живая клетка умирает
array[i][j] = false;
::countOfChanges++;
}
}
}
}
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 = (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;
}
В общем, помогите найти ошибку.