This "game" is a tick-based Simulation.
Simulated are single cells on an infinitely large grid.
Each tick, each cell is checked for one of the following conditions:
This repeats for as many ticks as is specified.
The simulation is primarily rule based and hence offers it self to be architected in a data driven way.
A object oriented approach would make little sense, since all a cell would do, is receiving the tick signal and then asking all its neighbors, if they are alive.
The following is a high level sketch of an implementation, since the mechanics will be different depending on your programming language chosen.
Start by creating the map.
A two dimensional array of bit
s is enough, since a cell has exactly two states.
You will also need to create a second map.
The program will switch between the two maps, always treating one as a buffer and the other as the source.
Now define the behavior for the kernel.
The kernel is the selection window that will move over the source array and calculate the value inside the buffer.
------------------------- ------------------------- -------------------------
|#|#|#| | | | | | | | | | | |#|#|#| | | | | | | | | | | |#|#|#| | | | | | | |
------------------------- ------------------------- -------------------------
|#|x|#| | | | | | | | | | | |#|x|#| | | | | | | | | | | |#|x|#| | | | | | | |
------------------------- -> ------------------------- -> -------------------------
|#|#|#| | | | | | | | | | | |#|#|#| | | | | | | | | | | |#|#|#| | | | | | | |
------------------------- ------------------------- -------------------------
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
------------------------- ------------------------- -------------------------
We notice two things with the kernel:
Since we can write the whole state inside a single byte, we can count the bits set in two ways:
The actual evaluation is static in nature:
if result:
0,1,4,5,6,7,8 -> 0
3 -> 1
2 -> ignore
You will also need to track eight additional data points for each simulated tick.
Four for enlarging the array...
...and four for shrinking the array.
If you detect a change, you need to allocate or de-allocate memory respectively and enlarge or shrink the array.
You might choose one of several methods of managing the size of your arrays.
One approach that is the simplest, is to increase and decrease by one each time.
But depending on the scenario, this can lead to many re-allocations, but maybe is necessary if you are dealing with sized at the limit of your memory.
A better approach would be to increase and shrink by a given factor.
The factor can then be fine tuned to fit your scenario.
For shrinking, this would require you to track different properties.
You would need to track the longest distance between two active bits.
------------------------- -------------------------
| | | | | | | | | | | | | | | | | | | | | | | | | |
------------------------- -------------------------
| |1|1| | | |1| |1| | | | | |#|#|#|#|#|#|#|#| | | |
------------------------- -> -------------------------
| |1|1| | |1|1| | | | | | | |#|#|#|#|#|#|#|#| | | |
------------------------- -------------------------
| | | | | | | | | | | | | | | | | | | | | | | | | |
------------------------- -------------------------
The last step would be to swap the two references.
You buffer becomes the new source and the source becomes the new buffer.