I'm trying to built 'Conway's Game of Life' but for some reason the number of neighbors are not calculated correctly, therefore I gets wrong results. please help me:)
I'm pretty lost I don't know what's wrong...
example that I tried and just make the board blank
[[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()
CodePudding user response:
In the series of if
and elif
s, at most one of them will get executed, which means neighbors
is either 0 or 1.
You may replace elif
s with if
s, but I would recommend at least using some loops to simplify the code:
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
There is another bug in your code:
line = [0 for _ in range(s)]
new_mat = [line for _ in range(s)]
Now new_mat
is a list of entries all pointing to the same line, which means modifying one line will effectively modify all the line. Instead, use:
new_mat = [[0 for _ in range(s)] for _ in range(s)]