Python - 康威的生命游戏 - 不会更新到下一个周期

时间:2016-01-08 03:36:12

标签: python conways-game-of-life

我是python的新手,来自Java和C#。我在Java中有一个工作实现,但是当我尝试用Python编写它时,网格将不会更新到下一个周期。我认为问题不在于深度复制。可以重新分配数组元素吗?

import copy

liveSymbol = "X"
deadSymbol = "-"

class Cell:
    def __init__(self, live, symbol, row, column):
        self.live = live
        self.symbol = symbol
        self.row = row
        self.column = column

    def __repr__(self):
        return repr(self.symbol)

class Model:
    def __init__(self, rows, columns):
        self.grid = []
        self.nextGrid = []
        self.rows = rows
        self.columns = columns

        self.initGrids()
        self.addPatternToGrid()
    def initGrids(self):
        for i in range(self.rows):
            self.grid.append([])
            self.nextGrid.append([])
            for j in range(self.columns):
                cell = Cell(False, deadSymbol, i, j)
                self.grid[i].append(cell)
                self.nextGrid[i].append(cell)

    def addPatternToGrid(self):
        self.grid[1][2] = Cell(True, liveSymbol, 1, 2)
        self.grid[2][2] = Cell(True, liveSymbol, 2, 2)
        self.grid[3][2] = Cell(True, liveSymbol, 3, 2)

    def printGrid(self):
        print("GRID")
        print("\n______________________", end=" ")
        for i in range(self.rows):
            print("")
            for j in range(self.columns):
                print(self.grid[i][j], end=" ")

    def printNextGrid(self):
        print("Next Grid")
        print("\n______________________", end=" ")
        for i in range(self.rows):
            print("")
            for j in range(self.columns):
                print(self.grid[i][j], end=" ")

    def start(self):
        for i in range(self.rows):
            for j in range(self.columns):
                willLive = self.aliveNextCycle(self.grid[i][j])
                symbol = self.getSymbol(willLive)
                self.nextGrid[i][j] = Cell(willLive, symbol, i, j)

        print("Before update grid to next cycle")
        self.printGrid()
        self.printNextGrid()

        self.updateGridToNextCycle()

        print("After update grid to next cycle")
        self.printGrid()
        self.printNextGrid()

    def getSymbol(self, isLive):
        return liveSymbol if True else deadSymbol

    def aliveNextCycle(self, cell):
        liveNeighbors = self.countTheLiveNeighbors(cell)
        if cell.live:
            live = not (liveNeighbors < 2 or liveNeighbors > 3)
            return not live
        else:
            lives = liveNeighbors==3
            return lives

    def updateGridToNextCycle(self):
        # for i in range(self.rows):
        #     for j in range(self.columns):
        #         self.grid[i][j] = self.nextGrid[i][j]
        self.grid = copy.deepcopy(self.nextGrid)

    def countTheLiveNeighbors(self, cell):
        count = 0
        # Directly Left
        if cell.column != 0:
            if self.grid[cell.row][cell.column - 1].live:
                count += 1
            # Upper Left
        if cell.row != 0 and cell.column != 0:
            if self.grid[cell.row - 1][cell.column - 1].live:
                count += 1
            # Directly above
        if cell.row != 0:
            if self.grid[cell.row - 1][cell.column].live:
                count += 1
            # Above right
        if cell.row != 0 and cell.column != self.columns - 1:
            if self.grid[cell.row - 1][cell.column + 1].live:
                count += 1
            # Directly right
        if cell.column != self.columns - 1:
            if self.grid[cell.row][cell.column + 1].live:
                count += 1
            # Right under
        if cell.row != self.rows - 1 and cell.column != self.columns - 1:
            if self.grid[cell.row + 1][cell.column + 1].live:
                count += 1
            # Directly beneath
        if cell.row != self.rows - 1:
            if self.grid[cell.row + 1][cell.column].live:
                count += 1
            # Down left
        if cell.row != self.rows - 1 and cell.column != 0:
            if self.grid[cell.row + 1][cell.column - 1].live:
                count += 1
        return count

model = Model(5, 5)
model.start()

以下是输出

Before update grid to next cycle
GRID

______________________ 
'-' '-' '-' '-' '-' 
'-' '-' 'X' '-' '-' 
'-' '-' 'X' '-' '-' 
'-' '-' 'X' '-' '-' 
'-' '-' '-' '-' '-' Next Grid

______________________ 
'-' '-' '-' '-' '-' 
'-' '-' 'X' '-' '-' 
'-' '-' 'X' '-' '-' 
'-' '-' 'X' '-' '-' 
'-' '-' '-' '-' '-' After update grid to next cycle
GRID

______________________ 
'X' 'X' 'X' 'X' 'X' 
'X' 'X' 'X' 'X' 'X' 
'X' 'X' 'X' 'X' 'X' 
'X' 'X' 'X' 'X' 'X' 
'X' 'X' 'X' 'X' 'X' Next Grid

______________________ 
'X' 'X' 'X' 'X' 'X' 
'X' 'X' 'X' 'X' 'X' 
'X' 'X' 'X' 'X' 'X' 
'X' 'X' 'X' 'X' 'X' 
'X' 'X' 'X' 'X' 'X' 

1 个答案:

答案 0 :(得分:1)

我在这里看到了几个问题。

首先,您的printNextGrid()功能与printGrid()完全相同;它会打印self.grid而不是self.nextGrid的数据。您对copy.deepcopy的使用完全没问题。

其次,您在Cell对象中嵌入了太多信息。每个单元只需跟踪自己的状态;它也不需要单独存储用于其当前状态的符号及其位置。 (说实话,并不清楚这需要成为一个对象;我强烈建议您将TrueFalse存储在网格中而不是对象中。这将使你的代码更简单。)

但至关重要的是,getSymbol()aliveNextCycle()的实施方式不正确。第一:

def getSymbol(self, isLive):
    return liveSymbol if True else deadSymbol
                      ^^^^^^^

True永远是真的。您想要的条件是isLive

第二

def aliveNextCycle(self, cell):
    liveNeighbors = self.countTheLiveNeighbors(cell)
    if cell.live:
        live = not (liveNeighbors < 2 or liveNeighbors > 3)
        return not live
    else:
        lives = liveNeighbors==3
        return lives

cell.live案例的逻辑过于复杂,最终会颠倒生存条件,造成不正确的行为。一个更简单(和正确的)实现将是:

def aliveNextCycle(self, cell):
    liveNeighbors = self.countTheLiveNeighbors(cell)
    if liveNeighbors == 3: return True
    if liveNeighbors == 2: return cell.live
    return False