我是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'
我在这里看到了几个问题。
首先,您的printNextGrid()
函数与printGrid()
函数完全相同;它打印来自CCD_ 3而不是CCD_。你对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