2012-10-25 28 views
1

我試圖通過將Cell對象存儲到一個集合(必須使用類)來創建一個簡單的生命遊戲,並且我遇到了無法將該單元格對象添加到集合中的問題,因爲它是不可能的...有沒有辦法解決這個問題?謝謝!LIfe Hashing Python的遊戲

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) 
+4

[你爲什麼創建getters?](http://archive.org/details/SeanKellyRecoveryfromAddiction) –

回答

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))快得多。

0

你的對象是可變的,你還沒有實現__hash__();但是你不想那麼做。你的細胞只在那裏表明它們是否存在,所以只需在你的集合中使用一個元組(row, col)。由於元組是不可變的且可散列的,因此可以將它們放入您的集合中。

使用網格和遊戲的類和對象,而不是單元格。

+0

感謝您的快速回答,但我不允許在我的設置中使用元組作爲單元格 – user1775641

+0

我會非常想做'class Cell(tuple):pass' ...;)或者一個命名的元組;但實際上,元組與其他元素一樣多。 – retracile