1
+ /*
2
+ Example developed starting from Toby Oxborrow's sketch
3
+ https://github.com/tobyoxborrow/gameoflife-arduino/blob/master/GameOfLife.ino
4
+ */
5
+
6
+ #include " Arduino_LED_Matrix.h"
7
+
8
+ // grid dimensions. should not be larger than 8x8
9
+ #define MAX_Y 8
10
+ #define MAX_X 12
11
+
12
+ // time to wait between turns
13
+ #define TURN_DELAY 200
14
+
15
+ // how many turns per game before starting a new game
16
+ // you can also use the reset button on the board
17
+ #define TURNS_MAX 60
18
+
19
+ // number of patterns in predefined list
20
+ #define MAX_PATTERNS 4
21
+
22
+ // how many turns to wait if there are no changes before starting a new game
23
+ #define NO_CHANGES_RESET 4
24
+
25
+ int turns = 0 ; // counter for turns
26
+ int noChanges = 0 ; // counter for turns without changes
27
+
28
+ // game state. 0 is dead cell, 1 is live cell
29
+ uint8_t grid[MAX_Y][MAX_X] = {
30
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
31
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
32
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
33
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
34
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
35
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
36
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
37
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
38
+ };
39
+
40
+ int currentPattern = 0 ;
41
+
42
+ String patternNames[] = {
43
+ " Glider" ,
44
+ " Light-weight spaceship" ,
45
+ " R-Pentomino" ,
46
+ " Diehard"
47
+ };
48
+
49
+ // custom starting grid patterns
50
+ boolean cGrids[][MAX_Y][MAX_X] = {
51
+ { /* Glider */
52
+ {0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
53
+ {0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
54
+ {1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
55
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
56
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
57
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
58
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
59
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
60
+ },
61
+ { /* Light-weight spaceship */
62
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
63
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
64
+ {0 , 0 , 0 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 },
65
+ {0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
66
+ {0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 },
67
+ {0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 },
68
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
69
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
70
+ },
71
+ { /* R-Pentomino */
72
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
73
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
74
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
75
+ {0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 },
76
+ {0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 },
77
+ {0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 },
78
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
79
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
80
+ },
81
+ { /* Die hard */
82
+ {0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 },
83
+ {1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
84
+ {0 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 0 , 0 , 0 , 0 },
85
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
86
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
87
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
88
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
89
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
90
+ }
91
+ };
92
+
93
+
94
+ ArduinoLEDMatrix matrix;
95
+
96
+ void setup () {
97
+ Serial.begin (9600 );
98
+ delay (1000 );
99
+
100
+ Serial.println (" Conway's game of life on Arduino LED Matrix" );
101
+ matrix.begin ();
102
+
103
+ resetGrid ();
104
+ displayGrid ();
105
+
106
+ }
107
+
108
+ void loop () {
109
+ delay (TURN_DELAY);
110
+
111
+ playGoL ();
112
+
113
+ turns++;
114
+
115
+ // reset the grid if no changes have occured recently
116
+ // for when the game enters a static stable state
117
+ if (noChanges > NO_CHANGES_RESET) {
118
+ resetGrid ();
119
+
120
+ }
121
+ // reset the grid if the loop has been running a long time
122
+ // for when the game cycles between a few stable states
123
+ if (turns > TURNS_MAX) {
124
+ resetGrid ();
125
+ }
126
+
127
+ displayGrid ();
128
+ }
129
+
130
+ // play game of life
131
+ void playGoL () {
132
+ /*
133
+ 1. Any live cell with fewer than two neighbours dies, as if by loneliness.
134
+ 2. Any live cell with more than three neighbours dies, as if by
135
+ overcrowding.
136
+ 3. Any live cell with two or three neighbours lives, unchanged, to the next
137
+ generation.
138
+ 4. Any dead cell with exactly three neighbours comes to life.
139
+ */
140
+
141
+ boolean newGrid[MAX_Y][MAX_X] = {
142
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
143
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
144
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
145
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
146
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
147
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
148
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
149
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
150
+ };
151
+
152
+ for (int y = 0 ; y < MAX_Y; y++) {
153
+ for (int x = 0 ; x < MAX_X; x++) {
154
+ int neighboughs = countNeighbours (y, x);
155
+ if (grid[y][x] == 1 ) {
156
+ if ((neighboughs == 2 ) || (neighboughs == 3 )) {
157
+ newGrid[y][x] = 1 ;
158
+ } else {
159
+ newGrid[y][x] = 0 ;
160
+ }
161
+ } else {
162
+ if (neighboughs == 3 ) {
163
+ newGrid[y][x] = 1 ;
164
+ } else {
165
+ newGrid[y][x] = 0 ;
166
+ }
167
+ }
168
+ }
169
+ }
170
+
171
+ // update the current grid from the new grid and count how many changes
172
+ // occured
173
+ int changes = 0 ;
174
+ for (int y = 0 ; y < MAX_Y; y++) {
175
+ for (int x = 0 ; x < MAX_X; x++) {
176
+ if (newGrid[y][x] != grid[y][x]) {
177
+ changes++;
178
+ }
179
+ grid[y][x] = newGrid[y][x];
180
+ }
181
+ }
182
+
183
+ // update global counter when no changes occured
184
+ if (changes == 0 ) {
185
+ noChanges++;
186
+ }
187
+ }
188
+
189
+ // count the number of neighbour live cells for a given cell
190
+ int countNeighbours (int y, int x) {
191
+ int count = 0 ;
192
+
193
+ // -- Row above us ---
194
+ if (y > 0 ) {
195
+ // above left
196
+ if (x > 0 ) {
197
+ count += grid[y - 1 ][x - 1 ];
198
+ }
199
+ // above
200
+ count += grid[y - 1 ][x];
201
+ // above right
202
+ if ((x + 1 ) < 8 ) {
203
+ count += grid[y - 1 ][x + 1 ];
204
+ }
205
+ }
206
+
207
+ // -- Same row -------
208
+ // left
209
+ if (x > 0 ) {
210
+ count += grid[y][x - 1 ];
211
+ }
212
+ // right
213
+ if ((x + 1 ) < 8 ) {
214
+ count += grid[y][x + 1 ];
215
+ }
216
+
217
+ // -- Row below us ---
218
+ if ((y + 1 ) < 8 ) {
219
+ // below left
220
+ if (x > 0 ) {
221
+ count += grid[y + 1 ][x - 1 ];
222
+ }
223
+ // below
224
+ count += grid[y + 1 ][x];
225
+ // below right
226
+ if ((x + 1 ) < 8 ) {
227
+ count += grid[y + 1 ][x + 1 ];
228
+ }
229
+ }
230
+
231
+ return count;
232
+ }
233
+
234
+ // reset the grid
235
+ void resetGrid () {
236
+ Serial.print (" Current pattern: " );
237
+ Serial.println (patternNames[currentPattern]);
238
+ noChanges = 0 ;
239
+ turns = 0 ;
240
+
241
+ for (int y = 0 ; y < MAX_Y; y++) {
242
+ for (int x = 0 ; x < MAX_X; x++) {
243
+ grid[y][x] = cGrids[currentPattern][y][x];
244
+ }
245
+ }
246
+ currentPattern++;
247
+ if (currentPattern >= MAX_PATTERNS){
248
+ currentPattern = 0 ;
249
+ }
250
+ }
251
+
252
+ // display the current grid to the LED matrix
253
+ void displayGrid () {
254
+ matrix.renderBitmap (grid, 8 , 12 );
255
+ }
0 commit comments