Category : Uncategorized
Last night at the Coder School in San Mateo a student and I found a cool site that showed how to create random Space Invaders-like graphics:
The 5×3 “invader array” would be filled in at random and then columns 1 and 2 would be copied or reflected across the center so invaders will all have lateral symmetry.
We had already done the “Atticus Clone” Random Art exploration so my student easily recognized the similarities. He made a class for an Invader and he already had the functionality for randomly filling in all 15 elements in the 3×5 array.
Those Awful Reflections
It wasn’t hard to get a list of 15 random 0’s and 1’s but how were we going to copy the terms and reflect them across the center? As a math guy, I was looking for patterns in the indices of the items to reflect and where to insert, but my lazy mind came up with an elegant solution!
Instead of trying to reflect elements of lists, I decided to flip the 5×3 grid into a 3×5 grid, with 3 lists of 5 elements each. That would make it a cinch to copy the lists and add the copies to another part of the array. Now if the array looked something like this:
blockList = [[1,0,0,1,1], [0,1,0,0,1], [0,0,1,1,1]]
I could easily add the second list to the end of the array, then add the first list. I’m copying each of those rows to the “gridList” which will be the 5×5 array. Then I’m copying/reflecting the first two lists starting with the second list and working backwards.
gridList = [[1,0,0,1,1], [0,1,0,0,1], [0,0,1,1,1], [0,1,0,0,1], [1,0,0,1,1]]
Notice the gridList has up-down symmetry. Here’s the code:
self.blockList =  for i in range(2): self.blockList.append() for j in range(5): self.blockList[i].append(choice([0,1])) #now copy the rows at the end to the beginning #rows 0,1,2,1,0 for rownum in range(3): #for 0,1,2 self.gridList.append(self.blockList[rownum]) for rownum in range(1,-1,-1): #for 1,0 self.gridList.append(self.blockList[rownum])
My next student wanted to make larger Invaders, so I generalized the code to make a grid of any size (“dim”).
self.blockList =  for i in range(dim//2+1): self.blockList.append() for j in range(dim): self.blockList[i].append(choice([0,1])) #now copy the rows at the end to the beginning #rows 0,1,2,3, ... n, ...,3,2,1,0 for rownum in range(dim//2+1): self.gridList.append(self.blockList[rownum]) for rownum in range(dim//2-1,-1,-1): self.gridList.append(self.blockList[rownum])
Now the reflection is fairly easy, and all I had to do was rotate the Invader so the copied rows became columns before drawing it. Just like the Atticus Clone sketch, I made a grid of randomly drawn Invaders:
All the code is on github. Have fun!