Форум программистов, компьютерный форум, киберфорум
Наши страницы

Игра "Жизнь" ( найти ошибку) - C++

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ Перемещение фигуры http://www.cyberforum.ru/cpp/thread1618220.html
Реализовать отображение на экране геометрической фигуры с возможностью перемещать ее с помощью клавиш(стрелки) и изменение цвета фигуры "+".
C++ Информация о железе Здравствуйте форумчане Очень нужно узнать информацию о: HDD(разделы, размер каждого раздела, сколько занято места) CPU(температура, загрузку каждого ядра) процессы(как в диспетчера задач) службы... http://www.cyberforum.ru/cpp/thread1618027.html
C++ Вычисление количества знаков после запятой
Написал функцию определяющую, что у числа менее 4 знаков после запятой. Помогите оптимизировать. bool rac(double a) { int c(0); a -= int(a); while (a - int(a) && c < 4) { ...
Создать и подключить библиотеку в Dev-C++ C++
Помогите пожалуйста. Необходимо создать библиотеку и exe файл. При запуске exe файла ввести 2 значения (a=число1, b=число2). Эти числа должны передаться библиотеке (dll) там сложиться и вернуться...
C++ Ошибка сегментирования при компиляции http://www.cyberforum.ru/cpp/thread1617311.html
Когда компилирую через g++ компилируется, при запуске выдает ошибку сегментирования, а при компиляции через NetBeans IDE выдает две ошибки, на скринах показал. Задача: Разработать две программы –...
C++ Как достать кириллические символы из char* Добрый день. Использую библиотеку, которая возвращает строку в char*. Если создавать std::wstring из этой строки, то кириллица отображается как знаки вопросов. Помогите достать из буфера char*... подробнее

Показать сообщение отдельно
NikBond
2 / 2 / 2
Регистрация: 21.07.2015
Сообщений: 36
26.12.2015, 10:41  [ТС]
Цитата Сообщение от Good-Morning Посмотреть сообщение
На сколько я понимаю, ошибка в том, что метод Fields::run переписывает матрицу "по живому", т.е. после изменения одного элемента следующие элементы изменяются исходя не из старой матрицы, а из "полупеределанной".
По логике программы он ее как раз переписывает корректно, считывая старую матрицу, и записывая в новую. Но, есть один нюанс, который я ничем не могу объяснить и, соответственно, пофиксить:
В методе run в определенный момент (например когда i = 1, j =0 при тех начальных данных, что я указал), и array[i][j], и, что самое главное, last.array[i][j] изменяют свое значение без какой-либо видимой причины (они вообще не попадают в тот блок который меняет значение). При чем last.array[i][j] вообще как константа передается, и по логике вещей, меняться никак не может.

Вот сам метод, чуть-чуть исправленный. Два лишних иф-елса расписал, чтобы легче было дебажить. :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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;
            }
        }
    }
}
Весь код целиком, тоже по мелочи доработанный:
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
/** \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;
}


Очень прошу помочь разобраться, что за шаманство.

Добавлено через 4 часа 54 минуты
Я локализовал проблему.
Код вида
C++
1
2
3
4
5
6
    
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
    
        }
    }
В любом месте программы при некоторых i и j сам меняет значение и текущего, и предыдущего.
Это просто взрыв мозга. Как?
0
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.