Skip to content

Commit a1d5621

Browse files
authored
LedMatrix: add Game of Life example (#60)
Former-commit-id: 1086e0d
1 parent 09bf31b commit a1d5621

File tree

1 file changed

+255
-0
lines changed

1 file changed

+255
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
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

Comments
 (0)