Бесконечная доска: игра жизни Конвея - Python

Мне был назначен этот проект с инструкциями ниже:

Игра «Жизнь» определена для сетки бесконечного размера. В главе 2 мы определили АТД Life Grid для использования сетки фиксированного размера, в которой пользователь задавал ширину и высоту сетки. Этого было достаточно в качестве иллюстрации использования двумерного массива для реализации игры «Жизнь». Но полная реализация должна допускать сетку бесконечного размера. Реализуйте АТД Sparse Life Grid, используя подход, аналогичный тому, который использовался для реализации разреженной матрицы.

Честно говоря, я не очень хорошо понимаю эту концепцию. Не могли бы вы дать мне краткое описание (если не краткий код), которое может понять неспециалист? Я буду признателен.

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()

person Jared Beach    schedule 08.03.2013    source источник
comment
В чем ваша настоящая проблема? Имейте в виду, что здесь мы можем помочь вам с практическими вопросами кода, а не с теорией CS или обзорами кода. Для этого у нас есть другие сайты в сети SE.   -  person Martijn Pieters    schedule 08.03.2013
comment
Вы понимаете, что такое разреженная матрица или как ее можно представить?   -  person NPE    schedule 08.03.2013


Ответы (2)


Разреженная матрица — это представление матрицы, в которой в памяти хранятся только местоположения значений, не равных значениям по умолчанию (обычно 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)

Этого должно быть достаточно, чтобы вы начали. Ваше упражнение требует, чтобы вы обернули такую ​​разреженную матрицу в класс, который даст ей тот же интерфейс, что и традиционная матрица.

Есть более продвинутый способ хранения такой разреженной матрицы, каждый из которых обеспечивает различный компромисс между сложностью, использование памяти, ...

person Sylvain Defresne    schedule 08.03.2013
comment
Спасибо за помощь. Наверное, я думал, что знаю, что такое разреженная матрица, но я этого не знал. Могу я попросить вас о помощи, если я застряну? - person Jared Beach; 08.03.2013

Вот простое решение для игры в жизнь на основе разреженных матриц в 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| | | |
 | | | | | | |
 | | | | | | |
 | | | | | | |
person dansalmo    schedule 09.01.2014