簡體   English   中英

我一直在用 python 制作康威的生活游戲,為什么它不起作用?

[英]I've been making conway's game of life in python, why doesn't it work?

因此,在 Cell.update() 中檢測它是否應該活着的代碼一定有問題,但是我硬編碼的滑翔機沒有按預期工作。 第一代和第二代按預期工作,但在第三代就消失了。 有誰知道問題是什么? 我知道代碼有點亂,但我對 python 很陌生,所以這是意料之中的。 提前致謝!

這是代碼:

import pygame

"""
rules:

1. Any live cell with two or three live neighbours survives.
2. Any dead cell with three live neighbours becomes a live cell.
3. All other live cells die in the next generation. Similarly, all other dead cells stay dead.

number cells on screen = 32x18
cell size = 30x30
"""

# variables
WIDTH = 960
HEIGHT = 540
TITLE = "Conway's Game Of Life"

GRID_COLOUR = (200, 200, 200)
BG_COLOUR = (255, 255, 255)

grid = [[False] * 32] * 18
cells = []

live_queue = []
die_queue = []

# window
wn = pygame.display.set_mode((WIDTH, HEIGHT), vsync=1)
pygame.display.set_caption(TITLE)


# classes
class Cell:
    def __init__(self, x, y, alive, index_x, index_y):
        self.x = x
        self.y = y
        self.alive = alive
        self.indexX = index_x
        self.indexY = index_y

    def die(self):
        self.alive = False

    def live(self):
        self.alive = True

    def get_index(self):
        return self.indexX, self.indexY

    def update(self):
        grid_temp = grid[self.indexY]
        grid_temp.pop(self.indexY)
        grid_temp.insert(self.indexY, self.alive)

        grid.pop(self.indexY)
        grid.insert(self.indexX, grid_temp)

        adjacent_alive = 0
        for i in cells:
            if i.x == self.x - 30 and i.y == self.y and i.alive:
                adjacent_alive += 1
            elif i.x == self.x + 30 and i.y == self.y and i.alive:
                adjacent_alive += 1
            elif i.x == self.x and i.y == self.y - 30 and i.alive:
                adjacent_alive += 1
            elif i.x == self.x and i.y == self.y + 30 and i.alive:
                adjacent_alive += 1
            elif i.x == self.x - 30 and i.y == self.y - 30 and i.alive:
                adjacent_alive += 1
            elif i.x == self.x - 30 and i.y == self.y + 30 and i.alive:
                adjacent_alive += 1
            elif i.x == self.x + 30 and i.y == self.y - 30 and i.alive:
                adjacent_alive += 1
            elif i.x == self.x + 30 and i.y == self.y + 30 and i.alive:
                adjacent_alive += 1

        if self.alive:
            if adjacent_alive < 2:
                return False
            elif adjacent_alive > 3:
                return False
            else:
                return True
        if not self.alive:
            if adjacent_alive == 3:
                return True
            else:
                return False

    def render(self):
        if self.alive:
            pygame.draw.rect(wn, (0, 0, 0), (self.x, self.y, 30, 30))


# functions
def render_grid():
    for y in range(0, HEIGHT, 30):
        pygame.draw.line(wn, GRID_COLOUR, (0, y), (WIDTH, y))

    for x in range(0, WIDTH, 30):
        pygame.draw.line(wn, GRID_COLOUR, (x, 0), (x, HEIGHT))


def parse_to_x_y(x, y):
    return x * 30, y * 30


def parse_to_index(x, y):
    return int(x / 30), int(y / 30)


indexX = 0
indexY = 0
x_pos = 0
y_pos = 0
for y_ in range(18):
    for x_ in range(32):
        cells.append(Cell(x_pos, y_pos, False, indexX, indexY))
        indexX += 1
        x_pos += 30
    y_pos += 30
    x_pos = 0
    indexY += 1
cells[2].live()
cells[35].live()
cells[65].live()
cells[66].live()
cells[67].live()

# main loop
fps = 1
clock = pygame.time.Clock()
while True:
    # start_time = time.time()

    wn.fill(BG_COLOUR)

    for item in cells:
        item.render()
    render_grid()

    # events loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quit()

    for item in cells:
        if item.update():
            live_queue.append(item)
        else:
            die_queue.append(item)
    for i in live_queue:
        i.live()
    for i in die_queue:
        i.die()
    pygame.display.update()
    clock.tick(fps)
    # end_time = time.time()
    # print(round(1 / (end_time - start_time)), "fps")

問題是你沒有在主循環中重置你的隊列。

所以在添加到隊列之前添加它:

live_queue = []   # <----
die_queue = []    # <----
for item in cells:
    if item.update():
        live_queue.append(item)
    else:
        die_queue.append(item)

其他一些備注

您永遠不會以有用的方式使用gridgrid_temp 甚至你對它們進行的操作也很奇怪。 無論如何,您可以刪除對它們的所有引用。

您永遠不會使用indexXindexY屬性,也不要使用它周圍的方法,也不要使用構造函數的相應參數。 能去的都行。

您應該避免僅僅為了找到一個單元格的(最多)8 個相鄰單元格而掃描所有單元格:這會對性能產生不良影響。

我同意評論者 Rabbid76 的觀點,因為您需要一次更新整個網格,而不是逐個單元格。 這通常是通過使用兩個單獨的網格來完成的,一個“以前的狀態”網格和一個“新狀態網格”。 循環遍歷“新狀態”網格中的每個位置,並使用“先前狀態”網格計算其活動鄰居的數量。 計算完整個“新狀態”網格后,可以將“新狀態”網格復制到“舊狀態”網格。

算法中的另一個致命缺陷是grid = [[False] * 32] * 18 這在 Python 中不會按預期工作 使用此代碼,每一行都是對同一數組的引用。 例如,表達式grid[0] is grid[1]將評估為True 如果將網格中的某個單元格設置為 true,則整列都將設置為 true。 您可以通過以下代碼解決此問題:

grid=[]
for r in range(18):
    row=[]
    for c in range(32):
        row.append(False)
    grid.append(row)

雖然它與錯誤沒有直接關系,但我建議對您的算法進行一些重新設計。 並不是真的需要將每個單元封裝在一個類中; 這樣做會在網格和單元格列表之間創建冗余。 這也會引導您通過像素位置識別單元格(因此ix == self.x - 30子句),這很容易導致錯誤。 我建議改為檢查網格變量中的相鄰索引。 嘗試查看https://www.geeksforgeeks.org/conways-game-life-python-implementation/以獲得一些靈感。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM