-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgrid.py
95 lines (82 loc) · 3.79 KB
/
grid.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
ALIVE = 1
DEAD = 0
class GameGrid:
def __init__(self, grid_height: int, grid_width: int) -> None:
self.grid = [[[0, 0] for x in range(grid_width)]
for y in range(grid_height)]
self.grid_height = grid_height
self.grid_width = grid_width
def set_cell(self, pos: list, status: int, old: bool = True) -> None:
"""
This function sets the status of the cell (old/new)
:param pos: A list of tuple containing (y,x) index of the cell to be set
:param status: Alive/Dead
:param old: Whether to update old state or new state
:return: None
"""
for (y_idx, x_idx) in pos:
if old:
self.grid[y_idx][x_idx][0] = status
else:
self.grid[y_idx][x_idx][1] = status
def get_grid(self) -> list:
return self.grid
def reset_grid(self) -> None:
self.grid = [[[0, 0] for x in range(self.grid_width)]
for y in range(self.grid_height)]
def get_neighbour_count(self, y_idx, x_idx):
"""
For a cell with index (y_idx, x_idx), it returns the number of ALIVE
neighbours
:param y_idx: y index of the cell
:param x_idx: x index of the cel
:return: None
"""
num_neighbour = 0
if x_idx - 1 >= 0:
num_neighbour += self.grid[y_idx][x_idx - 1][0]
if y_idx - 1 >= 0:
num_neighbour += self.grid[y_idx - 1][x_idx][0]
if x_idx + 1 < self.grid_width:
num_neighbour += self.grid[y_idx][x_idx + 1][0]
if y_idx + 1 < self.grid_height:
num_neighbour += self.grid[y_idx + 1][x_idx][0]
if y_idx - 1 >= 0 and x_idx - 1 >= 0:
num_neighbour += self.grid[y_idx - 1][x_idx - 1][0]
if y_idx + 1 < self.grid_height and x_idx + 1 < self.grid_width:
num_neighbour += self.grid[y_idx + 1][x_idx + 1][0]
if y_idx + 1 < self.grid_height and x_idx - 1 >= 0:
num_neighbour += self.grid[y_idx + 1][x_idx - 1][0]
if y_idx - 1 >= 0 and x_idx + 1 < self.grid_width:
num_neighbour += self.grid[y_idx - 1][x_idx + 1][0]
return num_neighbour
def run_iteration(self) -> None:
"""
This functions performs iteration based on the Rules of Convey's Game of life.
To summarise:
1) If a cell is alive and it has less than 2 alive neighbours, it dies due to loneliness.
2) If a cell is alive and it has more than 3 alive neighbours, it dies due to over population.
3) If a cell is alive and it has 2 or 3 alive neighbours, it continues to live.
4) If a cell is dead and it has exactly 3 alive neighbours, it becomes alive due to reproduction ;).
More information at : https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
:return: None
"""
for y_idx in range(self.grid_height):
for x_idx in range(self.grid_width):
if self.grid[y_idx][x_idx][0] == ALIVE:
num_neighbour = self.get_neighbour_count(y_idx, x_idx)
if num_neighbour < 2 or num_neighbour > 3:
pos = [(y_idx, x_idx)]
self.set_cell(pos, DEAD, False)
else:
pos = [(y_idx, x_idx)]
self.set_cell(pos, ALIVE, False)
else:
num_neighbour = self.get_neighbour_count(y_idx, x_idx)
if num_neighbour == 3:
pos = [(y_idx, x_idx)]
self.set_cell(pos, ALIVE, False)
for y_idx in range(self.grid_height):
for x_idx in range(self.grid_width):
pos = [(y_idx, x_idx)]
self.set_cell(pos, self.grid[y_idx][x_idx][1], True)