【问题标题】:Game of Life implementation doesn't work properly in Python生命游戏的实现在 Python 中无法正常工作
【发布时间】:2020-11-08 22:19:24
【问题描述】:

我在使用我的自动机 - Game of Life 时遇到问题。好吧,我有一个图像,我将其转换为 2d 矩阵。在这张图片的中间有一个振荡器。正如规则所说,这个函数的输出应该是另一个振荡器,但旋转了 90 度。不幸的是我的输出是错误的。您可以在下面的图片中看到。代码有什么问题?你能帮我解决这个问题吗?

def sim():
    tab = cv2.imread(jpg_path, 0)
    tab_x = tab.shape[0]
    tab_y = tab.shape[1]

    new_tab = np.zeros([tab_x, tab_y])

    for x in range(0, tab_x):
        for y in range(0, tab_y):
            if tab[x, y] == 255:
                tab[x, y] = 0
            else:
                tab[x, y] = 1

    #new_tab = tab.copy()

    for x in range(tab_x):
        for y in range(tab_y):
     
            summary = (tab[x, (y-1) % tab_x] + tab[x, (y+1) % tab_x] +
                         tab[(x-1) % tab_x, y] + tab[(x+1) % tab_x, y] +
                         tab[(x-1) % tab_x, (y-1) % tab_x] + tab[(x-1) % tab_x, (y+1) % tab_x] +
                         tab[(x+1) % tab_x, (y-1) % tab_x] + tab[(x+1) % tab_x, (y+1) % tab_x])

            if tab[x, y] == 1:
                if (summary < 2) or (summary > 3):
                    new_tab[x, y] = 0
            else:
                if summary == 3:
                    new_tab[x, y] = 1

    for y in range(0, tab_y):
        for x in range(0, tab_x):
            if new_tab[y, x] == 1:
                new_tab[y, x] = 0
            else:
                new_tab[y, x] = 255

    cv2.imwrite('anMD.jpg', new_tab)

input output

编辑:我正在添加更多功能,也许有问题。现在我的代码如下所示:

def osc(tab, x, y):
    tab[x-1,y-1] = 0
    tab[x-1,y] = 1
    tab[x-1,y+1] = 0
    tab[x,y-1] = 0
    tab[x,y] = 1
    tab[x,y+1] = 0
    tab[x+1,y-1] = 0
    tab[x+1,y] = 1
    tab[x+1,y+1] = 0

    return tab

def gol():
    tab_x = 50
    tab_y = 50

    x = 25
    y = 25

    tab = np.zeros([tab_x, tab_y])
    new_tab = osc(tab, x, y)

    for y in range(0, tab_y):
        for x in range(0, tab_x):
            if new_tab[y, x] == 1:
                new_tab[y, x] = 0
            else:
                new_tab[y, x] = 255

    cv2.imwrite('anMD.jpg', new_tab)
    canvas.delete("all")
    cv2.imwrite('show.jpg', new_tab)
    image = Image.open('show.jpg')
    new_image = image.resize((500, 500))
    new_image.save('show.jpg')
    dimg = ImageTk.PhotoImage(Image.open('show.jpg'))
    canvas.create_image(0, 0, anchor='nw', image=dimg)
    canvas.image = dimg

def sim():
    tab = cv2.imread(jpg_path, 0)
    tab_x = tab.shape[0]
    tab_y = tab.shape[1]

    new_tab = np.zeros_like(tab)

    for x in range(0, tab_x):
        for y in range(0, tab_y):
            if tab[x, y] == 255:
                tab[x, y] = 0
            else:
                tab[x, y] = 1

    for x in range(tab_x):
        for y in range(tab_y):
            """summary = 0
            summary += tab[x - 1, y - 1]
            summary += tab[x - 1, y]
            summary += tab[x - 1, y + 1]
            summary += tab[x, y - 1]
            summary += tab[x, y + 1]
            summary += tab[x + 1, y - 1]
            summary += tab[x + 1, y]
            summary += tab[x + 1, y + 1]"""

            summary = (tab[x, (y-1) % tab_y] + tab[x, (y+1) % tab_y] +
                         tab[(x-1) % tab_x, y] + tab[(x+1) % tab_x, y] +
                         tab[(x-1) % tab_x, (y-1) % tab_y] + tab[(x-1) % tab_x, (y+1) % tab_y] +
                         tab[(x+1) % tab_x, (y-1) % tab_y] + tab[(x+1) % tab_x, (y+1) % tab_y])

            if tab[x, y] == 1:
                if (summary < 2) or (summary > 3):
                    new_tab[x, y] = 0
                else:
                    new_tab[x, y] = 1
            else:
                if summary == 3:
                    new_tab[x, y] = 1

    for y in range(0, tab_y):
        for x in range(0, tab_x):
            if new_tab[y, x] == 1:
                new_tab[y, x] = 0
            else:
                new_tab[y, x] = 255

    for x in range (tab_x):
        for y in range (tab_y):
            tab[x, y] = new_tab[x, y]

    cv2.imwrite('anMD.jpg', new_tab)
    cv2.imwrite('show.jpg', new_tab)
    image = Image.open('show.jpg')
    new_image = image.resize((500,500))
    new_image.save('show.jpg')
    canvas.delete("all")
    dimg = ImageTk.PhotoImage(Image.open('show.jpg'))
    canvas.create_image(0, 0, anchor='nw', image=dimg)
    canvas.image = dimg

