Stage 2: Build a MadLib game
Introduction to serious programming
Here are some of the topics covered in this lesson:
- Computers: whilst most machines are built with a single purpose in mind, like a toaster, a computer can do almost anything as long as it receives the right program. It is a general purpose machine
- Programs: put simply, these are really a list of instructions that a computer has to perform
- Programming languages: natural languages are ambiguous in nature. This is why we had to create new languages to tell computers exactly what to do
- Interpreter: it acts as a translator between the programming language and the computer
- Python: it is a interpreted programming language.
- Grammar: as natural languages can be confusing, we also had to come up with a new type of grammar to describe programming language. The one that is still being used today is the Backus-Naur form. (John Backus was of the fathers or Fortran).
- Python expressions: using the Backus-Naur form, we can progressively replace "non-terminal items" with other "non-terminal items" or "terminal items". This means that Python expressions have to obbey a certian syntax (a line cannot start with a whitespace, for example).
Variables
- Python variables can store values such as strings or numbers
- To get a variable to store a value, you must assign the value to it using the assignment operator (=)
- The assignment operator is not to be confused with the equal sign that states that two sides of an expression are equal. The way to eproduce the equal sign in Python is by using ==
- variables are useful in the sense that they allow the programmer to different thongs depending on the value of the variable
- The +: the difference between 2+2 and "2"+"2"? is that it will add two numbers but concatenate two strings. Note that the + operator cannot concatenate a string and a number. The way to do this is to turn the number into a string using the str function
Functions
- What is a function: a function takes an input, works on it and returns an input (sometimes)
- There is a difference between making and using a function. To use a function you first have to declare it, i.e. making it by telling the computer how it works. You can then use it
- Functions help programmers to avoid repetiton by adopting a modular design. If each function is designed properly, they can be stacked on top of each other so that the output of one function can be used as the input of another one. This saves programmers from having to redesign each funtion every time.
- A useful function to know: randint, which generates a random integer. We first have to use an import statement: "from random import randint". Then we can use the function as follows: randint(low,high)
- What happens if a function doesn't have a return statement?: it does not return any value.
Strings
Strings are a way to convey information. They can also be indexed, i.e. each character in the string has a number attached to it, which makes it convenient for manipulation. We can use the square brackets and the find function to perform certain operations:
- string [n]: will retrieve the character at index n (counting from 0 to n from left to right or -1 to n-1 from right to left
- string [n:o]: will return the portion of the string in between the two index number
- string [:n]: will return the part of the string from the beginning of it to index n
- string [n:]: will return the part of the string from index n to the end of the string
- string.find(substring,index_parameter): will return the index location of the first occurence of the substring in the string. If the substring os not found, it will return -1. The index_parameter is optional and tells the computer to start its search at a particular location.
- string.replace(old,new,max): will replace a string with another. If max is used, the change will only apply to the first x instances in the string
- string.split(): will split a string in list based on single character separation. You can insert something in the parentheses to use as a basis for the split: (",") for example.
- string.join(): will do the opposite.
While Loops
While loops keep executing as long as their test condition is true. This a very convenient way of avoiding repetition and hard-coding. It is formulated as follows:
while (condition): rest of your code here.
You can also insert the break command to exit the loop before it ends. This is useful to break an infinite loop.
Debugging
There will always be errors in the code. It is just a fact of life that has to be acknowledged and dealt with. Debugging should really be treated as part of the developement process and as such, be handled with a systematic approach:
- Examine error messages when programs crash: the last line is usually the most understandable
- Work from example code: it is easy to find example code on the internet and use it as starting point. However...
- Make sure examples work!
- Check (print) intermediate results: you can use the print statement to make sure that the content of your variables evolves as expected as the program executes
- Keep and compare old versions: you can either comment out the old version or use GIT to capture the exact state of your code at a certain point in time
For lists and For loops
Lists are a way of structuring and packaging data. They can contain strings, numbers and other lists. I suspect that they are also called arrays.
Lists can be accessed, concatenated, appened to or have elements removed.
- To access the elements of a list, you can use their index (stating with 0):print list[0]
- If the element that you want to access is in a list within a list, you can use:print list[0][0]
- You can concatenate list by using code such as list1 = list1 + [5,6]This creates a new list that includes 5 & 6.
- Also, you can append to a list using list1.append([5, 6]). In this case, 5 & 6 have been added as a list
- Finally, you can delete from a list by using the del like in the reverse mad libs exercise: del game_answers[0]
Lists can also be altered by mutation and aliasing.
- Mutation: as we saw, lists can be altered. So can strings.
- Aliasing: when a string gets created its value assigned to a variable then another variable, two string objects get created. The difference with lists is that when a list is created and its value assigned to two variables, both variables still refer to the same string object. So amending the list for one, amends it for the other too. I strongly suspect that this has something to do with pointers...
Then there the "For" loops that enable you to iterate throught the list
On a final note about Python, you should be aware that the language is subject to formating rules reffered to as "PEP 8" and that you can check
your code here: pep 8 checker
How to solve problems
- Don't panic
- Understand the problem, i.e. inputs and outputs
- What are the valid inputs?
- Have you defined the validity criteria of the imput?
- Are you testing the validity of the input?
- How are you going to represent the inputs, i.e. how will they be packaged? Seperate values, objects...?
- What are the outputs?
- What are the relationships between the inputs and the outputs? You should work it out by working through some examples that you can use as test cases later on.
- Understand how a human systematically solves the problem
- Write the algorithm in pseudo code
- See if there is any way to simplify the way the product is being handled. The first attempt is rarely the best one as we often try to take shortcuts that will come back to bite us at some point in time... Use a simpe mechanical solution
- Don't optimise too early...
- Develop incrementally by testing often