我是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'
答案 0 :(得分:1)
我在这里看到了几个问题。
首先,您的printNextGrid()
功能与printGrid()
完全相同;它会打印self.grid
而不是self.nextGrid
的数据。您对copy.deepcopy
的使用完全没问题。
其次,您在Cell
对象中嵌入了太多信息。每个单元只需跟踪自己的状态;它也不需要单独存储用于其当前状态的符号及其位置。 (说实话,并不清楚这需要成为一个对象;我强烈建议您将True
和False
存储在网格中而不是对象中。这将使你的代码更简单。)
但至关重要的是,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