123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- import argparse
- import copy
- import os
- import sys
- import time
-
- DEFAULT_GRID = [
- [0, 0, 0, 0, 0],
- [0, 0, 1, 0, 0],
- [0, 0, 1, 0, 0],
- [0, 0, 1, 0, 0],
- [0, 0, 0, 0, 0],
- ]
-
- DEFAULT_SPEED = 500
-
-
- class GameOfLife:
- def __init__(self, speed: int = DEFAULT_SPEED, grid: list[list[int]] = DEFAULT_GRID):
- self.grid = grid.copy()
- self.height = len(self.grid)
- self.width = len(self.grid[0])
- self.speed = speed
-
- @classmethod
- def from_string(cls, template: str, speed: int = DEFAULT_SPEED):
- lines = template.strip().split('\n')
- for line in lines:
- print("line is: ", line, "+++")
- grid = [[int(col) for col in line] for line in lines]
- return GameOfLife(grid=grid, speed=speed)
-
- def play(self):
- while True:
- self.iterate()
- self.show()
- time.sleep(self.speed / 1000)
-
- def iterate(self):
- new_grid = copy.deepcopy(self.grid)
-
- for y, row in enumerate(self.grid):
- for x, current_value in enumerate(row):
- is_alive = current_value == 1
- living_neighbors = self.get_living_neighbors(y, x)
-
- if is_alive:
- if living_neighbors < 2:
- new_grid[y][x] = 0
- elif living_neighbors == 2 or living_neighbors == 3:
- new_grid[y][x] = 1
- else:
- new_grid[y][x] = 0
- else:
- if living_neighbors == 3:
- new_grid[y][x] = 1
-
- self.grid = new_grid
-
- def get_living_neighbors(self, y: int, x: int):
- neighbors = self.get_neighbors(y, x)
- living = [n for n in neighbors if n == 1]
- return len(living)
-
- def get_neighbors(self, y: int, x: int):
- neighbors = []
-
- if y > 0:
- neighbors.append(self.grid[y - 1][x]) # N
- if x > 0:
- neighbors.append(self.grid[y - 1][x - 1]) # NW
- if x < self.width - 1:
- neighbors.append(self.grid[y - 1][x + 1]) # NE
-
- if x > 0:
- neighbors.append(self.grid[y][x - 1]) # W
- if x < self.width - 1:
- neighbors.append(self.grid[y][x + 1]) # E
-
- if y < self.height - 1:
- neighbors.append(self.grid[y + 1][x]) # S
- if x > 0:
- neighbors.append(self.grid[y + 1][x - 1]) # SW
- if x < self.width - 1:
- neighbors.append(self.grid[y + 1][x + 1]) # SE
-
- return neighbors
-
- def show(self):
- self.clear()
-
- for row in self.grid:
- for col in row:
- if col == 0:
- # print('□', end='')
- print('·', end='')
- else:
- print('■', end='')
-
- print('\n')
-
- def clear(self):
- os.system('cls' if os.name == 'nt' else 'clear')
-
-
- if __name__ == "__main__":
- parser = argparse.ArgumentParser(description='Conway\'s Game of Life')
- parser.add_argument(
- '-f', '--file', help='The path to a file containing a starting grid. The grid file should use 0 for dead cells and 1 for living cells.')
- parser.add_argument(
- '-s', '--speed', help='The delay between iterations in milliseconds (default: 500, minimum: 100)', default=500, type=int),
- args = parser.parse_args()
-
- if args.speed < 100:
- print('Speed must be at least 100 milliseconds')
- exit(1)
-
- if args.file:
- with open(args.file, 'r') as f:
- contents = f.read()
- GameOfLife.from_string(contents, args.speed).play()
- else:
- GameOfLife(args.speed).play()
|