-
Notifications
You must be signed in to change notification settings - Fork 0
/
life_serial.cpp
204 lines (186 loc) · 5.06 KB
/
life_serial.cpp
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
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <sstream>
//#include "mpi.h"
using std::cout;
using std::cin;
using std::endl;
//using namespace MPI;
// Prototype definitions
inline int getIndex(int, int, int);
void initGrid(int, int, bool[]);
int getNeighbors(int, int, int, bool[]);
void step(int, bool[], bool[]);
void doHallo(int, bool[]);
void copyGrid(int, bool[], bool[]);
void makeImage(int, int, bool[]);
// end of prototype definitions
/**
* Determines the index in a one-dimensional interpretation
* of the (gridSize + 2)x(gridSize + 2) matrix
*/
inline int getIndex(int gridSize, int y, int x)
{
return x + (gridSize + 2) * y;
}
/**
* fills every cell of the grid with a predefined probability
* fills the hallo too
*/
void initGrid(int gridSize, int probability, bool grid[])
{
//fill with probability
int y, x;
for(y = 1; y <= gridSize; y++)
{
for(x = 1; x <= gridSize; x++)
{
int random = (100.0 * rand()) / RAND_MAX;
if(random < probability)
grid[getIndex(gridSize, y, x)] = true;
else
grid[getIndex(gridSize, y, x)] = false;
}
}
doHallo(gridSize, grid);
}
/**
* Returns the neighbors count for this cell. x,y are between 1 and gridSize
*/
int getNeighbors(int gridSize, int y, int x, bool grid[])
{
int count = 0;
if(grid[getIndex(gridSize, y - 1, x - 1)])
count++;
if(grid[getIndex(gridSize, y - 1, x)])
count++;
if(grid[getIndex(gridSize, y - 1, x + 1)])
count++;
if(grid[getIndex(gridSize, y, x - 1)])
count++;
if(grid[getIndex(gridSize, y, x + 1)])
count++;
if(grid[getIndex(gridSize, y + 1, x - 1)])
count++;
if(grid[getIndex(gridSize, y + 1, x)])
count++;
if(grid[getIndex(gridSize, y + 1, x + 1)])
count++;
return count;
}
/**
* Applies the rules to the grid of cells:
* Every dead cell with exactly 3 neighbors will come to live
* Every living cell with more than 3 or less than 2 neighbors will die
*/
void step(int gridSize, bool grid[], bool nextGrid[])
{
int x, y;
for(y = 1; y < gridSize; y++)
{
for(x = 1; x < gridSize; x++)
{
int index = getIndex(gridSize, y, x);
int neighbors = getNeighbors(gridSize, y, x, grid);
//every dead cell with exactly 3 neighbors comes back to live
if(!grid[index])
{
if(neighbors == 3)
nextGrid[index] = true;
}
//every living cell with less than 2 or more than 3 neighbors dies
else if(neighbors < 2 || neighbors > 3)
nextGrid[index] = false;
}
}
}
/**
* Recalculates the hallo
*/
void doHallo(int gridSize, bool grid[])
{
int i;
//horizontal hallo and vertical
for(i = 1; i <= gridSize; i++)
{
grid[getIndex(gridSize, 0, i)] = grid[getIndex(gridSize, gridSize, i)];
grid[getIndex(gridSize, gridSize + 1, i)] = grid[getIndex(gridSize, 1, i)];
grid[getIndex(gridSize, i, 0)] = grid[getIndex(gridSize, i, gridSize)];
grid[getIndex(gridSize, i, gridSize + 1)] = grid[getIndex(gridSize, i, 1)];
}
//hallo corners
grid[getIndex(gridSize, 0, 0)] = grid[getIndex(gridSize, gridSize, gridSize)];
grid[getIndex(gridSize, 0, gridSize + 1)] = grid[getIndex(gridSize, gridSize, 1)];
grid[getIndex(gridSize, gridSize + 1, 0)] = grid[getIndex(gridSize, 1, gridSize)];
grid[getIndex(gridSize, gridSize + 1, gridSize + 1)] = grid[getIndex(gridSize, 1, 1)];
}
/**
* Copies the contents of source to target. Will copy hallo as well
*/
void copyGrid(int gridSize, bool source[], bool target[])
{
for(int i = 0; i < (gridSize + 2) * (gridSize + 2); i++)
target[i] = source[i];
}
void makeImage(int gridSize, int step, bool grid[])
{
const int squareSize = 5;
std::ostringstream sstream;
sstream << "images/step" << step << ".pgm";
std::ofstream stream(sstream.str().c_str());
stream << "P2\n#Step " << step << " of the Game of Life.\n";
stream << (gridSize * squareSize) << " " << (gridSize * squareSize) << "\n" << 1 << "\n";
int symbols = 0;
int y, x, repy, repx;
for(y = 1; y <= gridSize; y++)
{
//repeat every row squareSize times
for(repy = 0; repy < squareSize; repy++)
{
for(x = 1; x <= gridSize; x++)
{
//repeat every column squareSize times
for(repx = 0; repx < squareSize; repx++)
{
//living cells are black
if(grid[getIndex(gridSize, y, x)])
stream << "0";
//dead cells are white
else
stream << "1";
if((++symbols) % 30 == 0) // no more than 30 pixels per row (60 chars)
stream << "\n";
else
stream << " ";
}
}
}
}
}
int main(int argv, char* argc[])
{
// parameters input
int gridSize;
int probability;
int steps;
cout << "Enter grid size: ";
cin >> gridSize;
cout << "Enter initial fill probability [0 - 100]: ";
cin >> probability;
cout << "Enter steps count: ";
cin >> steps;
// initialization of the grid matrix for the current step and the next step
bool* grid = new bool[(gridSize + 2) * (gridSize + 2)];
bool* nextGrid = new bool[(gridSize + 2) * (gridSize + 2)];
initGrid(gridSize, probability, grid);
makeImage(gridSize, 0, grid);
for(int i = 1; i <= steps; i++)
{
step(gridSize, grid, nextGrid);
makeImage(gridSize, i, nextGrid);
doHallo(gridSize, nextGrid);
copyGrid(gridSize, nextGrid, grid);
}
return 0;
}