Coding Curriculum - Python

Worksheet 6

After this worksheet, we will finally have a working version of our word search puzzle! But before that, we still have a couple of things to do

  1. Create a loop, to run until we have found an appropriate spot for a word
  2. Fix our loop.
  3. Place the word in that spot
  4. Randomly populate the rest of the grid
  5. Link everything together

Step 1: Finding a Spot

Our placeHorizontally function is already able to find a spot for our function and determine if it is appropriate or not. Now we need to create a loop that loops until it has found a spot. Should we use a for or a while loop? A for loop is used if you have to loop a fixed number of times whilst a while loop runs depending on the circumstances. Thus since we do not know how many times we will have to look, we will use a while loop.

For our while loop, we will need some sort of boolean to determine if we have found a solution or not. But wait? We already had one, called fits! We should be able to use it. Let's try it out.

def placeHorizontally(grid, entry):
fits = True # assume that it fits
while fits:
column = randint(0, len(grid) - len(entry["answer"]))
row = randint(0, len(grid) - 1)

for i in range(column, column + len(entry["answer"])):
if grid[row][i] != '.':
fits = False
break

Step 2: Fixing our loop

So we basically took our previous code and placed everything inside a while loop. Let's see if this works. The loop will stop once fits is false. Wait a second, that's not what we want, we want the loop to stop once fits is true! We will have the change our code! Instead we will have to assume that fits is false and set it to true if it has found a solution. Try to code this.

for i in range(column, column + len(entry["answer"])):
if grid[row][i] != '.':
fits = False
break
elif i == column + len(entry["answer")]
fits = True

Step 3: Placing the words inside the grid

Yes this seems to work!! What is next? We actually have to place the word inside the grid. We can use a similar for loop than the one we have already used. We will also need a variable that allows us to access every character in the answer. Try to code this.

You should have a loop variable that takes you from the starting column to the end of the column. However in order to access every element in the word as well, we will need a second variable like so:

j = 0
for i in range(5, 10)
print str(i) + str(j)
j += 1

Congratulations! You are now able to place every item you want horizontally in the grid!! Try to finish the placeVertically on your own.

Step 4: Populate the rest of the Grid

So we have got placeItems that goes over every element we want to place in the grid and either places them horizontally or vertically by calling placeHorizontally or placeVertically. Now that we are able to place every element in the grid, we need to create a functions, called fillGrid that randomly populates the rest. We can make use of 2 for loops to go over every element in the grid and use the choice function to choose a random letter.

for i in range(0, 10):
for j in range(0, 10):
if grid[i][j] == '.':
grid[i][j] = choice(letters)

If you have done that, your code should look like:

Step 5: Linking Everything Together

Wow, we are done! We have written all the functions that we needed! But wait, the most important part is yet to come, linking everything together. But before we do that, to make our lives easier, let's think about what we want our program to do.

  1. Ask you which questions you want to study
  2. Calculate the size of the grid
  3. Create the grid
  4. Place all of the answers on the grid
  5. Fill the rest of the grid with random letters
  6. Print the grid
  7. Ask of the questions and prompt for the answer

4) This list will make our lives so much easier because we basically have a function for all of the things in this list. Therefore we simply need to create a new function, that calls all of the functions that we have created, in the order that we want them to. Try to make such a main function. It should look like:

def main():
variable = callFunction()
otherFunction(variable)
#and so on

Finally, we simply call our main function inside our program like so: main(). Then we run it in the terminal using the command: python filename.py (replace the filename with how you called the file)

That was it! You are now able to study in a fun, new way.

The Complete Code

from random import randint, choice
import string

chemistryEntries = [
{"question":"What is the chemical composition of water?", "answer": "H2O"},
{"question":"What does Mg stand for?", "answer": "magnesium"},
{"question":"What type of bonding is there betwwn Fe atoms?", "answer": "metallic"},
{"question":"Which sub atomic particle has a positive charge?", "answer": "protons"},
{"question":"What are atoms with the same amount of protons but a different mass number?", "answer": "isotopes"},
{"question":"What does K stand for?", "answer": "potassium"},
]

