The no-player game uses a two-dimensional grid of cells, each of which can be 'alive' or 'dead'. These are then processed through generations where they live or die according to rules about the cells' immediate neighbours:
- Any live cell with fewer than two live neighbours dies, as if caused by under-population.
- Any live cell with two or three live neighbours lives on to the next generation.
- Any live cell with more than three live neighbours dies, as if by over-population.
- Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
My initial code is below. I know this can be improved, possibly by using the LEDs and their brightness level in place of the arrays. Anyway here it is...
# Conway's Game of Life
# Richard Zealley
# 9th May 2016
from microbit import *
from random import *
#number of lives to start out with (12 seems to work pretty well)
numbugs=12
#whether to treat the sides as boundaries or wrap round to the other side
wrap=True
#We're stuck with a 5x5 array but may be useful on another platform
cols=5
rows=5
#define 5x5 array full of 0s
bugs = [[0 for x in range(cols)] for y in range(rows)]
def clear_bugs():
'clears the array though this is not actually used as the definition above does this anyway but could be useful at some point'
global bugs
#set all array elements to 0
for x in range(5):
for y in range(5):
bugs[x][y]=0
return
def random_bugs(n):
'generate a set number of cells as populated (with 1)'
global bugs
i=0
while i<n:
x=randint(0,4)
y=randint(0,4)
#check not already populated
if bugs[x][y]!=1:
#populate it
bugs[x][y]=1
#count it
i+=1
return
def show_bugs():
'clear the display and then set any led which is populated'
global bugs
display.clear()
for x in range(5):
for y in range(5):
if bugs[x][y]==1:
display.set_pixel(x,y,9)
return
def check_position(pos):
'for wrapping - check if a position is in the 5x5 grid, and shift to opposite side if necessary'
if pos<0:
pos=5+pos
if pos>4:
pos=pos-5
return pos
def process_bug(x,y):
'check a position by counting each of its 8 surrounding neighbours and return the number populated'
global bugs
n=0
#count each of 8 neighbours
for i in (-1,0,1): #col
for j in (-1,0,1): #row
if not (i==0 and j==0): #don't count the current bug
if wrap:
col=check_position(x+i)
row=check_position(y+j)
if bugs[col][row]==1:
n+=1
else:
if i in (0,1,2,3,4) and j in (0,1,2,3,4):
if bugs[i][j]==1:
n+=1
return n
def generate_bugs():
'check each position in grid, count neighbours and die or birth accordingly'
global bugs
#track changes - if none then no point continuing
changes=0
#clone current bug positions because need to work from riginal before changing any
new_bugs=[list(row) for row in bugs]
#check each bug for neighbours
for x in range(5):
for y in range(5):
n=process_bug(x,y)
#live cell
if bugs[x][y]==1:
if n<2 or n>3: #dies (under or over population)
new_bugs[x][y]=0
changes +=1
elif n==3: #dead cell with 3 neighbours
#new birth
new_bugs[x][y]=1
changes +=1
#copy new population back to bugs
bugs=[list(row) for row in new_bugs]
return changes
def main():
#count the number of generations
goes=0
#create the game and show the initials LEDs
random_bugs(numbugs)
show_bugs()
sleep(1000)
#continue until button B is pressed
while not button_b.is_pressed():
goes+=1
#process bugs and stop if no longer any changes
changes=generate_bugs()
show_bugs()
#slow things down
sleep(1000)
#if nothing changed, that's it
if changes==0:
break
display.scroll(str(goes)+" generations")
display.scroll("The End")
#run it 8-)
if __name__ == "__main__":
main()
No comments:
Post a Comment