Answer the question
In order to leave comments, you need to log in
How to find an error in the code (Game of Life)?
Please help me find the error.
I wrote the cellular automaton "Life" (description can be found on Wikipedia, or in the comments to the code below).
When everything seemed to be done, I found that the algorithm actually does not work correctly.
For example, this can be seen when the input is such a file ("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
According to the logic of the game, the "square" has a stable position and should not change, the "strip" should "rotate", and the figure below should be a glider . But that doesn't happen.
At first I thought the mistake was that I didn’t overload the assignment operator, and the standard one assigned not the values of a two-dimensional array, but a pointer to it (thus, both objects referred to the same array, and gibberish came out). But after I overloaded the assignment operator, the behavior of the program did not change.
/** \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;
}
Answer the question
In order to leave comments, you need to log in
обнаружил, что алгоритм на самом деле работает не правильно.
1. Минимизируйте неправильный пример. Что именно неправильно? Полоска, квадрат?
2. Создайте как можно меньший пример, который работает некорректно, а с ним уже работайте отладчиком.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question