简体   繁体   中英

Beginner Conway's Game of Life

I am trying to implement Conway's Game of Life :

The universe of the Game of Life is a [...] two-dimensional orthogonal grid of square cells, each of which is in one of two possible states, live or dead (or populated and unpopulated, respectively). Every cell interacts with its eight neighbours, which are the cells that are horizontally, vertically, or diagonally adjacent. At each step in time, the following transitions occur:

  • Any live cell with fewer than two live neighbours dies, as if by underpopulation.
  • Any live cell with two or three live neighbours lives on to the next generation.
  • Any live cell with more than three live neighbours dies, as if by overpopulation.
  • Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

Given is a grid of 5 rows and 7 columns ("X" is alive, "-" is dead):

-------
-------
------X
---XXXX
------X

I need to calculate the next generation of this grid, which should be:

-------
-------
----X-X
----X-X
----X-X

But my code produces this output:

-------
-------
----X--
----X--
-------

I don't understand why this code is not giving the correct answer. What is wrong with the logic here?

Here is my code:

# #mark all places where new life will be born;
# mark all organisms which will die;
# remove all marked organisms;
# fill all marked empty cells with new organisms.
# Input data will contain 5 lines of 7 characters each. They represent a 5 by 7 fragment of the game field.

def convert(initial_state= ('''-------
-------
------X
---XXXX
------X''')): #convert input into a list, so it is easier to operate on

    game_list = []
    row_start = 0 
    row_end = 7

    for _ in range(5):
        row_cells = ''

        for i in range(row_start,row_end):
            row_cells += initial_state[i]
        game_list.append(row_cells)
        row_start += 8
        row_end += 8

    return(game_list)

def mark_cell():
    #if cell has 0-1 or 3+ alive neighbours(X) - dies
    #if 2 neighbours - survives
    #if 3 neighbours - it becomes alive
    
    result = '' #life after day 1 (after one neighbour check for all cells)

    game_list = convert()

    for r in range(len(game_list)):
        result += '''
        '''
        for c in range(len(game_list[r])):
            choosen_cell = game_list[r][c]
        
            try:
                born_count = 0
                neighbours = [game_list[r-1][c-1],game_list[r-1][c],game_list[r-1][c+1],game_list[r][c-1],game_list[r][c+1],game_list[r+1][c-1],game_list[r+1][c],game_list[r+1][c+1]]
                

                if r == 0 and c != 0 and c!= 6:
                    neighbours = neighbours[3:]
                elif r == 4 and c != 0 and c!= 6:
                    neighbours = neighbours[:5]

                elif c == 0 and r != 0 and r != 4:

                    del neighbours[5]
                    del neighbours[3]
                    del neighbours[0]
                    
                elif c == 6  and r != 0 and r != 4:

                    del neighbours[7]
                    del neighbours[4]
                    del neighbours[2]

                elif r == 0 and c == 0:
                    
                    neighbours = neighbours[3:]
                    del neighbours[2]
                    del neighbours[0]

                elif r == 0 and c == 6:
                    
                    neighbours = neighbours[3:]
                    del neighbours[4]
                    del neighbours[1]

                elif r == 4 and c == 0:
                    
                    neighbours = neighbours[:5]
                    del neighbours[3]
                    del neighbours[0]

                elif r == 4 and c == 6:

                    neighbours = neighbours[:5]
                    del neighbours[4]
                    del neighbours[2]

                for num in neighbours:
                    if  num == "X":
                        born_count +=1

            except IndexError:
                pass  

            finally:
                pass

            if born_count < 2 or born_count > 3:
                result += "-"
            elif born_count == 3:
                result += "X"
            else:
                result += choosen_cell
    print (result)
    return result        

mark_cell()

The first function changes the multiline string input into a list with rows as its elements.

The second function checks the neighbour of each cell, counts alive neighbours and creates new multiline string, which represents the "board" state after one dead-alive check (or rather it was supposed to do so).

What is wrong with the logic here?

There are a few issues here:

  • When r is 0, the access to [r-1] will be to the last row. A cell in the first row does not have neighbors in the 5 th row, so this is wrong. A similar thing happens with [c-1]

  • When r is 4 (the last row), then the access to [r+1] will trigger an exception, and the way this exception is handled means that born_count will remain zero, so ignoring the fact there are some other neighbors that should have been counted.

You can fix these issues by filtering first the valid row coordinates, and for each of those, the valid column coordinates. Only when that is true, process that neighbor. You can use min and max functions to do such filtering on the coordinate.

Here is a correction of your mark_cell function. A few other things were improved but are not essential to the correction:

def mark_cell():
    result = ''
    game_list = convert()
    for r in range(len(game_list)):
        result += '\n'
        for c in range(len(game_list[r])):
            choosen_cell = game_list[r][c]
            born_count = 0
            for rr in range(max(0, r-1), min(len(game_list), r+2)):
                for cc in range(max(0, c-1), min(len(game_list[rr]), c+2)):
                    if (rr, cc) != (r, c) and game_list[rr][cc] == "X":
                        born_count += 1
            if born_count == 3:
                result += "X"
            elif born_count == 2:
                result += choosen_cell
            else:
                result += "-"
    return result

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM