python - Conway 的生命游戏在计算邻居时出现错误,因此得到错误的结果

python - Conway's Game of Life bug at calculating neighbors, and therefore gets wrong results

我正在尝试构建“Conway 的生命游戏”,但出于某种原因,邻居的数量计算不正确,因此我得到了错误的结果。请帮助我:)

我很迷茫我不知道怎么了...

我试过的例子,只是让白板空白

[[1, 1, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 1, 1], [1, 1, 0, 1 , 1], [0, 1, 0, 1, 0]]


| * | * | | | |


| | * | * | * | |


| | | | * | * |


| * | * | | * | * |


| | * | | * | |


def userinp(size_):
"""
    create the matrix by taking user input on board with user default range size.
    :return: a matrix (lists inside a list)
"""
    matrix = []

    for i in range(size_):
        line = []
        for j in range(size_):
            cell = int(input(f"Row {i + 1} column {j + 1} : "))
            line.append(cell)
        matrix.append(line)
        if i == size_ - 1:  # when reach limit of rows & lines we stop asking from the user an input.
            continue
        else:
            print(f"line {i+1} submitted. continue to line {i+2} : ")

    return matrix


def draw(board, size):
    """
    draw the board by user input (board) of matrix and games rules.
    """
    for i in range(size):
        print(" ---" * size)
        for j in range(size):
            if board[i][j] == 0:
                print("|   ", end='')
            elif board[i][j] == 1:
                print("| * ", end='')
            if j == size - 1:
                print("|")
        if i == size - 1:
            print(" ---" * size)


def calc_cell(old_status, size, matrix, row, col, new_status=0, neighbors=0):
    """
    calculate neighbors and return the new value of the cell.

    :param old_status: boolean value represent if the cell alive or dead
    :param new_status: the new value that will be returned to the cell
    :param size: size of matrix
    :param matrix: the data of the matrix
    :param row: the row of the cell The function check
    :param col: the column of the cell the function check
    :param neighbors: number of the live neighbors of the cell.
    :return: '1' if alive or '0' if dead.
    """
 # check all the cells around the cell, before checking the cells I check if the neighbor cell is in our range.
    if row - 1 >= 0 and col - 1 >= 0:
        if matrix[row-1][col-1] == 1:
            neighbors += 1

    elif row - 1 >= 0:
        if matrix[row-1][col] == 1:
            neighbors += 1

    elif row - 1 >= 0 and col + 1 < size:
        if matrix[row-1][col+1] == 1:
            neighbors += 1

    elif col - 1 >= 0:
        if matrix[row][col-1] == 1:
            neighbors += 1

    elif col + 1 < size:
        if matrix[row][col+1] == 1:
            neighbors += 1

    elif col - 1 >= 0 and row + 1 < size:
        if matrix[row+1][col-1] == 1:
            neighbors += 1

    elif row + 1 < size:
        if matrix[row+1][col] == 1:
            neighbors += 1

    elif col + 1 < size and row + 1 < size:
        if matrix[row+1][col+1] == 1:
            neighbors += 1

    print(f"neighbors = {neighbors}")  # todo: delete
    # check by the rules of the game what is the new status of the cell.
    alive = old_status

    if alive and neighbors <= 1:
        new_status = 0

    elif neighbors > 3:
        new_status = 0

    elif not alive and neighbors == 3:
        new_status = 1

    elif alive and (neighbors == 2 or neighbors == 3):
        new_status = int(old_status)  # convert the boolean value to '0' or '1' (integers)

    return new_status


def main():
    s = int(input("Please enter the size of the board (rows = columns): "))
    print("Please enter input for stating the game.\nInput is '1' for a live cell and 
'0' for dead cell.")
    b = userinp(s)  # my board, a matrix.
    draw(b, s)

    # start checking cells status
    while True:
        # create empty matrix to store updated values
        line = [0 for _ in range(s)]
        new_mat = [line for _ in range(s)]
        # put new values in new matrix
        for row in range(s):
            for col in range(s):
                new_mat[row][col] = calc_cell(old_status=bool(b[row][col]), size=s, matrix=b, row=row, col=col)
            print(b)  # todo: delete

        draw(new_mat, s)
        q = input("would you like the program to continue calculating the board? (type yes / no): ").lower()
        if 'n' in q:
            break
        else:
            b = new_mat


if __name__ == '__main__':
    main()

ifelif的系列中,最多执行其中一个,这意味着neighbors是0或1。

您可以将 elifs 替换为 ifs,但我建议至少使用一些循环来简化代码:

for dx in [-1, 0, 1]:
    for dy in [-1, 0, 1]:
        # For the 3x3 square around the cell
        if (0 <= col + dx < size) and (0 <= row + dy < size):
            if (dx != 0 or dy != 0) and matrix[row + dy][col + dx] == 1:
                # Excludes the cell itself
                neighbors += 1

您的代码中还有另一个错误:

line = [0 for _ in range(s)]
new_mat = [line for _ in range(s)]

现在new_mat是一个条目列表,所有条目都指向同一行,这意味着修改一行将有效地修改所有行。相反,使用:

new_mat = [[0 for _ in range(s)] for _ in range(s)]