Conway's Game of Life implemented in Python

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
10
down vote

favorite












I'm a Python novice and decided to give Game of Life a try in Python 3:



import os
import time
import curses

class Cell:
newlabel = ''
def __init__(self,row,col,label):
self.row = row
self.col = col
self.label = label

def updatecell(self,celllist, boardsize):
liveneighbours = self.getliveneighbours(celllist, boardsize)
if liveneighbours < 2 or liveneighbours > 3: #Kills cell if it has <2 or >3 neighbours
self.newlabel = ' '
elif liveneighbours == 2 and self.label == ' ': #Cell doesn't come alive if it is dead and only has 2 neighbours
self.newlabel = ' '
else: #Cell comes alive if it is already alive and has 2/3 neighbours or if it is dead and has 3 neighbours
self.newlabel = 0

def getliveneighbours(self,celllist,boardsize):
count = 0
for row in range(self.row-1,self.row+2):
try:
celllist[row]
except: #Handles vertical wrapping. If there's an error, it checks the wrapped cell
if row < 0:
row += boardsize[0]
else:
row -= boardsize[0]
for col in range(self.col-1,self.col+2):
try: #Handles horizontal wrapping. If there's an error, it checks the wrapped cell
celllist[row][col]
except:
if col < 0:
col += boardsize[1]
else:
col -= boardsize[1]
if not celllist[row][col].label:
count += 1
if not self.label: #Subtracts the cell from the neighbours count
return count-1
else:
return count

def updatelabel(self): #Updates the cell's label after all cell updates have been processes
self.label = self.newlabel


class Board:
celllist = #Dict of rows
def __init__(self, rows, columns):
self.rows = rows
self.columns = columns
self.generate()

def printboard(self): #Prints the board to the terminal using curses
for num, row in self.celllist.items():
line = ''
for col, cell in enumerate(row):
line += str(cell.label)
terminal.addstr(num, 0, line)
terminal.refresh()

def generate(self): #Adds all the cells to the board
for row in range(self.rows-1):
self.celllist[row] =
for col in range(self.columns):
self.celllist[row].append(Cell(row,col,' '))

def updateboard(self): #Prompts each cell to update and then update their label
for row in self.celllist:
for cell in self.celllist[row]:
cell.updatecell(self.celllist, (self.rows-1, self.columns))
for row in self.celllist:
for cell in self.celllist[row]:
cell.updatelabel()

if __name__ == "__main__":
terminal = curses.initscr() # Opens a curses window
curses.noecho()
curses.cbreak()
terminal.nodelay(1) #Don't wait for user input later
rows, columns = os.popen('stty size', 'r').read().split()
board = Board(int(rows), int(columns))
board.celllist[6][8].label = 0
board.celllist[7][9].label = 0
board.celllist[7][10].label = 0
board.celllist[8][8].label = 0
board.celllist[8][9].label = 0
while 1:
board.printboard()
time.sleep(0.1)
board.updateboard()
char = terminal.getch()
if char == 113: #Checks for ASCII Char code for q and then breaks loop
break
curses.endwin() #Closes curses window


I've written it to work based on your terminal size and I've made the sides wrap around because it was the only solution I could think of. Also, at the end, I've included a glider example as a test.



Questions:



  1. Is my implementation pythonic enough (particularly concerning ranges and my constant use of iteration)?


  2. Are the data structures that I've used for the celllist (arrays in a dict) suitable?


  3. Is curses a good way of displaying the game? Would pyGame be better?


  4. Is the overall code style good?


  5. To further develop this, is there a better algorithm I could implement or a better method (other than wrapping the sides) of displaying all the cells?







