pythontkinterconways-game-of-life

Trying to fix a problem with finding neighbors in Conway's Game of Life


I was trying to recreate Conway's Game of Life in python using Tkinter, but I got stuck while checking for the neighbors. I can't seem to find the solution to my problem. If a cell is alive it is stored using numpy, 0 for the dead cells and 1 for the living cells. The function "get_neighbours" checks if the cell is not in a corner or next to a side and it returns the ammount of neighbours each cell has. The function "recalculate" basically makes a new board with 0s and 1s which then replaces the original board and redraws everything. But when compared to an already existing game the progress is different.

import tkinter as tk
import numpy as np
win = tk.Tk()

WIDTH = 500
HEIGHT = 500
vs = 10
absvs = vs
cells = np.zeros((WIDTH//vs, HEIGHT//vs), dtype=int)
cells_new = np.zeros((WIDTH//vs, HEIGHT//vs), dtype=int)

def get_neighbours(x, y):
    total = 0
    if x > 0:
        total += cells[x - 1, y]
    if x > 0 and y > 0:
        total += cells[x - 1, y - 1]
    if y > 0:
        total += cells[x, y - 1]
    if x > 0 and y < (HEIGHT // absvs - 1):
        total += cells[x - 1, y + 1]
    if x < (WIDTH // absvs - 1):
        total += cells[x + 1, y]
    if x < (WIDTH // absvs - 1) and y < (HEIGHT // absvs - 1):
        total += cells[x + 1, y + 1]
    if y < (HEIGHT // absvs - 1):
        total += cells[x, y + 1]
    if x > 0 and y < (HEIGHT // absvs - 1):
        total += cells[x - 1, y + 1]
    return total

def recalculate():
    global cells, cells_new
    for y in range(HEIGHT//absvs):
        for x in range(WIDTH//absvs):
            temp = get_neighbours(x, y)
            if (temp == 2 and cells[x, y] == 1) or (temp == 3 and cells[x, y] == 1):
                cells_new[x, y] = 1
            elif temp == 3 and cells[x, y] == 0:
                cells_new[x, y] = 1
            elif temp < 2 or temp > 3:
                cells_new[x, y] = 0
    cells = cells_new
    canvas.delete("all")
    create_stage()
    redraw_cell()

def slider_changer(e):
    global vs
    canvas.delete("all")
    vs = w.get()
    create_stage()
    redraw_cell()

def create_cell(e):
    global cells
    tx = e.x // vs
    ty = e.y // vs
    x = tx * vs
    y = ty * vs
    canvas.create_rectangle(x, y, x + vs, y + vs, fill="gray")
    cells[tx, ty] = 1
    print(get_neighbours(tx, ty))

def redraw_cell():
    for x in range(WIDTH//vs):
        for y in range(HEIGHT//vs):
            if cells[x, y] == 1:
                canvas.create_rectangle(x * vs, y * vs, x * vs + vs, y * vs + vs, fill="gray")


def create_stage():
    for x in range(WIDTH//vs):
        canvas.create_line(x*vs, 0, x*vs, HEIGHT)
    for y in range(HEIGHT//vs):
        canvas.create_line(0, y*vs, WIDTH, y*vs)

canvas = tk.Canvas(width = WIDTH, height = HEIGHT, bg = "white")
canvas.pack()

w = tk.Scale(win, from_=10, to=50, orient="horizontal", command = slider_changer, length = 500)
w.pack()
w2 = tk.Button(win, text = "PRESS ME!!!", command = recalculate)
w2.pack()

create_stage()
canvas.bind("<Button-1>", create_cell)
win.mainloop()

Solution

  • There are these issues in your code:


    1 It is not helping that several websites, including https://www.geeksforgeeks.org/how-to-copy-numpy-array-into-another-array/ and https://www.askpython.com/python-modules/numpy/numpy-copy, wrongly assert that an assignment of one numpy array to another makes a copy. That is not true.