0

The algorithm I created (implementation of Conway's Game of Life's rules) doesn't match Conway's GoL. I've tried just about everything I can do, but it just doesn't match.

Additionally, if anyone knows how to make it into an infinite plane or perhaps wrap on itself, I'd be interested to see it implemented with my code!

Running JSFiddle: http://jsfiddle.net/jGkKF/2/

Pertinent code:

Checking the surrounding cells for live cells: (Line 28)

var   x2 = x+1,   x3 = x-1,   y2 = y+1,   y3 = y-1;     // Math
if(tC[x][y3] !== undefined && tC[x][y3]) ne++;          // T
if(tC[x][y2] !== undefined && tC[x][y2]) ne++;          // TR
if(tC[x2] !== undefined) {
    if(tC[x2][y]) ne++;                                 // R
    if(tC[x2][y3] !== undefined && tC[x2][y3]) ne++;    // BR
    if(tC[x2][y2] !== undefined && tC[x2][y2]) ne++;    // B
}
if(tC[x3] !== undefined) {
    if(tC[x3][y]) ne++;                                 // BL
    if(tC[x3][y3] !== undefined && tC[x3][y3]) ne++;    // L
    if(tC[x3][y2] !== undefined && tC[x3][y2]) ne++;    // TL
}

And the algorithm: (Line 50)

if(cell && (ne < 2 || ne > 3)) cell = 0; // Over- or under- populated?
else if(!cell && ne == 3) cell = 1;      // Give life?
Alca
  • 55
  • 1
  • 8

2 Answers2

1

A few items:

  1. The game rules say to check all 8 surrounding squares. Based on your code, you seem to be only checking 6 of them. Edit: OP is checking all 8. I still recommend point 2, it allows consistent handling of each cell being checked.
  2. The easiest way to hand it is to set up a list of cells that need to be check, then run a loop over that list to do the counting.
  3. To set up a wrapping list, have bounds checking code when setting up the list of cells, e.g.
    • if cellIndex < 0 then cellIndex == maxIndex
    • if cellIndex >= maxIndex then cellIndex = 0
  4. You need to be wary of a "scan line" effect that can occur if you update the values representing "this" generation while trying to calculate the "next" generation. The two need to be stored independently. Note if you are using arrays of ints, this can simply mean storing "this" generation as 0 and 1, and the "next" generation of live cells can be indicated by adding 8 etc. After you process the current generation, change everything >= 8 to 1, and any cell < 8 becomes 0.
Shawn C
  • 356
  • 2
  • 5
  • It is set to check all 8 if they exist and if it's alive. If it exists and alive, then it counts it. – Alca Apr 09 '14 at 17:21
  • I looked at your fiddle - as I said in point #4, and as @Pointy also points out, your not separating "this" generation from the "next" generation, so the results are off. See http://stackoverflow.com/questions/509579/how-does-variable-assignment-work-in-javascript and http://stackoverflow.com/questions/122102/most-efficient-way-to-clone-an-object/5344074#5344074 . Also, if you add a single step button, you'll get a better view on the logic. – Shawn C Apr 09 '14 at 22:11
  • `tC = cells.slice(0);` seems to store the past generation just fine. This still does not allow me to match any of Conway's results. I'm getting "explosive growth" when I shouldn't be. No patterns work other than some of the basic static shapes like "block" – Alca Apr 09 '14 at 23:03
  • Add a single step mode to your UI. Similar to your "Simulate" button, have it turn on both the `simulate` flag & a new `onegeneration` flag. You can then see what is happening in each generation. You could even do cools stuff like set new cells to green (e.g. 2) and died cells a dark red (e.g. store as -1) – Shawn C Apr 10 '14 at 12:30
0

The statement

tC = cells;

does not make a copy of the cell array. It merely creates a second reference to the exact same array. Thus, later on, when you do this:

cells[x][y] = cell; // Setting the cell

that's modifying the same array that the loop is looking at.

Also, in your loop to check neighbors, you've coded an exact comparison to undefined. However, the rest of your code seems to fill empty cells in with 0.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • I meant to say reference. It checks if they exist, due to it being a limited square, and then if it's alive. If both are true, then it counts it. – Alca Apr 09 '14 at 17:22
  • Well if you're updating the cell matrix while you're making a generational pass, it won't work, because you'll be modifying cells you need to check for the next row of the "world" grid. You might want to make things work by switching back and forth between *two* grids. – Pointy Apr 09 '14 at 17:33
  • Ah. Well that's not optimal, but I'll do it. – Alca Apr 09 '14 at 19:12
  • @Alca it shouldn't be that bad. All you have to do is clear out each cell in the "new" grid before determining it's state by looking at the "old" grid. Then you just have to flip the variables that reference each grid, so that on the next generation the "new" grid is the "old" grid, and the *former* old grid is the new new grid. – Pointy Apr 09 '14 at 19:25
  • I have tried `tC = cells.slice(0);` and I still get the same effect that is unlike Conway's GOL. – Alca Apr 09 '14 at 22:23
  • @Alca that won't do it - it's a 2-dimensional array. That'll give you an array with references to the same rows. But you don't have to make a copy anyway. Just initialize two empty arrays at the start, and then flip back and forth between them. – Pointy Apr 09 '14 at 23:23
  • Then I don't understand how I'm supposed to do it. Perhaps pseudo/real code would help. – Alca Apr 09 '14 at 23:37