I've had a pretty good grasp on concepts until I hit 2D lists, and I recently failed a homework assignment in which I had to make a simple rendition of "Conway's Game of Life" using 2D lists. I was able to print the board, and a U shape using for loops, but I couldn't even start trying to do the same with 2D lists. I'm just so lost, and I feel like if I can just get a jumping off point that I can figure out the rest. The other issue is that the "U" shape is static, and I've tried a few different things with "randint" function, but can't get the entire "U" shape to move around.
EDIT: Added code to the bottom starting at "tempGen".
I figured out how to print the 30 x 60 board using a 2D list, and I'm currently trying to figure out how to incorporate my "U" shape into there.
#! python3
import random
from random import randint
MAX_ROW = 30
MAX_COL = 60
currentGen = [ [MAX_ROW], [MAX_COL] ]
tempGen = [ [MAX_ROW], [MAX_COL] ]
def displayMenu(): #DISPLAY OUTPUT OPTIONS, DON'T COLLECT
print("[P]lay - Press 'P' to play.\n[Q]uit - Press 'Q' to exit.\n")
def setZeroList(): #INITIALIZE 2-D LISTS TO ZERO
currentGen = [[0], [0]]
tempGen = [[0], [0]]
return currentGen, tempGen
def copyList(): #COPY 2D LIST TO ANOTHER 2D LIST
print("?????")
def displayList(): #PRINTS ANY 2D LIST
print("?????")
def setInitialPatternList(): #CREATE THE "U" SHAPE
for MAX_ROW in range(30):
for MAX_COL in range(60):
if ((MAX_COL == 0 or MAX_COL == 6) and MAX_ROW <= 5) or (MAX_ROW == 5 and (MAX_COL >= 0 and MAX_COL <= 6)):
print("X", end="")
else:
print(end = ".")
print()
tempGen = [["*"]* MAX_COL] * MAX_ROW
print("\ntable:")
for row in range(MAX_ROW):
for col in range(MAX_COL):
if (col == (MAX_COL - 1)):
print(tempGen[row][col], end = "\n")
else:
print(tempGen[row][col], end = "")
Lets start with what 2D lists really are. A 2D list is simply a list of lists. With a normal list, you can do things like
my_list[0] = 4
For a 2D list, each element is a list-
list_of_lists[4] = ["a","b"]
In this case list_of_list[4][0]
returns "a", because we are really doing (list_of_list[4])[0]
. You can think of the something[i][j]
notation to being equivalent to Coordinate Plane: 'something', Position: (i, j)
, with i
and j
being x and y values.
With that out of the way, lets consider making 2D lists. Since every "row" in your 2D list consists of a list, you need to first populate your original list with empty lists. Something like
list_of_lists = []
for i in range(depth):
list_of_lists.append([])
This will allow you to assign to append to any row of your 2D list, within range of [0,depth). You cannot simply use tempGen = [["*"]* MAX_COL] * MAX_ROW
as your original post does, because every row of your 2D list will be a reference to the same exact list, and thus changing one row affects all rows identically. If you also want to access each element without appending, consider filling the original list with something like [0] * width
or [None] * width
, instead of the empty list []
.
Now lets say you have a 2D list built, you populated it with some data, and now you would like to shift all elements rightwards. You can write a function to do this
def right_shift(my_list):
for row_num in range(len(my_list)): # for each list in our list of lists
row = my_list[row_num]
for col_num in range(len(row)-2, -1, -1): # skip the last element, and iterate backwards
row[col_num + 1] = row[col_num] # assign the (col_num+1)th element to equal the col_num 'th element in that row.
return my_list
Just write the logic to handle one row, and then extend that logic to all other rows of your list of lists (usually with just a for loop).
For good measure, lets cover printing your 2D array-
def print_matrix(list_of_lists):
for row in list_of_lists:
print("".join(map(str, row))) # here map(str,...) is used to make sure every element is a string.
Once you get comfortable with 2D lists, you may want to consider looking at dictionaries. You can avoid nesting lists by using a tuple as the key, for example my_dict[(14, 27)] = "A"
, or even using a defaultdict to avoid populating each entry with an empty list/dict first- from collections import defaultdict; my_2D_dict = defaultdict(dict)
, which could then be used directly my_2D_dict[4][2] = "something"
.