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