share|improve this question



























    up vote
    10
    down vote

    favorite












    I'm a Python novice and decided to give Game of Life a try in Python 3:



    import os
    import time
    import curses

    class Cell:
    newlabel = ''
    def __init__(self,row,col,label):
    self.row = row
    self.col = col
    self.label = label

    def updatecell(self,celllist, boardsize):
    liveneighbours = self.getliveneighbours(celllist, boardsize)
    if liveneighbours < 2 or liveneighbours > 3: #Kills cell if it has <2 or >3 neighbours
    self.newlabel = ' '
    elif liveneighbours == 2 and self.label == ' ': #Cell doesn't come alive if it is dead and only has 2 neighbours
    self.newlabel = ' '
    else: #Cell comes alive if it is already alive and has 2/3 neighbours or if it is dead and has 3 neighbours
    self.newlabel = 0

    def getliveneighbours(self,celllist,boardsize):
    count = 0
    for row in range(self.row-1,self.row+2):
    try:
    celllist[row]
    except: #Handles vertical wrapping. If there's an error, it checks the wrapped cell
    if row < 0:
    row += boardsize[0]
    else:
    row -= boardsize[0]
    for col in range(self.col-1,self.col+2):
    try: #Handles horizontal wrapping. If there's an error, it checks the wrapped cell
    celllist[row][col]
    except:
    if col < 0:
    col += boardsize[1]
    else:
    col -= boardsize[1]
    if not celllist[row][col].label:
    count += 1
    if not self.label: #Subtracts the cell from the neighbours count
    return count-1
    else:
    return count

    def updatelabel(self): #Updates the cell's label after all cell updates have been processes
    self.label = self.newlabel


    class Board:
    celllist = #Dict of rows
    def __init__(self, rows, columns):
    self.rows = rows
    self.columns = columns
    self.generate()

    def printboard(self): #Prints the board to the terminal using curses
    for num, row in self.celllist.items():
    line = ''
    for col, cell in enumerate(row):
    line += str(cell.label)
    terminal.addstr(num, 0, line)
    terminal.refresh()

    def generate(self): #Adds all the cells to the board
    for row in range(self.rows-1):
    self.celllist[row] =
    for col in range(self.columns):
    self.celllist[row].append(Cell(row,col,' '))

    def updateboard(self): #Prompts each cell to update and then update their label
    for row in self.celllist:
    for cell in self.celllist[row]:
    cell.updatecell(self.celllist, (self.rows-1, self.columns))
    for row in self.celllist:
    for cell in self.celllist[row]:
    cell.updatelabel()

    if __name__ == "__main__":
    terminal = curses.initscr() # Opens a curses window
    curses.noecho()
    curses.cbreak()
    terminal.nodelay(1) #Don't wait for user input later
    rows, columns = os.popen('stty size', 'r').read().split()
    board = Board(int(rows), int(columns))
    board.celllist[6][8].label = 0
    board.celllist[7][9].label = 0
    board.celllist[7][10].label = 0
    board.celllist[8][8].label = 0
    board.celllist[8][9].label = 0
    while 1:
    board.printboard()
    time.sleep(0.1)
    board.updateboard()
    char = terminal.getch()
    if char == 113: #Checks for ASCII Char code for q and then breaks loop
    break
    curses.endwin() #Closes curses window


    I've written it to work based on your terminal size and I've made the sides wrap around because it was the only solution I could think of. Also, at the end, I've included a glider example as a test.



    Questions:



    1. Is my implementation pythonic enough (particularly concerning ranges and my constant use of iteration)?


    2. Are the data structures that I've used for the celllist (arrays in a dict) suitable?


    3. Is curses a good way of displaying the game? Would pyGame be better?


    4. Is the overall code style good?


    5. To further develop this, is there a better algorithm I could implement or a better method (other than wrapping the sides) of displaying all the cells?







    share|improve this question























      up vote
      10
      down vote

      favorite









      up vote
      10
      down vote

      favorite











      I'm a Python novice and decided to give Game of Life a try in Python 3:



      import os
      import time
      import curses

      class Cell:
      newlabel = ''
      def __init__(self,row,col,label):
      self.row = row
      self.col = col
      self.label = label

      def updatecell(self,celllist, boardsize):
      liveneighbours = self.getliveneighbours(celllist, boardsize)
      if liveneighbours < 2 or liveneighbours > 3: #Kills cell if it has <2 or >3 neighbours
      self.newlabel = ' '
      elif liveneighbours == 2 and self.label == ' ': #Cell doesn't come alive if it is dead and only has 2 neighbours
      self.newlabel = ' '
      else: #Cell comes alive if it is already alive and has 2/3 neighbours or if it is dead and has 3 neighbours
      self.newlabel = 0

      def getliveneighbours(self,celllist,boardsize):
      count = 0
      for row in range(self.row-1,self.row+2):
      try:
      celllist[row]
      except: #Handles vertical wrapping. If there's an error, it checks the wrapped cell
      if row < 0:
      row += boardsize[0]
      else:
      row -= boardsize[0]
      for col in range(self.col-1,self.col+2):
      try: #Handles horizontal wrapping. If there's an error, it checks the wrapped cell
      celllist[row][col]
      except:
      if col < 0:
      col += boardsize[1]
      else:
      col -= boardsize[1]
      if not celllist[row][col].label:
      count += 1
      if not self.label: #Subtracts the cell from the neighbours count
      return count-1
      else:
      return count

      def updatelabel(self): #Updates the cell's label after all cell updates have been processes
      self.label = self.newlabel


      class Board:
      celllist = #Dict of rows
      def __init__(self, rows, columns):
      self.rows = rows
      self.columns = columns
      self.generate()

      def printboard(self): #Prints the board to the terminal using curses
      for num, row in self.celllist.items():
      line = ''
      for col, cell in enumerate(row):
      line += str(cell.label)
      terminal.addstr(num, 0, line)
      terminal.refresh()

      def generate(self): #Adds all the cells to the board
      for row in range(self.rows-1):
      self.celllist[row] =
      for col in range(self.columns):
      self.celllist[row].append(Cell(row,col,' '))

      def updateboard(self): #Prompts each cell to update and then update their label
      for row in self.celllist:
      for cell in self.celllist[row]:
      cell.updatecell(self.celllist, (self.rows-1, self.columns))
      for row in self.celllist:
      for cell in self.celllist[row]:
      cell.updatelabel()

      if __name__ == "__main__":
      terminal = curses.initscr() # Opens a curses window
      curses.noecho()
      curses.cbreak()
      terminal.nodelay(1) #Don't wait for user input later
      rows, columns = os.popen('stty size', 'r').read().split()
      board = Board(int(rows), int(columns))
      board.celllist[6][8].label = 0
      board.celllist[7][9].label = 0
      board.celllist[7][10].label = 0
      board.celllist[8][8].label = 0
      board.celllist[8][9].label = 0
      while 1:
      board.printboard()
      time.sleep(0.1)
      board.updateboard()
      char = terminal.getch()
      if char == 113: #Checks for ASCII Char code for q and then breaks loop
      break
      curses.endwin() #Closes curses window


      I've written it to work based on your terminal size and I've made the sides wrap around because it was the only solution I could think of. Also, at the end, I've included a glider example as a test.



      Questions:



      1. Is my implementation pythonic enough (particularly concerning ranges and my constant use of iteration)?


      2. Are the data structures that I've used for the celllist (arrays in a dict) suitable?


      3. Is curses a good way of displaying the game? Would pyGame be better?


      4. Is the overall code style good?


      5. To further develop this, is there a better algorithm I could implement or a better method (other than wrapping the sides) of displaying all the cells?







      share|improve this question













      I'm a Python novice and decided to give Game of Life a try in Python 3:



      import os
      import time
      import curses

      class Cell:
      newlabel = ''
      def __init__(self,row,col,label):
      self.row = row
      self.col = col
      self.label = label

      def updatecell(self,celllist, boardsize):
      liveneighbours = self.getliveneighbours(celllist, boardsize)
      if liveneighbours < 2 or liveneighbours > 3: #Kills cell if it has <2 or >3 neighbours
      self.newlabel = ' '
      elif liveneighbours == 2 and self.label == ' ': #Cell doesn't come alive if it is dead and only has 2 neighbours
      self.newlabel = ' '
      else: #Cell comes alive if it is already alive and has 2/3 neighbours or if it is dead and has 3 neighbours
      self.newlabel = 0

      def getliveneighbours(self,celllist,boardsize):
      count = 0
      for row in range(self.row-1,self.row+2):
      try:
      celllist[row]
      except: #Handles vertical wrapping. If there's an error, it checks the wrapped cell
      if row < 0:
      row += boardsize[0]
      else:
      row -= boardsize[0]
      for col in range(self.col-1,self.col+2):
      try: #Handles horizontal wrapping. If there's an error, it checks the wrapped cell
      celllist[row][col]
      except:
      if col < 0:
      col += boardsize[1]
      else:
      col -= boardsize[1]
      if not celllist[row][col].label:
      count += 1
      if not self.label: #Subtracts the cell from the neighbours count
      return count-1
      else:
      return count

      def updatelabel(self): #Updates the cell's label after all cell updates have been processes
      self.label = self.newlabel


      class Board:
      celllist = #Dict of rows
      def __init__(self, rows, columns):
      self.rows = rows
      self.columns = columns
      self.generate()

      def printboard(self): #Prints the board to the terminal using curses
      for num, row in self.celllist.items():
      line = ''
      for col, cell in enumerate(row):
      line += str(cell.label)
      terminal.addstr(num, 0, line)
      terminal.refresh()

      def generate(self): #Adds all the cells to the board
      for row in range(self.rows-1):
      self.celllist[row] =
      for col in range(self.columns):
      self.celllist[row].append(Cell(row,col,' '))

      def updateboard(self): #Prompts each cell to update and then update their label
      for row in self.celllist:
      for cell in self.celllist[row]:
      cell.updatecell(self.celllist, (self.rows-1, self.columns))
      for row in self.celllist:
      for cell in self.celllist[row]:
      cell.updatelabel()

      if __name__ == "__main__":
      terminal = curses.initscr() # Opens a curses window
      curses.noecho()
      curses.cbreak()
      terminal.nodelay(1) #Don't wait for user input later
      rows, columns = os.popen('stty size', 'r').read().split()
      board = Board(int(rows), int(columns))
      board.celllist[6][8].label = 0
      board.celllist[7][9].label = 0
      board.celllist[7][10].label = 0
      board.celllist[8][8].label = 0
      board.celllist[8][9].label = 0
      while 1:
      board.printboard()
      time.sleep(0.1)
      board.updateboard()
      char = terminal.getch()
      if char == 113: #Checks for ASCII Char code for q and then breaks loop
      break
      curses.endwin() #Closes curses window


      I've written it to work based on your terminal size and I've made the sides wrap around because it was the only solution I could think of. Also, at the end, I've included a glider example as a test.



      Questions:



      1. Is my implementation pythonic enough (particularly concerning ranges and my constant use of iteration)?


      2. Are the data structures that I've used for the celllist (arrays in a dict) suitable?


      3. Is curses a good way of displaying the game? Would pyGame be better?


      4. Is the overall code style good?


      5. To further develop this, is there a better algorithm I could implement or a better method (other than wrapping the sides) of displaying all the cells?









      share|improve this question












      share|improve this question




      share|improve this question








      edited Apr 3 at 1:55









      Jamal♦

      30.1k11114225




      30.1k11114225









      asked Apr 3 at 1:50









      HydraulicSheep

      535




      535




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          5
          down vote



          accepted










          1. Running your code through pycodestyle will highlight some issues to make the code more familiar to Pythonistas. Other than that:


            • while 1 should be written as while True (Explicit is better than implicit)

            • Rather than checking for a specific character to quit I would just assume that people know about Ctrl-c

            • Use as easily readable names as possible. updatecell, for example, could be update_cell or even update since it's implicit that it's the Cell that's being updated.

            • Usually if __name__ == "__main__": is followed by simply main() or sys.exit(main()) (probably not relevant in your case). This makes the code more testable. Aim to minimize the amount of top-level code in general.


          2. The board is really a matrix, so it would IMO be better to represent it using a list of lists or ideally a matrix class. A dict has no intrinsic order, so semantically it's the wrong thing to use in any case.

          3. Somebody else will have to answer this.

          4. This is too subjective to answer.

          5. Some suggestions:

            • Try to take into account the fact that the Game of Life board is infinite in all directions. Ideally your implementation should handle this, but you could also use it as a stop condition - when things get too close to the edge to be able to figure out the next step with certainty the program could stop.

            • You can avoid conversions between numbers and strings by using numbers or even booleans everywhere (for example stored in a value or state field rather than label). You can then write a separate method to display a Board, converting values to whatever pair of characters you want, and possibly with decorations.

            • Rather than updating Cells individually by saving their new value you can replace the entire Board with a new one at each step.

            • The time.sleep() currently does not take into account that the Board update time might change. This is unlikely to be a problem for a small board, but if you want completely smooth frames you'll want to either use threads or a tight loop which checks whether it's time to print the current Board yet.






          share|improve this answer























          • Thanks! How would I do this: "Rather than updating Cells individually by saving their new value you can replace the entire Board with a new one at each step." ?
            – HydraulicSheep
            Apr 3 at 5:02







          • 1




            You currently populate the newlabel field and then updatelabel once all the Cells are processed. You can avoid re-entering each Cell by creating the new Board based on the current Board, conceptually replacing newlabel with newboard.
            – l0b0
            Apr 3 at 6:18










          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191111%2fconways-game-of-life-implemented-in-python%23new-answer', 'question_page');

          );

          Post as a guest






























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          5
          down vote



          accepted










          1. Running your code through pycodestyle will highlight some issues to make the code more familiar to Pythonistas. Other than that:


            • while 1 should be written as while True (Explicit is better than implicit)

            • Rather than checking for a specific character to quit I would just assume that people know about Ctrl-c

            • Use as easily readable names as possible. updatecell, for example, could be update_cell or even update since it's implicit that it's the Cell that's being updated.

            • Usually if __name__ == "__main__": is followed by simply main() or sys.exit(main()) (probably not relevant in your case). This makes the code more testable. Aim to minimize the amount of top-level code in general.


          2. The board is really a matrix, so it would IMO be better to represent it using a list of lists or ideally a matrix class. A dict has no intrinsic order, so semantically it's the wrong thing to use in any case.

          3. Somebody else will have to answer this.

          4. This is too subjective to answer.

          5. Some suggestions:

            • Try to take into account the fact that the Game of Life board is infinite in all directions. Ideally your implementation should handle this, but you could also use it as a stop condition - when things get too close to the edge to be able to figure out the next step with certainty the program could stop.

            • You can avoid conversions between numbers and strings by using numbers or even booleans everywhere (for example stored in a value or state field rather than label). You can then write a separate method to display a Board, converting values to whatever pair of characters you want, and possibly with decorations.

            • Rather than updating Cells individually by saving their new value you can replace the entire Board with a new one at each step.

            • The time.sleep() currently does not take into account that the Board update time might change. This is unlikely to be a problem for a small board, but if you want completely smooth frames you'll want to either use threads or a tight loop which checks whether it's time to print the current Board yet.






          share|improve this answer























          • Thanks! How would I do this: "Rather than updating Cells individually by saving their new value you can replace the entire Board with a new one at each step." ?
            – HydraulicSheep
            Apr 3 at 5:02







          • 1




            You currently populate the newlabel field and then updatelabel once all the Cells are processed. You can avoid re-entering each Cell by creating the new Board based on the current Board, conceptually replacing newlabel with newboard.
            – l0b0
            Apr 3 at 6:18














          up vote
          5
          down vote



          accepted










          1. Running your code through pycodestyle will highlight some issues to make the code more familiar to Pythonistas. Other than that:


            • while 1 should be written as while True (Explicit is better than implicit)

            • Rather than checking for a specific character to quit I would just assume that people know about Ctrl-c

            • Use as easily readable names as possible. updatecell, for example, could be update_cell or even update since it's implicit that it's the Cell that's being updated.

            • Usually if __name__ == "__main__": is followed by simply main() or sys.exit(main()) (probably not relevant in your case). This makes the code more testable. Aim to minimize the amount of top-level code in general.


          2. The board is really a matrix, so it would IMO be better to represent it using a list of lists or ideally a matrix class. A dict has no intrinsic order, so semantically it's the wrong thing to use in any case.

          3. Somebody else will have to answer this.

          4. This is too subjective to answer.

          5. Some suggestions:

            • Try to take into account the fact that the Game of Life board is infinite in all directions. Ideally your implementation should handle this, but you could also use it as a stop condition - when things get too close to the edge to be able to figure out the next step with certainty the program could stop.

            • You can avoid conversions between numbers and strings by using numbers or even booleans everywhere (for example stored in a value or state field rather than label). You can then write a separate method to display a Board, converting values to whatever pair of characters you want, and possibly with decorations.

            • Rather than updating Cells individually by saving their new value you can replace the entire Board with a new one at each step.

            • The time.sleep() currently does not take into account that the Board update time might change. This is unlikely to be a problem for a small board, but if you want completely smooth frames you'll want to either use threads or a tight loop which checks whether it's time to print the current Board yet.






          share|improve this answer























          • Thanks! How would I do this: "Rather than updating Cells individually by saving their new value you can replace the entire Board with a new one at each step." ?
            – HydraulicSheep
            Apr 3 at 5:02







          • 1




            You currently populate the newlabel field and then updatelabel once all the Cells are processed. You can avoid re-entering each Cell by creating the new Board based on the current Board, conceptually replacing newlabel with newboard.
            – l0b0
            Apr 3 at 6:18












          up vote
          5
          down vote



          accepted







          up vote
          5
          down vote



          accepted






          1. Running your code through pycodestyle will highlight some issues to make the code more familiar to Pythonistas. Other than that:


            • while 1 should be written as while True (Explicit is better than implicit)

            • Rather than checking for a specific character to quit I would just assume that people know about Ctrl-c

            • Use as easily readable names as possible. updatecell, for example, could be update_cell or even update since it's implicit that it's the Cell that's being updated.

            • Usually if __name__ == "__main__": is followed by simply main() or sys.exit(main()) (probably not relevant in your case). This makes the code more testable. Aim to minimize the amount of top-level code in general.


          2. The board is really a matrix, so it would IMO be better to represent it using a list of lists or ideally a matrix class. A dict has no intrinsic order, so semantically it's the wrong thing to use in any case.

          3. Somebody else will have to answer this.

          4. This is too subjective to answer.

          5. Some suggestions:

            • Try to take into account the fact that the Game of Life board is infinite in all directions. Ideally your implementation should handle this, but you could also use it as a stop condition - when things get too close to the edge to be able to figure out the next step with certainty the program could stop.

            • You can avoid conversions between numbers and strings by using numbers or even booleans everywhere (for example stored in a value or state field rather than label). You can then write a separate method to display a Board, converting values to whatever pair of characters you want, and possibly with decorations.

            • Rather than updating Cells individually by saving their new value you can replace the entire Board with a new one at each step.

            • The time.sleep() currently does not take into account that the Board update time might change. This is unlikely to be a problem for a small board, but if you want completely smooth frames you'll want to either use threads or a tight loop which checks whether it's time to print the current Board yet.






          share|improve this answer















          1. Running your code through pycodestyle will highlight some issues to make the code more familiar to Pythonistas. Other than that:


            • while 1 should be written as while True (Explicit is better than implicit)

            • Rather than checking for a specific character to quit I would just assume that people know about Ctrl-c

            • Use as easily readable names as possible. updatecell, for example, could be update_cell or even update since it's implicit that it's the Cell that's being updated.

            • Usually if __name__ == "__main__": is followed by simply main() or sys.exit(main()) (probably not relevant in your case). This makes the code more testable. Aim to minimize the amount of top-level code in general.


          2. The board is really a matrix, so it would IMO be better to represent it using a list of lists or ideally a matrix class. A dict has no intrinsic order, so semantically it's the wrong thing to use in any case.

          3. Somebody else will have to answer this.

          4. This is too subjective to answer.

          5. Some suggestions:

            • Try to take into account the fact that the Game of Life board is infinite in all directions. Ideally your implementation should handle this, but you could also use it as a stop condition - when things get too close to the edge to be able to figure out the next step with certainty the program could stop.

            • You can avoid conversions between numbers and strings by using numbers or even booleans everywhere (for example stored in a value or state field rather than label). You can then write a separate method to display a Board, converting values to whatever pair of characters you want, and possibly with decorations.

            • Rather than updating Cells individually by saving their new value you can replace the entire Board with a new one at each step.

            • The time.sleep() currently does not take into account that the Board update time might change. This is unlikely to be a problem for a small board, but if you want completely smooth frames you'll want to either use threads or a tight loop which checks whether it's time to print the current Board yet.







          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited Apr 3 at 3:59


























          answered Apr 3 at 3:43









          l0b0

          3,580922




          3,580922











          • Thanks! How would I do this: "Rather than updating Cells individually by saving their new value you can replace the entire Board with a new one at each step." ?
            – HydraulicSheep
            Apr 3 at 5:02







          • 1




            You currently populate the newlabel field and then updatelabel once all the Cells are processed. You can avoid re-entering each Cell by creating the new Board based on the current Board, conceptually replacing newlabel with newboard.
            – l0b0
            Apr 3 at 6:18
















          • Thanks! How would I do this: "Rather than updating Cells individually by saving their new value you can replace the entire Board with a new one at each step." ?
            – HydraulicSheep
            Apr 3 at 5:02







          • 1




            You currently populate the newlabel field and then updatelabel once all the Cells are processed. You can avoid re-entering each Cell by creating the new Board based on the current Board, conceptually replacing newlabel with newboard.
            – l0b0
            Apr 3 at 6:18















          Thanks! How would I do this: "Rather than updating Cells individually by saving their new value you can replace the entire Board with a new one at each step." ?
          – HydraulicSheep
          Apr 3 at 5:02





          Thanks! How would I do this: "Rather than updating Cells individually by saving their new value you can replace the entire Board with a new one at each step." ?
          – HydraulicSheep
          Apr 3 at 5:02





          1




          1




          You currently populate the newlabel field and then updatelabel once all the Cells are processed. You can avoid re-entering each Cell by creating the new Board based on the current Board, conceptually replacing newlabel with newboard.
          – l0b0
          Apr 3 at 6:18




          You currently populate the newlabel field and then updatelabel once all the Cells are processed. You can avoid re-entering each Cell by creating the new Board based on the current Board, conceptually replacing newlabel with newboard.
          – l0b0
          Apr 3 at 6:18












           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191111%2fconways-game-of-life-implemented-in-python%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Chat program with C++ and SFML

          Function to Return a JSON Like Objects Using VBA Collections and Arrays

          Will my employers contract hold up in court?