my_list = list()
with open(“my_file.txt”, “r”) as my_file:
for line in my_file.read():
my_list.append(line) print(my_list)
> > Hello from Python!
With the file contents saved in a list, we can easily access it later in our program whenever we need it.
CSV Files
Python comes with a built-in module for working with CSV files. CSV stands for comma separated value. It is a file format commonly used in Microsoft Excel: a program for creating spreadsheets. A comma in a CSV file is called a delimiter. Every piece of data
separated by a comma represents a cell in Excel. Each line of the CSV file represents a row in Excel. Here is an example of the contents of a csv file:
# my_file.csv one, two, three four, five, six
You could load this file into excel and one , two and three would each get their own cells in the first row of the spreadsheet; and four , five and six would each get their own cells in the second row of the spreadsheet.
We can use a with statement to open a CSV file like the example from the previous
section, but inside the with statement we need to use the csv module to convert our file object
into a csv object. The csv module has a method called writer that accepts a file object and a delimiter and returns a csv object with a method called writerow we can use to write to our CSV file:
# https://github.com/calthoff/tstp/blob/master/part_I/files/csv_files.py import csv
with open (‘ my_file.csv’ , ‘w’ ) as csvfile:
spamwriter = csv . writer(csvfile, delimiter = ',’) spamwriter . writerow([ ‘one’, ‘two’, ‘three’ ]) spamwriter . writerow([‘ four ’, ‘five’, ‘six’ ])
>>
The writerow method accepts a list as a parameter. Every item in the list gets written to the CSV file and each item is separated by the delimiter you passed to the writer method (in this case a comma). writerow only writes one row, so we have to call it twice to create two rows.
When you run this program, it will create a new file called my_file.csv and when you open the file with a text editor, it will look like this:
# my_file.csv on e, two, th ree four, five, six
If you load this file into Excel (or Google Sheets a free Excel alternative), the commas disappear, but one , two and three will each have their own cell in row one; and four , five and six will each have their own cell in row two.
We can also use the csv module to read the contents of a file. To read from a CSV file, first we pass in ‘r ’ to open as as the second parameter. This opens the file for reading only.
Instead of using the writer method like the previous example, we use the reader method, but still pass in the file path and a comma as the delineator.
reader returns an iterable we can iterate through to print each row. We can call the join method on a comma to add a comma in between each value to print the contents of the file like it appears in the original file:
# https://github.com/calthoff/tstp/blob/master/part_I/files/csv_files_ex2.py import csv
with open(‘my_file.csv’, ‘r ’) as csvfile:
spamreader = csv . reader(csvfile, delimiter = ',' ) for row in spamreader:
print ( ',' . join(row)) >> one,two,thre e
>> four, five, six
Challenge
Data persists when it outlives the program that created it. We can use files to persist data by writing the output of our programs to a file. Write a program that collects data from a user—
and saves it to a file—so the data persists.
Chapter 10. Bringing It All Together
In this chapter, we are going to combine the concepts we’ve learned so far to build a text-based game: the classic game Hangman. If you’ve never played Hangman, here's how it works. Player One picks a secret word and draws lines representing each letter in the word (we will use an underscore to represent each line). Player Two tries to guess the word one letter at a time. If Player Two guess a letter correctly, the corresponding underscore is
replaced with the correct letter. If Player Two guesses incorrectly, Player One draws a piece of a picture of a hangman (a person hanging). If Player Two completes the word before the picture of the hangman is drawn, they win, if not they lose. In our program the computer will be Player One, and the person playing the game will be Player Two. Are you ready to build Hangman?
Hangman
Here is the beginning of our hangman code:
#
https://github.com/calthoff/tstp/blob/master/part_I/bringing_it_all_together/hangman.py def hangman ():
word = "caat"
wrong_guesses = 0
stages = [ "" , "________ " , "| | " , "| 0 " , "| /|\ " , "| / \ " , "| " ]
letters_left = list (word)
score_board = [ '__' ] * len (word) win = False
print ( 'Welcome to Hang Man' )
First we create a function called hangman we can call to start the game. The word to guess is stored in the variable word (you can change the word the player has to guess by changing the variable). We use another variable wrong_guesses to keep track of how many incorrect letters the player has guessed.
stages is a list filled with strings we will use to draw our Hangman. When each string in the stages list is printed on a new line, a picture of a hangman forms. letters_left is a list made
up of each character in word . We will use it to keep track of which letters are left to guess in our word.
scoreboard is a list of strings used to keep track of the hints we display to the user e.g.,
“c __ t” if the word is “cat” . The initial value of score_board is calculated with [‘__’] * len(word) which returns a list made up of the number of underscores to start with. For example if the word is “cat” score_board starts as [“__”, “__”, “__”] .
Finally, we have a win variable that starts as False to keep track of whether the player has won the game yet or not. To start the game off we print Welcome to Hangman .
When you build a game, you normally use a loop that continues until the game is over.
Here is the loop we will use in our game:
while wrong_guesses < len (stages) - 1 : print ( ' \n ' )
guess = input ( "Guess a letter" ) if guess in letters_left:
character_index = letters_left.index(guess) score_board[character_index] = guess letters_left[character_index] = '$' else :
wrong_guesses += 1 print ( '' .join(score_board))
print ( ' \n ' .join(stages[ 0 : wrong_guesses + 1 ])) if '__' not in score_board:
print ( 'You win! The word was:' ) print ( ' ' .join(score_board)) win = True
break
Our loop continues as long as the variable wrong_guesses is less than the
len(wrong_guesses) - 1 . wrong_guesses keeps track of the number of wrong letters the user has guessed, so as soon as the user has guessed more wrong letters than the number of strings that make up the hangman, the game is over. The reason we subtract 1 is because the length function in Python does not count from 0 , it counts from 1 . In order to compensate for this, we have to subtract one, to compensate for the fact that length counts starting from 1 instead of 0 . The reason we want to count from 0 is because stages is a list, and we are going to be using wrong_guesses as an index to get the strings from stages and indexes start at 0 .
Inside our loop, we print a blank space to make our game look nice when it’s printed in the shell. Next we collect the player ’s guess with the built-in input function and store the value in the variable guess .
If guess is in letters_left (a variable from the beginning of our program that keeps track of the letters that haven’t been guessed yet), the player guessed correctly. If the player guessed correctly we need to update our score_board list, which we use later in the game to display the score. If the user guessed “c” , we want to change our score_board to look like
this: [“c”, “__”, “__”] . We use the index method on our letters_left list to get the first index of the letter that was guessed. We use that index to replace the underscore in score_board at the index with the correctly guessed letter. We have a problem though. Because index only returns the first index of the character we are looking for, our code will not work if word (the word the player is guessing) has more than one of the same character. To compensate for this, we modify letters_left by replacing the character that was just correctly guessed with a dollar sign so that the next time around the loop, if there is more than one letter in the word index will find second occurrence of the letter since the first occurrence of the letter was replaced by a dollar sign. If on the other hand the player guesses an incorrect letter, we simply increment wrong_guesses by 1 .
Next we print the scoreboard and print our hangman using our score_board and stages lists. To print the scoreboard, all we have to do is print '' .join(score_board) .
Printing the hangman is trickier. When each of the strings in our stages list is printed on a new line, a complete picture of a hangman is printed. We can easily create the entire hangman by printing ' \n ' .join(stages) . This connects each string in the stages list with a blank space ( \n ) . But we want to print our hangman at the stage we are currently at, which we accomplish by slicing our stages list. We start at stage 0 and slice up until whatever stage we are at (represented by the variable wrong_guesses ) plus one. The reason we add one, is because when you are slicing, the end slice does not get included in the results. This gives us only the strings we need to print the stage of the hangman we are currently on which we then print.
The last thing we do in our loop is check if the user has won the game If there are no more underscores in the score_board list, we know the user has guessed all the letters and won the game. If the user has won, we print that they won and we print the word they correctly guessed. We also set the variable win to True which is used when we break out of our loop.
Once we break out of our loop, if the user won, we do nothing, and the program is over.
If the user did not win, the variable win will be False . If that is the case we know the user lost the game and we print the full hangman, print “You lose!” followed by the word they incorrectly guessed:
if not win:
print ( ' \n ' .join(wrong_guesses[ 0 : stage]))
print ( 'You lose! The words was {}' .format(word)) hangman()
Here is our complete code:
#
https://github.com/calthoff/tstp/blob/master/part_I/bringing_it_all_together/hangman.py def hangman ():
stage = 0
wrong_guesses = [ "" , "________ " , "| | " , "| 0 " , "| /|\ " , "| / \ " , "| " ]
word = "cat"
score_board = [ '__' ] * len (word) win = False
print ( 'Welcome to Hang Man' )
while stage < len (wrong_guesses) - 1 : print ( ' \n ' )
guess = input ( "Guess a letter" ) if guess in word:
score_board[word.index(guess)] = guess else :
stage += 1
print (( ' ' .join(score_board)))
print ( ' \n ' .join(wrong_guesses[ 0 : stage + 1 ])) if '__' not in score_board:
print ( 'You win! The word was:' ) print ( ' ' .join(score_board)) win = True
break if not win:
print ( ' \n ' .join(wrong_guesses[ 0 : stage])) print ( 'You lose!' )
hangman()
Challenge
Building text-based games is a great way to improve your programming ability. Build another text-based game that interests you.
Chapter 11. Practice
“ The fool wonders, the wise man asks. ” — Benjamin Disraeli
If this is your first programming book, I recommend you spend time practicing before moving on to the next section. In this chapter, I provide exercises to help you get additional practice before moving on to the next section, resources to check out, and we cover how to get help if you get stuck.
Exercises
0. Create a text based game of your favorite sport.
0. Make up your own text based game. When I was starting out I built a fantasy based game based on Heroes of Might and Magic III
0. Build a text based magic 8 ball program where the user can shake a magic eight ball and get predictions about their future
0. Create a program that asks the user what kind of mood they are in and recommends a song.
0. Build a program that prints out ten brands and lets the user type them in. When they do, the program should print the brand’s trademark i.e., the user could type Nike and the program would print “Just do it.”
Read
0. http://programmers.stackexchange.com/questions/44177/what-is-the-single-most-effective-thing-you-did-to-improve-your-programming-skil
0. https://www.codementor.io/ama/0926528143/stackoverflow-python-moderator-martijn-pieters-zopatista