[II] The Game Of Life
So, ich habe das Ding jetzt von der Geschwindigkeit etwa verdreifacht. Außerdem noch ein wenig aufgeräumt und den Debug-Code entfernt. Noch ein paar Kommentare und eine Priese Dokumentation dazu und fertig ist’s. Wer sich mein Game Of Life gerne mal anschauen möchte hat hiermit die Gelegenheit. Downloadlink. Oder einfach auf “more” klicken.
-
#!/usr/bin/python
-
# Valentin Voigt
-
-
import os
-
import sys
-
-
F_DEAD = 0 # Dead cell
-
F_ALIVE = 1 # Living cell
-
-
class GameOfLife:
-
-
field = []
-
renderer = None
-
generation = 0
-
-
def __init__(self, width, height, renderer):
-
"""Initializes the GameOfLife object.
-
Width describes the number of cells on the x-axis, height describes
-
the number of cells on the y-axis. Renderer must be callable. It takes
-
one argument with the two-dimensional game field."""
-
-
self.field = [[F_DEAD for i in range(width)] for i in range(height)]
-
self.width = width
-
self.height = height
-
self.renderer = renderer
-
-
def alive_neighbours(self, x, y):
-
"""Returns the number of living cells around the given cell."""
-
-
count = 0
-
# Some time ago I put that annoying "if"s into some functions called
-
# "cell_exists" and "if_alive_return_one". So the following part was
-
# very easy with just 8 lines similar to this one:
-
# count += if_alive_return_one(x+1, y+1)
-
# But because this was to slowly I had to put these "if"s here. Now
-
# the code works a bit faster, although it doesn't look very
-
# professional anymore.
-
if y-1 < self.height and y-1 >= 0 and x-1 < self.width and x-1 >= 0:
-
if self.field[y-1][x-1] == F_ALIVE:
-
count += 1
-
if y-1 < self.height and y-1 >= 0 and x < self.width and x >= 0:
-
if self.field[y-1][x] == F_ALIVE:
-
count += 1
-
if y-1 < self.height and y-1 >= 0 and x+1 < self.width and x+1 >= 0:
-
if self.field[y-1][x+1] == F_ALIVE:
-
count += 1
-
if y < self.height and y >= 0 and x-1 < self.width and x-1 >= 0:
-
if self.field[y][x-1] == F_ALIVE:
-
count += 1
-
if y < self.height and y >= 0 and x+1 < self.width and x+1 >= 0:
-
if self.field[y][x+1] == F_ALIVE:
-
count += 1
-
if y+1 < self.height and y+1 >= 0 and x-1 < self.width and x-1 >= 0:
-
if self.field[y+1][x-1] == F_ALIVE:
-
count += 1
-
if y+1 < self.height and y+1 >= 0 and x < self.width and x >= 0:
-
if self.field[y+1][x] == F_ALIVE:
-
count += 1
-
if y+1 < self.height and y+1 >= 0 and x+1 < self.width and x+1 >= 0:
-
if self.field[y+1][x+1] == F_ALIVE:
-
count += 1
-
return count
-
-
def activate(self, x, y):
-
"""Marks the specified cells as alive"""
-
-
self.field[y][x] = F_ALIVE
-
-
def activate_list(self, cells):
-
"""Marks the specified list of cells as alive.
-
Takes a list of lists with two elemts. Example:
-
activate_list([ (0,1), (2,3), (9,2) ])"""
-
-
for cell in cells:
-
self.activate(cell[0], cell[1])
-
-
def tick(self):
-
"""Calculate the next generation."""
-
-
# Initialises a new field with only dead cells. They'll be
-
# overwritten in the following lines. Before I used [].append to
-
# create the new field. But this was too slowly, too…
-
new_field = [[F_DEAD for i in range(self.width)] for j in range(self.height)]
-
y = 0
-
for row in self.field:
-
x = 0
-
for cell in row:
-
if cell == F_DEAD:
-
if self.alive_neighbours(x, y) == 3:
-
new_field[y][x] = F_ALIVE
-
else:
-
new_field[y][x] = F_DEAD
-
elif cell == F_ALIVE:
-
n = self.alive_neighbours(x, y)
-
if n < 2:
-
new_field[y][x] = F_DEAD
-
elif n > 3:
-
new_field[y][x] = F_DEAD
-
else:
-
new_field[y][x] = F_ALIVE
-
x += 1
-
y += 1
-
self.field = new_field
-
self.generation += 1
-
-
def render(self):
-
"""Calls the render function."""
-
-
# Reminds me on some of my friends.
-
# They often make others do their jobs.
-
self.renderer(self.field)
-
-
def ConsoleRenderer(field):
-
"""Simplest way I found for drawing the game field."""
-
-
# Clear screen
-
if os.name == "nt":
-
os.system("cls")
-
elif os.name == "posix":
-
os.system("clear")
-
else:
-
for i in range(0, 100):
-
print ""
-
# Print field
-
for row in field:
-
for cell in row:
-
sys.stdout.write("X" if cell == F_ALIVE else " ")
-
print
-
print
-
-
def start_example():
-
game = GameOfLife(79, 25, ConsoleRenderer)
-
game.activate_list([ (50, 16), (51, 16), (51, 17), (51, 15), (52, 15) ])
-
try:
-
while True:
-
game.tick()
-
game.render()
-
except KeyboardInterrupt:
-
pass
-
-
if __name__ == "__main__":
-
start_example()