无限棋盘:康威生命游戏 - Python
我被分配了一个项目,下面是指示:
生命游戏是在一个无限大的网格上进行的。在第二章中,我们定义了一个固定大小的生命网格,用户可以指定网格的宽度和高度。这个方法足以展示如何用二维数组来实现生命游戏。但一个完整的实现应该支持无限大的网格。请使用类似于稀疏矩阵的方式来实现稀疏生命网格。
老实说,我对这个概念不是很理解。能不能给我一个简单的描述(如果没有简短的代码也可以),让普通人也能明白?我会很感激的。
Sparselifegrid.py
""" My initial GameOfLife code
Feb 27, 2013
Sparse Matrix code specially designed for Game of Life
"""
class SparseLifeGrid:
def __init__(self):
"""
"pass" just allows this to run w/o crashing.
Replace it with your own code in each method.
"""
pass
def minRange(self):
"""
Return the minimum row & column as a list.
"""
pass
def maxRange(self):
"""
Returns the maximum row & column as a list.
"""
pass
def configure(self,coordList):
pass
def clearCell(self,row, col):
pass
def setCell(self,row, col):
pass
def isValidRowCol(val1,val2):
pass
def isLiveCell(self,row, col):
pass
def numLiveNeighbors(self, row,col):
pass
def __getitem__(self,ndxTuple):
pass
def __setitem__(self,ndxTuple, life):
"""
The possible values are only true or false:
True says alive, False for dead.
"""
pass
def _findPosition(self,row,col):
pass
def __repr__(self):
pass
def __str__(self):
"""
This method will only print the non-empty values,
and a row and column outside the non-empty values.
"""
pass
def evolve(self):
"""
Return the next generation state.
"""
pass
def hasOccurred(self):
"""
Check whether this current state has already occured.
If not, return False. If true, return which generation number (1-10).
"""
pass
def __eq__(self,other):
"""
This is good method if we want to compare two sparse matrices.
You can just use sparseMatrixA == sparseMatrixB because of this method.
"""
pass
def printLifeGrid(lifeGrid):
"""
Print a column before and after the live cells
"""
s=""
maxRange=lifeGrid.maxRange()
minRange=lifeGrid.minRange()
for i in range(minRange[0]-1,maxRange[0]+2):
for j in range(minRange[1]-1,maxRange[1]+2):
s+=" "+str(lifeGrid[i,j])
s+="\n"
print(s)
class _GoLMatrixElement:
"""
Storage class for one cell
"""
def __init__(self,row,col):
pass
def __str__self(self):
pass
def __eq__(self,other):
pass
这是我的主文件
""" Marcus Brown's initial GameOfLife code
Feb 27, 2013
"""
from SparseLifeGrid_Key import SparseLifeGrid
import sys
# You'll probably need to add some other stuff like global variables
""" ####################################################
Don't change anything below this line: readPoints or main
""" ####################################################
def readPoints(lifeGrid):
"""
Reads the locations of life and set to the SparseMatrix
"""
print("1. Enter positions of life with row,col format (e.g., 2,3).")
print("2. Enter empty line to stop.")
life=input()
coordList=[]
while life:
points=life.split(",")
try:
coord=[int(points[0]),int(points[1])]
coordList.append(coord)
except ValueError:
print("Ignored input:" + life+ ", row, col not valid numbers")
except:
print("Unexpected error:", sys.exc_info()[0])
print("added, keep entering or enter empty line to stop.")
life=input()
print("Thanks, finished entering live cells")
lifeGrid.configure(coordList)
def main():
"""
Runs for ten generations if a stable (repeating) state is not found.
"""
lifeGrid= SparseLifeGrid()
readPoints(lifeGrid)
lifeGrid.printLifeGrid()
patterns=0
i=0
while i <10 and patterns == 0:
"""
Evolve to the next generation
"""
lifeGrid.evolve()
"""
Check whether this generation is a repetition of any of the
previous states.
If yes return the previous matching generation (1-10).
"""
patterns=lifeGrid.hasOccurred()
if patterns != -1:
break
i+=1
lifeGrid.printLifeGrid()
if i==10:
print("No pattern found")
else:
print("Pattern found at: " + str(i)+ " of type: " + str(patterns))
main()
2 个回答
1
这里有一个简单的基于稀疏矩阵的生命游戏解决方案,使用的是Python 2.x。你可以把大小设置得尽可能大,只要你的系统能处理得了。这个游戏在x和y方向上都是循环的,也就是说,如果你走出边界,会从另一边重新出现。
class Cell():
def __init__(self, x, y, live=True):
self.x, self.y = x, y
self.live = live
self.around = 0
def __eq__(self, other):
return (self.x, self.y) == (other.x, other.y)
def spawn(self):
self.live = True
self.around = 0
return self
class Grid():
def __init__(self, width, height):
self.xMax = width
self.yMax = height
self.cells = []
self.deltas = [(-1, -1), (0, -1), (1, -1), (1, 0),
(1, 1), (0, 1), (-1, 1), (-1, 0)]
def tick(self):
newCells = self.cells[:]
''' create potential new cells '''
for cell in self.cells:
for dx, dy in self.deltas:
newCell = Cell((cell.x+dx)%self.xMax,
(cell.y+dy)%self.yMax, live=False)
if newCell not in newCells:
newCells.append(newCell)
newCells[newCells.index(newCell)].around += 1
''' spawn new cells for next grid '''
self.cells = []
for cell in newCells:
if (cell.live and cell.around in [2, 3]
or not cell.live and cell.around == 3):
self.cells.append(cell.spawn())
def show(self):
for y in range(self.yMax):
print ''.join('X|' if Cell(x, y) in self.cells
else ' |' for x in range(self.xMax))
print
使用方法:
>>> glider = [Cell(2,0), Cell(2,1), Cell(2,2), Cell(1,2), Cell(0,1)]
>>> g = Grid(7, 7)
>>> glider = [Cell(2,0), Cell(2,1), Cell(2,2), Cell(1,2), Cell(0,1)]
>>> g.cells = glider
>>> g.show()
| |X| | | | |
X| |X| | | | |
|X|X| | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
>>> g.tick()
>>> g.tick()
>>> g.show()
| |X| | | | |
| | |X| | | |
|X|X|X| | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
>>> g.tick()
>>> g.tick()
>>> g.show()
| | | | | | |
| | |X| | | |
|X| |X| | | |
| |X|X| | | |
| | | | | | |
| | | | | | |
| | | | | | |
6
稀疏矩阵是一种矩阵的表示方式,它只存储那些不等于默认值(通常是0)的数值所在的位置。用Python来表示这样的矩阵,一个简单的方法是使用字典,字典的键是坐标的元组(x, y)
,而值就是矩阵中的数值。
比如说,这个矩阵:
0 0 0 0
0 0 0 0
0 1 0 0
0 0 0 0
可以用以下方式表示:
matrix = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0]]
sparse_matrix = {(1, 2): 1}
你可以这样访问这些值:
for x in xrange(4):
for y in xrange(4):
assert matrix[y][x] == sparse_matrix.get((x, y), 0)
这些内容应该能帮助你入门。你的练习是要把这样的稀疏矩阵封装在一个类里面,让它的使用方式和传统矩阵一样。
还有更高级的方法来存储这样的稀疏矩阵,每种方法在复杂性、内存使用等方面都有不同的权衡。