我正在尝试通过将Cell对象存储到一个集合(必须使用类)来创建一个简单的生命游戏,并且我遇到了无法将单元格对象添加到Set中的问题,因为它是不可用的...有没有办法解决?谢谢!
class Cell():
def __init__(self, row, col):
self.row = row
self.col = col
def getRow(self):
return self.row
def getCol(self):
return self.col
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.__dict__ == other.__dict__
else:
return False
def __ne__(self, other):
return not self.__eq__(other)
class SparseLifeGrid(set):
# Creates a new infinite-sized game grid with all cells set to dead.
def __init__(self):
self.rowList = []
self.colList = []
self.cellSet = set()
def __add__(self, cell):
self.cellSet.add(cell)
self.rowList.append(cell.getRow())
self.colList.append(cell.getCol())
def minRange(self):
#Returns a 2-tuple (minrow, mincol) that contains the minimum
#row index and the minimum
#column index that is currently occupied by a live cell.
#None is returned if there are no alive cells.
return (sorted(self.rowList)[0], sorted(self.rowList)[0])
def maxRange(self):
#Returns a 2-tuple (maxrow, maxcol) that contains the
#maximum row index and the maximum
#column index that is currently occupied by a live cell.
#None is returned if there are no live cells.
return (sorted(self.rowList,reverse = True)[0],\
sorted(self.colList,reverse = True)[0])
def clearCell(self, row, col):
#Clears the individual cell (row, col) and sets it to dead.
#If the cell is already dead, no action is taken.
for item in self:
if item == Cell(row,col):
self.remove(item)
def setCell(self, row, col):
#Sets the indicated cell (row, col) to be alive.
#If the cell is already alive, no action is taken.
self.__add__(Cell(row,col))
def isLiveCell(self, row, col):
#Returns a boolean value indicating if the given
#cell (row, col) contains a live organism.
return Cell(row,col) in self
def numLiveNeighbors(self, row, col):
#checks how many live adjacents (not diagonals I think) a cell has
surround = 0
if self.isLiveCell(row+1,col):
surround += 1
if self.isLiveCell(row-1,col):
surround += 1
if self.isLiveCell(row, col+1):
surround += 1
if self.isLiveCell(row, col-1):
surround += 1
return surround
G = SparseLifeGrid()
G.setCell(2,3)
答案 0 :(得分:0)
您的对象是可变的,并且您尚未实现__hash__()
;但无论如何你真的不想这样做。如果它们存在,您的单元格仅用于表示存活,因此只需在集合中使用元组(row, col)
即可。由于元组是不可变的和可清除的,你可以将它们放在你的集合中。
使用网格和游戏的类和对象,而不是单元格。
答案 1 :(得分:0)
您需要使Cell实例不可变,然后创建始终保持不变的__hash__
方法。如果你不能直接使用元组,这里有一个替代方案(只从tuple
借用一点):
class Cell:
# each cell will have exactly two values, so no need for __dict__
__slots__ = ["row", "col"]
# set up values at construction time using super().__setitem__()
def __init__(self, row, col):
super().__setitem__("row", row)
super().__setitem__("col", col)
return self
# a Cell is intended to be immutable, so __setattr__ always raises an error
def __setattr__(self, name, value):
if hasattr(self, name):
raise AttributeError("{!r} object attribute {!r} is read-only"
.format(self.__class__.__name__, name))
else:
raise AttributeError("{!r} object has no attribute {!r}"
.format(self.__class__.__name__, name))
# comparison operators
def __eq__(self, other):
return (isinstance(other, Cell) and
self.row == other.row and
self.col == other.col)
def __ne__(self, other):
return not self == other
# hash function, with a value borrowed from a tuple
def __hash__(self):
return hash((self.row, self.col))
这是相当多的工作,但相当于:
Cell = collections.namedtuple(["row", "col"])
您的网格类也存在一些问题。例如,你覆盖__add__
,它用于实现加法运算符,但你不返回任何东西,所以它不会像预期的那样工作。我怀疑你的意思是覆盖add
方法(没有下划线)。但是,如果是这种情况,如果您希望网格实际上作为一个集合运行,那么您需要确保使用适当的参数调用super().add()
。
此外,min(lst)
应该比sorted(lst)[0]
(O(N)而不是O(N log N))快得多。