这是原始的 50x50 输入和输出。 original input original output

【问题讨论】:

  • 是的,我想了很久,但我不知道如何不混淆现在和未来。矩阵保存有问题,但是什么?

标签: python arrays conways-game-of-life cellular-automata


【解决方案1】:

您正在使用 y 值 % tab_x 而不是 % tab_y

在这一点

if tab[x, y] == 1:
    if (summary < 2) or (summary > 3):
        new_tab[x, y] = 0
    else:
        if summary == 3:
            new_tab[x, y] = 1

您遗漏了一些案例。请记住,您将 new_tab 初始化为零,因此您永远不需要设置 0,但您确实需要设置 1。

if tab[x, y] == 1:
    if (summary == 2) or (summary == 3):
        new_tab[x, y] = 1
else:
    if summary == 3:
        new_tab[x, y] = 1

应该可以。

最后,在您的读出循环中,您将通过 [y, x] 而不是 [x, y] 来索引数组。

【讨论】:

  • 这没问题,因为例子中tab_x和tab_y是​​一样的。
  • 您更新的代码不能解决我的问题。 :( 我认为保存我的矩阵有问题。那里出了点问题,但我不知道如何修复它。
【解决方案2】:

我注意到您似乎正在以 JPEG 格式读取和写入图像,并且您的图像读取代码将每个不是纯白色 (255) 的像素视为活细胞。

JPEG 是一种有损压缩的图像格式,这意味着您从读取图像文件中获得的像素值通常不会与您写入文件的像素值完全相同。特别是,当原始图像包含高对比度颜色之间的清晰边界时,在 JPEG 压缩版本中这些边界附近通常会有fringing and other compression artifacts。当被您的代码解析时,这种边缘会导致额外的活细胞出现在您的图案附近。

(要确认这是一个问题,请尝试完全删除 CA 模拟代码,并将单元状态从 tab 复制到 new_tab 不变。您的输出图像可能与输入不匹配。)

如果您坚持使用 JPEG 格式,则应将图像读取代码中的 if tab[x, y] == 255 条件更改为更健壮的内容,例如 if tab[x, y] &gt; 127。为此,您还应该强烈考虑使用不同的图像格式,例如 PNG。

附言。作为一般提示,如果您使用非常小的图像(例如,8 x 8 像素或更小)测试代码并打印出 tab / new_tab 的内容,您可能已经自己解决了这个问题在您的代码中的各个点创建数组,或者更好的是,在 debugger 中逐步检查您的代码并使用它来检查数组。

【讨论】:

  • 非常感谢!更改此“if tab[x, y] > 127”条件解决了我的问题。
【解决方案3】:

除了hobbs 所说的范围之外,您忘记了单元格存活的情况。你只介绍了当它死去或一个新的出生时会发生什么。

这只是因为我们从一个空的new_tab = np.zeroslike(tab) 开始。如果我们以new_tab = tab.copy 开头,我们就不必指定单元格存活了。

我制作了一个 matplotlib 解决方案来向您展示动画结果:)

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
fig.show()

# Base data.
tab = np.zeros((10, 10))
tab[4, 2] = 1
tab[4, 3] = 1
tab[4, 4] = 1

ax.imshow(tab)
ax.set_title("0")
plt.pause(0.3)

# Play 10 turns.
for n in range(10):
    new_tab = np.zeros_like(tab)
    tab_x, tab_y = tab.shape

    for x in range(tab_x):
        for y in range(tab_y):

            summary = (  tab[x, (y-1) % tab_y]
                       + tab[x, (y+1) % tab_y]
                       + tab[(x-1) % tab_x, y]
                       + tab[(x+1) % tab_x, y]
                       + tab[(x-1) % tab_x, (y-1) % tab_y]
                       + tab[(x-1) % tab_x, (y+1) % tab_y]
                       + tab[(x+1) % tab_x, (y-1) % tab_y]
                       + tab[(x+1) % tab_x, (y+1) % tab_y])

            if tab[x, y] == 1:
                if (summary < 2) or (summary > 3):
                    new_tab[x, y] = 0
                else:
                    new_tab[x, y] = 1 # Survival case you need to add to your code.
            else:
                if summary == 3:
                    new_tab[x, y] = 1

    ax.imshow(new_tab)
    ax.set_title(f"{n+1}")
    plt.pause(0.3)

    tab = new_tab

【讨论】:

  • 我已经提出了您的建议,但问题仍然存在。我不知道怎么了。我将在这里发布另一个与此相关的功能,也许问题出在不同的地方。
猜你喜欢
  • 1970-01-01
  • 2012-12-18
  • 1970-01-01
  • 1970-01-01
  • 2012-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多