mathEntries = [
{"question": "What method do we use to calculate the slope of a graph?", "answer": "differentiation"},
{"question": "Whose theorem states that in a triangle: a^2 = b^2 + c ^2?", "answer": "pythagoras"},
{"question": "What is the type of the following function: x^2 + x + 4?", "answer": "quadratic"},
{"question": "If the determinant of a quadratic equation is greater than 0, how many roots are there?", "answer": "two"},
]

physicsEntries = [
{"question": "Does a metal expand when heated?", "answer": "yes"},
{"question": "In what units do we measure resitance?", "answer": "ohms"},
{"question": "What type of lens does a magnifying glass have?", "answer": "convex"},
{"question": "What is the correct formula for momentum?", "answer": "mxv"},
]

#First we need to figure out how big the grid needs to be
def sizeOfGrid(entries):
maximum = len(entries[1]["answer"])
for item in entries:
if len(item["answer"]) > maximum:
maximum = len(item["answer"])
return maximum + int(len(entries)/3)


#create the grid, initialize values with x

def createGrid(size):
grid = [['.' for i in range(size)] for x in range(size)]
return grid


def printGrid(grid):
for item in grid:
print " ".join(item)

#place a word vertically in the grid
def placeVertically(grid, entry):
fits = False      #assume that it does not fit
while not fits:  #runs while it is false
row = randint(0, len(grid) - len(entry["answer"]))
column = randint(0, len(grid) - 1)

for i in range(row, row + len(entry["answer"])):
if grid[i][column] != '.':
break
fits = True  #if the loop did not break, it fits

j = 0
for i in range(row, row + len(entry["answer"])):
grid[i][column] = entry["answer"][j]
j += 1

#place a word horizontally in a grid
def placeHorizontally(grid, entry):
fits = False      #assume that it does not fit
while not fits:  #runs while it is false
column = randint(0, len(grid) - len(entry["answer"]))
row = randint(0, len(grid) - 1)

for i in range(column, column + len(entry["answer"])):
if grid[row][i] != '.':
break
fits = True  #if the loop did not break, it fits

j = 0
for i in range(column, column + len(entry["answer"])):
grid[row][i] = entry["answer"][j]
j += 1

def placeItems(grid, entries):
for item in entries:
horizontal = randint(0, 1) #1 if it is placed horizontally, 0 if it is placed vertically

if horizontal == 0:
placeVertically(grid, item)
else:
placeHorizontally(grid, item)

#after the words are in the grid, fill the remaining places with random numbers
def fillGrid(grid):
for i in range(0, len(grid)):
for j in range(0, len(grid)):
if grid[i][j] == '.':
grid[i][j] = choice(string.letters)

def askQuestions(entries):
score = 0
for i in range(0, len(entries)):
correct = False
print "Question " + str(i + 1) + "\n"
answer = raw_input(entries[i]["question"] + " ")
if answer.lower() == entries[i]["answer"].lower():
print "That is correct, well done!\n"
correct = True
score += 1
while not correct:
score -= 0.1
print "I am sorry, but that was not the answer, let's try again\n"
answer = raw_input(entries[i]["question"] + " ")            
if answer.lower() == entries[i]["answer"].lower():
print "That is correct, well done!\n"
correct = True
score += 1
elif answer == "skip":
print "Okay, let's try the next one\n"
correct = True
print "Good job, you got a " + str(score) + "/" + str(len(entries) ) + " :)\n"

def decideTopic():
print "Welcome to the Word Search Quiz"
print "What do you want to study?"
print "1. Math"
print "2. Chemistry"
print "3. Physics"
validAnswer = False
while not validAnswer:
answer = int(raw_input())
if answer == 1:
entries = mathEntries
validAnswer = True
elif answer == 2:
entries = chemistryEntries
validAnswer = True
elif answer == 3:
entries = physicsEntries
validAnswer = True
else:
print "I am sorry but that was not a valid answer, try again"
return entries

def main():
entries = decideTopic()
size = sizeOfGrid(entries)
grid = createGrid(size)
placeItems(grid, entries)
fillGrid(grid)
printGrid(grid)
askQuestions(entries)


main()

Some Extra Thinking...

If you found this easy and you are up for the challenge, try to hide the words diagonally or make words overlap each other.