0
\$\begingroup\$

the getNeighbors and isOutOfBounds function works fine as far as my tests go but for some reason the game never works as intended and i did the rules according to this:

  • Any live cell with two or three live neighbours survives.
  • Any dead cell with three live neighbours becomes a live cell.
  • All other live cells die in the next generation. Similarly, all other dead cells stay dead.

this is the advance() function of my game of life attempt:

var grid : MutableList<MutableList<Boolean>> // initialised in the constructor
    fun advance()
    {
        var iter = grid.iterator()
        var toSet = MutableList(grid.size)  { i-> iter.next()}
        var dieAmount = 0
        var reviveAmount = 0
        for( col in 0 until grid.size)
        {
            for( row in 0 until grid[0].size )
            {
                var neighbors = getNeighborCount(grid, col, row)



                if(!(neighbors == 2 || neighbors == 3))
                {
                    toSet[col][row] = false
                    dieAmount++
                }
                 if(neighbors == 3 && !grid[col][row])
                {
                    toSet[col][row] = true
                    reviveAmount++
                }
                else
                    toSet[col][row] = false

            }

        }
        //println("dieAmount: $dieAmount surviveAmount: $reviveAmount")
        grid = toSet
    }

and my functions:

    fun getNeighborCount(grid: MutableList<MutableList<Boolean>>, column:Int, row:Int) : Int
    {
        var toReturn = 0
        for(minorColumn in -1..1)
            for(minorRow in -1..1)
                if(!isOverBounds(grid,column + minorColumn, row +minorRow) &&  !(minorColumn == 0 && minorRow == 0))
                {
                    if(grid[column+minorColumn][row + minorRow])
                    {
                        toReturn++
                    }
                }
        return toReturn
    }


    fun <T> isOverBounds(args: MutableList<MutableList<T>>, colCheck: Int, rowCheck: Int) : Boolean
    {
        if(args.size < colCheck+1 ||colCheck < 0) return true
        if(args[0].size<rowCheck+1||rowCheck < 0) return true
        return false
    }

the game is initially at this state:

enter image description here

advancement 1:

enter image description here

and the sole cell disappears in the second

another example:

enter image description here

advancement 1:

enter image description here

advancement 2:

enter image description here

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Your if statements are not correct.

Lets assume neightbors = 2 (2 neightbors) and grid[col][row] = true (the cell is alive)

The rules states that "Any live cell with two or three live neighbours survives."

Lets check the if statements

  • if(!(neighbors == 2 || neighbors == 3)): if(!(true || false)): if(!true): if(false): We don't take this branch
  • if(neighbors == 3 && !grid[col][row]): if(false && !true): if(false && false): if(false): We don't take this branch
  • else: We take this branch, and set the new value to false. This is incorrect.

We need to implement these if statements following the rules, like

            if(grid[col][row] && (neighbors == 2 || neighbors == 3))
            {
                // Any live cell with two or three live neighbours survives.
                toSet[col][row] = true
            }
            else if(!grid[col][row] && neighbors == 3)
            {
                // Any dead cell with three live neighbours becomes a live cell.
                toSet[col][row] = true
                reviveAmount++
            }
            else if(grid[col][row])
            {
                // All other live cells die in the next generation. 
                toSet[col][row] = false
                dieAmount++
            }
            else
            {
                // Similarly, all other dead cells stay dead.
                toSet[col][row] = false;
            }
           
\$\endgroup\$
8
  • \$\begingroup\$ thanks for your help but the algorithm you provided doesn't work as intended \$\endgroup\$ Nov 21, 2021 at 14:16
  • \$\begingroup\$ @logic "doesn't work" is generally not enough information to diagnose and fix a problem. Try to explain a concrete test case and how the behaviour of this code deviates from what you expect in that case. \$\endgroup\$
    – DMGregory
    Nov 21, 2021 at 14:20
  • \$\begingroup\$ a comparison: i.imgur.com/E8X8sbD.png \$\endgroup\$ Nov 21, 2021 at 14:36
  • 2
    \$\begingroup\$ Another problem is how you are defining "toSet", it is not making a copy properly. You are making a copy of the initial list, the the inner lists are left alone. The algorithm needs to work on the old state, and not a mix of the old and new state \$\endgroup\$
    – Ferrybig
    Nov 21, 2021 at 14:51
  • 2
    \$\begingroup\$ What Ferrybig is saying is that toSet is a shallow copy. It's a new list of columns, but each column inside it is still the original MutableList<Boolean> from grid, just repackaged in a new wrapper. When you set a value inside a column of toSet, it's the original column of grid you're modifying. You need to make a deep copy or, since you're assigning every cell in your loop anyway, just make a new empty grid of the same size, rather than a copy. You could also ping-pong between two grids if you prefer. \$\endgroup\$
    – DMGregory
    Nov 21, 2021 at 16:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .