8
\$\begingroup\$

It's my implementation. Can I get some opinions on it?

import random
import os
import time
class Game:
 def __init__(self, turns, w, h):
 self.board = []
 for x in range(0, h):
 self.board.append([])
 for y in range(0, w):
 self.board[x].append(random.random())
 self.turns = turns
 def next_gen(self):
 self.board_next = []
 for x in range(0, len(self.board)):
 self.board_next.append([])
 for x in range(0, len(self.board)):
 for y in range(0, len(self.board[x])):
 n = 0
 for dx in range(-1, 2):
 for dy in range(-1, 2):
 if (dx == 0 and dy == 0):
 pass
 else:
 try:
 if (x + dx >= 0 and y + dy >= 0):
 if (self.board[x + dx][y + dy]):
 n += 1
 except IndexError:
 pass
 c = self.board[x][y]
 if (n == 1 or n == 0):
 c = 0
 elif (n == 3):
 c = 1
 elif (n == 2):
 pass
 else:
 c = 0
 self.board_next[x].append(c)
 self.board = self.board_next[:]
 def show(self):
 for x in range(0, len(self.board)):
 l = ""
 for y in range(0, len(self.board[x])):
 if (self.board[x][y]):
 l += "X"
 else:
 l += "#"
 print(l)
 time.sleep(0.5)
 def start(self):
 for x in range(0, self.turns):
 print("\n+Gen {0}".format(x + 1))
 self.show()
 if (x + 1 != self.turns):
 os.system('clear')
 self.next_gen()
os.system('clear')
game = Game(3, 3, 3)
game.board = [
 [0, 0, 0],
 [1, 1, 1],
 [0, 0, 0]]
game.start()

And output:

+Gen 1
###
XXX
###
+Gen 2 
#X# 
#X#
#X#
+Gen 3
###
XXX
###
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Oct 14, 2016 at 8:48
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

First three general remarks:

  1. range does not need an explicit start argument, it defaults to 0. range is basically range(start=0, stop, step=1), only stop is needed
  2. if takes an expression as argument which just has to evaluate truthy or falsey. There is no need for parenthesis, unless chaining multiple expressions over multiple lines or doing some complicated and/or logic.
  3. you should consistently use 4 spaces per indentation level (your class only has 2 in the outer level).

Your setting up of the board can be simplified with a list comprehension:

self.board = [[random.random() for _ in range(w)] for _ in range(h)]

Here I used _ as an unused loop variable, as customary in Python.

I would also save h and w in the class for later use.


In Game.next_gen:

if (n == 1 or n == 0):
 c = 0
elif (n == 3):
 c = 1
elif (n == 2):
 pass
else:
 c = 0

is equivalent to:

if n == 3:
 c = 1
elif n != 2:
 c = 0

I would make two helper functions calculating neighbours that are alive:

def neighbours(self, x, y):
 p = -1, 0, 1
 for dx, dy in itertools.product(p, p)
 if dx == dy == 0:
 continue
 _x, _y = x + dx, y + dy
 if 0 <= _x < self.h and 0 <= _y < self.w:
 yield _x, _y
def alive_neighbours(self, x, y):
 return sum(self.board[n_x][n_y] > 0 for n_x, n_y in self.neighbours(x, y))

Here I used the boundaries to make sure that neighbours only serves points inside the grid (and used itertools.product to make it easier to construct dx and dy). Then getting the sum of all alive neighbours just sums over the values, since in self.board empty cells have a value of zero, while alive cells a value greater than zero.

This simplifies next_gen to:

def next_gen(self):
 board_next = [[0 for _ in range(self.w)] * self.h]
 for x in range(len(self.board)):
 for y in range(len(self.board[x])):
 n = self.alive_neighbours(x, y)
 cell = self.board[x][y]
 if n == 3:
 cell = 1
 elif n != 2:
 cell = 0
 board_next[x][y] = cell
 self.board = board_next[:]

Your show function can be simplified using str.join:

def show(self):
 for row in self.board:
 print("".join("X" if cell else "#" for cell in row))

The time.sleep(0.5) I would put in start to make it possible to show the generation without delay if necessary.


I would put the code calling your class into a if __name__ == "__main__": guard to allow importing your class from another module:

if __name__ == "__main__":
 os.system('clear')
 game = Game(3, 3, 3)
 game.board = [
 [0, 0, 0],
 [1, 1, 1],
 [0, 0, 0]]
 game.start()
answered Oct 14, 2016 at 19:21
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.