您的位置:首页 > 理论基础 > 数据结构算法

python数据结构学习笔记-2016-10-15-02-生命游戏

2016-10-15 11:57 751 查看
        2.5 生命游戏

        生命游戏由英国数学及John H.Conway设计,是一个零人游戏。

        2.5.1 游戏规则

        这个游戏使用一张无限大的直角坐标网格,每一个网格可以由一个细胞占据,当一个网格被细胞占据,称为活的(alive),而空网格被称为死的(dead),也可以以活细胞和死细胞称呼。

        游戏的每一轮称为一代(generation),根据每个网格细胞的当前形态(configuration),决定下一代中网格细胞的形态。

 当一个网格细胞是活的,并且周围有2~3个邻居(活细胞)时,其在下一代中是活的,注意周围是指水平、竖直和对角线相邻的网格;
 当一个网格细胞是活的,并且周围有0~1个邻居时,其在下一代中变成死的;
 当一个网格细胞是活的,并且周围有4~5个邻居时,其在下一代中变成死的;
 当一个网格细胞是死的,并且周围有3个邻居时,其在下一代中变成活的,其余所有死细胞在下一代中,仍是死的。

        这一游戏的最终结果依据于初始状态和世代数,大部分结果是所有细胞都会死去,但也有一些有趣的情况。

        稳态:



         两相振荡:



         
       2.5.2 设计一个解决方法
       本游戏需要创建一个生命网格ADT,来记录每一代的网格细胞的状态。这一ADT,应包含如下方法:

LifeGrid(nrows, ncols):创建生命网格实例,行数是nrows,列数是ncols,所有网格被初始化为死的状态;
numRows():返回行数;
numCols():返回列数;
configure(coordList):设定本世代中网格细胞的状态,将一系列给定坐标的网格设定为活细胞状态,而coordList是由多个含两个数值的元组组成,其余网格为死细胞状态;
clearCell(row, col):将给定坐标的网格细胞设定为死细胞;
setCell(row, col):将给定坐标的网格细胞设定为活细胞;
isLiveCell(row, col):判断给定坐标的网格细胞的状态,False为死细胞,True为活细胞;
numLiveNeighbors(row, col):计算给定坐标周围活细胞数,特殊情况是考虑在网格边缘处周围活细胞数统计。
#-*-coding: utf-8-*-

# 生命游戏程序

from life import LifeGrid

# 网格大小
GRID_WIDTH = int(raw_input("Please enter a positive integer as width: "))
GRID_HEIGHT = int(raw_input("Please enter a positive integer as height: "))

# 初始状态
INIT_CONFIG = [(0, 0), (0, 1), (1, 0), (1, 2), (3, 2), (3, 4), (5, 4), (5, 6), (7, 6), (7, 8), (9, 8), (9, 10), (11, 10), (11, 12), (12, 11), (12, 12)]

# 世代数
NUM_GENS = int(raw_input("Please enter a positive integer as generation: "))

# 产生下一代的生命
def evolve(grid):
# 储存下一代活细胞的列表
liveCells = list()

# 遍历整个网格
for i in range(grid.numRows()):
for j in range(grid.numCols()):
# 读取周围活细胞数
neighbors = grid.numLiveNeighbors(i, j)

# 如果该坐标有活细胞,并且周围活细胞数是2或3,将该坐标加入到下一代活细胞的列表
if (neighbors == 2 and grid.isLiveCell(i, j)) or (neighbors == 3):
liveCells.append((i, j))

# 使用下一代活细胞的列表去初始化网格
grid.configure(liveCells)

# 打印一个基于文本表示的生命游戏
def draw(grid):
for i in range(grid.numRows()):
string = ''
for j in range(grid.numCols()):
if grid.isLiveCell(i, j):
string += '@  '
else:
string += '.  '
print string
print '\n'

def main():
# 构建游戏网格,并初始化
grid = LifeGrid(GRID_WIDTH, GRID_HEIGHT)
grid.configure(INIT_CONFIG)

# 游戏开始
draw(grid)
# for i in INIT_CONFIG:
# print grid.numLiveNeighbors(*i)
for i in range(NUM_GENS):
evolve(grid)
draw(grid)

if __name__ == "__main__":
main()
       draw()函数是打印当前网格状态,而evolve()是产生下一代的网格状态。



         2.5.3 实现
#-*-coding: utf-8-*-

# 实现LifeGrid ADT

from myarray2d import Array2D

class LifeGrid(object):
# 定义代表细胞状态的常量
DEAD_CELL = 0
LIVE_CELL = 1

# 创建游戏网格实例,并将所有细胞设定为死细胞状态
def __init__(self, numRows, numCols):
# 创建网格实例
self._grid = Array2D(numRows, numCols)
# 将所有细胞设定为死细胞状态
self.configure(list())

def numRows(self):
return self._grid.numRows()

def numCols(self):
return self._grid.numCols()

# 将给定网格坐标的细胞设为活细胞,网格坐标由列表传入
def configure(self, coordList):
# 先将所有网格中的细胞设为死细胞
for i in range(self.numRows()):
for j in range(self.numCols()):
self.clearCell(i, j)

# 再将给定网格坐标的细胞设为活细胞
for coord in coordList:
self.setCell(coord[0], coord[1])

# 判断给定网格坐标中的细胞状态
def isLiveCell(self, row, col):
return self._grid[row, col] == LifeGrid.LIVE_CELL

def clearCell(self, row, col):
self._grid[row, col] = LifeGrid.DEAD_CELL

def setCell(self, row, col):
self._grid[row, col] = LifeGrid.LIVE_CELL

# 计算给定网格周围活细胞数
def numLiveNeighbors(self, row, col):
count = -1 if self.isLiveCell(row, col) else 0
for r in range(row-1, row+2):
for c in range(col-1, col+2):
try:
if self.isLiveCell(r, c):
count += 1
except AssertionError, e:
continue
return count


        
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息