Search code examples
pythonlistconways-game-of-lifecopying

Copying List Error Python (part of Conway's Game of Life)


This is not my whole code. This just shows what I want done. What I want is for the list "board" to stay the same and for the list "new" to change. The problem I have with the program is that the list "new" changes as well as board.

DEADCELL = "."
LIVECELL = "A"
rows = 5
columns = 5

def startingBoard():
    cellRow = ""
    cellCol = 1
    board = []
    for i in range(rows):
        board.append([DEADCELL]* columns)
    while cellRow != "q":
        cellRow = input("Please enter the row of a cell to turn on (or q to exit): ")  
        if cellRow != "q":
            cellCol = int(input("Please enter a column for that cell: "))
            board[int(cellRow)][cellCol] = LIVECELL
    return board

def printBoard(board):
    for i in range(rows):
        printRow = ""
        for j in range(columns):
            if board[i][j] == LIVECELL:
                printRow = printRow + LIVECELL
            elif board[i][j] == DEADCELL:
                printRow = printRow + DEADCELL
        print(printRow)
    print("\n")

def neighbors(board):
    new = list(board)
    for r in range(rows):
        for c in range(columns):
            neighbors = 0
            # ALL THIS SECTION DOES IS CHECK THE 'NEIGHBORS' AROUND A CELL
            if r - 1 >= 0 and c - 1 >= 0:
                if board[r - 1][c - 1] == LIVECELL:
                    neighbors += 1
            if c - 1 >= 0:
                if board[r][c-1] == LIVECELL:
                    neighbors += 1
            if r + 1 < rows and c + 1 < rows:
                if board[r + 1][c + 1] == LIVECELL:
                    neighbors += 1
            if r - 1 >= 0:
                if board[r - 1][c] == LIVECELL:
                    neighbors += 1
            if r + 1 < rows:  
                if board[r + 1][c] == LIVECELL:
                    neighbors += 1
            if r - 1 >=0 and c + 1 < rows:
                if board[r-1][c+1] == LIVECELL:
                    neighbors += 1
            if c + 1 < rows:
                if board[r][c+1] == LIVECELL:
                    neighbors += 1
            if r + 1 < rows and c - 1 >= 0:
                if board[r+1][c-1] == LIVECELL:
                    neighbors += 1

            # RULES FOR CELLS:
            # IF A LIVE CELL HAS TWO OR THREE NEIGHBORS, IT STAYS ALIVE
            # IF A LIVE CELL HAS LESS THAN TWO NEIGHBORS, IT DIES
            # IF A LIVE CELL HAS MORE THAN THREE NEIGHBORS, IT DIES
            # IF A DEAD CELL HAS THREE NEIGHBORS, IT BECOMES ALIVE
            if board[r][c] == DEADCELL and neighbors == 3:
                new[r][c] = LIVECELL
            elif board[r][c] == LIVECELL and (neighbors < 2 or neighbors > 3):
                new[r][c] = DEADCELL
    #This prints out the new list and the board list to show you guys how they are the same.
    print(new)
    print(board)

def main():
    board = startingBoard()
    printBoard(board)
    neighbors(board)
    printBoard(board)
main()

Here is my output:

Please enter the row of a cell to turn on (or q to exit): 2
Please enter a column for that cell: 1
Please enter the row of a cell to turn on (or q to exit): 2
Please enter a column for that cell: 2
Please enter the row of a cell to turn on (or q to exit): 2
Please enter a column for that cell: 3
Please enter the row of a cell to turn on (or q to exit): q
.....
.....
.AAA.
.....
.....


[['.', '.', '.', '.', '.'], ['.', '.', 'A', 'A', '.'], ['.', 'A', '.', 'A', '.'], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.']]
[['.', '.', '.', '.', '.'], ['.', '.', 'A', 'A', '.'], ['.', 'A', '.', 'A', '.'], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.']]
.....
..AA.
.A.A.
.....
.....

See how the lists new and board are the same. Why is that?


Solution

  • new = list(board) is shallow copy: it will not clone the sub-elements, it will just copy the references.

    a = [[True]]
    b = list(a)
    b[0][0] = False
    a
    # => [[False]]
    

    You need deep copy:

    a = [[True]]
    from copy import deepcopy
    b = deepcopy(a)
    b[0][0] = False
    a
    # => [[True]]