patternpythonMinor
Python implementation of a wrapped Conway's Game Of Life board
Viewed 0 times
conwaygamewrappedpythonlifeimplementationboard
Problem
```
import random
import rlereader
class Board:
"""Handles the status of all cells."""
def __init__(self, size):
self.size = size
self.grid = self.make_blank_grid()
self.furthest_col = 0
self.furthest_row = 0
def run_turns(self, num_turns):
"""Run a the simulator for a number of turns."""
while num_turns > 0:
self.run_turn()
num_turns -= 1
def run_turn(self):
"""Run a single turn of the simulator."""
new_grid = self.make_blank_grid()
for row in range(0, self.size):
for col in range(0, self.size):
new_grid[row][col] = self.get_cell_life(row, col)
self.grid = new_grid
def toggle_cell(self, row, col):
"""Toggle the dead or alive status of a single cell."""
self.grid[row][col] = not self.grid[row][col]
def check_furthest(self, row, col):
"""Check the furthest processed cell against this one and update if we
near the edge."""
if row + 1 >= self.furthest_row:
self.furthest_row = row + 2
if col + 1 >= self.furthest_col:
self.furthest_col = col + 2
def get_cell_life(self, row, col):
"""Return whether a given cell should become dead or alive.
This may update the processed cell boundaries if neccessary."""
living_neighbours = self.count_living_neighbours(row, col)
if self.grid[row][col]:
if living_neighbours in [2, 3]:
return True
else:
self.check_furthest(row, col)
return False
else:
if living_neighbours == 3:
self.check_furthest(row, col)
return True
return False
def check_cell(self, row, col):
"""Return whether the cell is dead or alive for the current
generation."""
if row self.size - 1:
row = 0
if col self.size - 1:
col = 0
import random
import rlereader
class Board:
"""Handles the status of all cells."""
def __init__(self, size):
self.size = size
self.grid = self.make_blank_grid()
self.furthest_col = 0
self.furthest_row = 0
def run_turns(self, num_turns):
"""Run a the simulator for a number of turns."""
while num_turns > 0:
self.run_turn()
num_turns -= 1
def run_turn(self):
"""Run a single turn of the simulator."""
new_grid = self.make_blank_grid()
for row in range(0, self.size):
for col in range(0, self.size):
new_grid[row][col] = self.get_cell_life(row, col)
self.grid = new_grid
def toggle_cell(self, row, col):
"""Toggle the dead or alive status of a single cell."""
self.grid[row][col] = not self.grid[row][col]
def check_furthest(self, row, col):
"""Check the furthest processed cell against this one and update if we
near the edge."""
if row + 1 >= self.furthest_row:
self.furthest_row = row + 2
if col + 1 >= self.furthest_col:
self.furthest_col = col + 2
def get_cell_life(self, row, col):
"""Return whether a given cell should become dead or alive.
This may update the processed cell boundaries if neccessary."""
living_neighbours = self.count_living_neighbours(row, col)
if self.grid[row][col]:
if living_neighbours in [2, 3]:
return True
else:
self.check_furthest(row, col)
return False
else:
if living_neighbours == 3:
self.check_furthest(row, col)
return True
return False
def check_cell(self, row, col):
"""Return whether the cell is dead or alive for the current
generation."""
if row self.size - 1:
row = 0
if col self.size - 1:
col = 0
Solution
import random
import rlereader
class Board:
"""Handles the status of all cells."""
def __init__(self, size):
self.size = size
self.grid = self.make_blank_grid()
self.furthest_col = 0
self.furthest_row = 0
def run_turns(self, num_turns):
"""Run a the simulator for a number of turns."""
while num_turns > 0:Use a
for turn in range(num_terms) loop instead of a while loopself.run_turn()
num_turns -= 1
def run_turn(self):
"""Run a single turn of the simulator."""
new_grid = self.make_blank_grid()
for row in range(0, self.size):Just use range(self.size), the 0 is not needed.
for col in range(0, self.size):
new_grid[row][col] = self.get_cell_life(row, col)
self.grid = new_grid
def toggle_cell(self, row, col):
"""Toggle the dead or alive status of a single cell."""
self.grid[row][col] = not self.grid[row][col]
def check_furthest(self, row, col):
"""Check the furthest processed cell against this one and update if we
near the edge."""
if row + 1 >= self.furthest_row:
self.furthest_row = row + 2
if col + 1 >= self.furthest_col:
self.furthest_col = col + 2Write it like this instead:
self.furthest_row = max(self.furthest_row, row + 2)
self.furthest_col = max(self.furthest_col, col + 2)Also, the function updates rather then checks the furthest, a better name would be update_furthest
I don't know why you are adding 2 here, a comment explaining that would be helpful
def get_cell_life(self, row, col):
"""Return whether a given cell should become dead or alive.
This may update the processed cell boundaries if neccessary."""
living_neighbours = self.count_living_neighbours(row, col)
if self.grid[row][col]:
if living_neighbours in [2, 3]:
return True
else:
self.check_furthest(row, col)
return False
else:
if living_neighbours == 3:
self.check_furthest(row, col)
return True
return FalseWrite it like this instead:
living_neighbours = self.count_living_neighbours(row, col)
if self.grid[row][cell]:
new_value = living_neighbors in [2,3]
else:
new_value = living_neighbors == 3
if new_value != self.grid[row][cell]:
self.check_furthest(row, cell)
return new_valueThis way we separate the furthest updating from the decision of the new value of the cell. It might also be a good idea to move the furthest updating to run_turn
def check_cell(self, row, col):
"""Return whether the cell is dead or alive for the current
generation."""
if row self.size - 1:
row = 0
if col self.size - 1:
col = 0
return self.grid[row][col]Use modulous instead of all those ifs
def check_cell(self, row, col):
return self.grid[row % self.size][col % self.size]The % divides with remainder which gives exactly the wrap around feature you want.
def count_living_neighbours(self, row, col):
"""Find how many neighnours of a given cell are alive."""
active_count = 0
to_check = [
(row - 1, col - 1), # Top left
(row - 1, col), # Top
(row - 1, col + 1), # Top right
(row, col - 1), # Left
(row, col + 1), # Right
(row + 1, col - 1), # Bottom left
(row + 1, col), # Bottom
(row + 1, col + 1) # Bottom Right
]
for crow, ccol in to_check:
if self.check_cell(crow, ccol):
active_count += 1
return active_countYou can simplify the function by replacing it with:
return sum(self.check_cell(row, col) for row, col in to_check)I recommend moving to_check to a global constant.
def make_blank_grid(self):
"""Returns a blank grid for future use."""
grid = []
for row in range(0, self.size):
grid.append([])
for col in range(0, self.size):
grid[row].append([])
grid[row][col] = False
return gridWrite it like this instead:
def make_blank_grid(self):
"""Returns a blank grid for future use."""
grid = []
for row in range(0, self.size):
grid.append([False] * self.size)
return gridThe multiply produces a new list which is the original list repeated. But only use it on immutable values like numbers and bools. Don't use on anything that can be modified like other lists.
```
def load_rle_into_grid(self, rle):
"""Loads a RLE representation of a playing field into the grid.
rle should be a file like object."""
reader = rlereader.GRLEReader()
data = reader.rea
Code Snippets
import random
import rlereader
class Board:
"""Handles the status of all cells."""
def __init__(self, size):
self.size = size
self.grid = self.make_blank_grid()
self.furthest_col = 0
self.furthest_row = 0
def run_turns(self, num_turns):
"""Run a the simulator for a number of turns."""
while num_turns > 0:self.run_turn()
num_turns -= 1
def run_turn(self):
"""Run a single turn of the simulator."""
new_grid = self.make_blank_grid()
for row in range(0, self.size):for col in range(0, self.size):
new_grid[row][col] = self.get_cell_life(row, col)
self.grid = new_grid
def toggle_cell(self, row, col):
"""Toggle the dead or alive status of a single cell."""
self.grid[row][col] = not self.grid[row][col]
def check_furthest(self, row, col):
"""Check the furthest processed cell against this one and update if we
near the edge."""
if row + 1 >= self.furthest_row:
self.furthest_row = row + 2
if col + 1 >= self.furthest_col:
self.furthest_col = col + 2self.furthest_row = max(self.furthest_row, row + 2)
self.furthest_col = max(self.furthest_col, col + 2)def get_cell_life(self, row, col):
"""Return whether a given cell should become dead or alive.
This may update the processed cell boundaries if neccessary."""
living_neighbours = self.count_living_neighbours(row, col)
if self.grid[row][col]:
if living_neighbours in [2, 3]:
return True
else:
self.check_furthest(row, col)
return False
else:
if living_neighbours == 3:
self.check_furthest(row, col)
return True
return FalseContext
StackExchange Code Review Q#2303, answer score: 4
Revisions (0)
No revisions yet.