简体   繁体   中英

Formatting issue from reading in text from text file in Python?

So, one of my assignments is to modify an existing trivia game so that each question has a certain point value. The game gets pretty much all the text from a text file.

But, I'm having some issues: For some reason, when I add a point value to the text file, it messes up the format of the program and doesn't print some of the lines.

When I run it I get this:

    Welcome to Trivia Challenge!

    An Episode You Can't Refuse

  On the Run With a Mamma

  You'll end up on the goat

  1 - 

  2 - If you wait too long, what will happen?

  3 - You'll end up on the sheep

  4 - 

What's your answer?: 

I'm not sure how to fix it. Any help?

Here's both the program file and the text file.

# Trivia Challenge
# Trivia game that reads a plain text file

import sys

def open_file(file_name, mode):
    """Open a file."""
    try:
        the_file = open(file_name, mode)
    except(IOError), e:
        print "Unable to open the file", file_name, "Ending program.\n", e
        raw_input("\n\nPress the enter key to exit.")
    sys.exit()
    else:
        return the_file

def next_line(the_file):
    """Return next line from the trivia file, formatted."""
    line = the_file.readline()
    line = line.replace("/", "\n")
    return line

def next_block(the_file):
    """Return the next block of data from the trivia file."""
       category = next_line(the_file)

       question = next_line(the_file)

       answers = []
       for i in range(4):
           answers.append(next_line(the_file))

       correct = next_line(the_file)
       if correct:
           correct = correct[0]

       explanation = next_line(the_file)

       point_val = next_line(the_file)

       return category, question, answers, correct, explanation, point_val

def welcome(title):
    """Welcome the player and get his/her name."""
    print "\t\tWelcome to Trivia Challenge!\n"
    print "\t\t", title, "\n"

def main():
    trivia_file = open_file("trivia2.txt", "r")
    title = next_line(trivia_file)
    welcome(title)
    score = 0


  # get first block
    category, question, answers, correct, explanation, point_val = next_block(trivia_file)

    while category:
        # ask a question
        print category
        print question
        for i in range(4):
            print "\t", i + 1, "-", answers[i]

        # get answer
        answer = raw_input("What's your answer?: ")

        # check answer
        if answer == correct:
            print "\nRight!",
            score += int(point_val)
        else:
            print "\nWrong.",
        print explanation
        print "Score:", score, "\n\n"

        # get next block
        category, question, answers, correct, explanation, point_val = next_block(trivia_file)

    trivia_file.close()

    print "That was the last question!"
    print "You're final score is:", score

main()  
raw_input("\n\nPress the enter key to exit.")

Text File (trivia2.txt)

An Episode You Can't Refuse

On the Run With a Mamma

If you wait too long, what will happen?

You'll end up on the sheep

You'll end up on the cow

You'll end up on the goat

You'll end up on the emu

A lamb is just a young sheep.

5

The Godfather Will Get Down With You Now

Let's say you have an audience with the Godfather of Soul. How would it be /smart

to address him?

Mr. Richard

Mr. Domino

Mr. Brown

Mr. Checker

10

James Brown is the Godfather of Soul.

That's Gonna Cost Ya

If you paid the Mob protection money in rupees, what business would you most

likely be insuring?

Your tulip farm in Holland

Your curry powder factory in India

Your vodka distillery in Russian

Your army knife warehouse in Switzerland

The Rupee is the standard monetary unit of India.

15

Keeping It the Family

If your mother's father's sister's son was in "The Family," how are you related to the mob?

By your first cousin once removed

By your first cousin twice removed

By your second cousin once removed

By your second cousin twice removed

Your mother's father's sister is her aunt -- and her son is your mother's first cousin. Since you and your mother are exactly one generation apart,her first cousin is your first cousin once removed.

20

A Maid Man

If you were to literally launder your money, but didn't want the green in your bills to run, what temperature should you use?

Hot

Warm

Tepid

Cold

According to my detergent bottle, cold is best for colors that might run.

25

I'm not entirely sure what problem you're having, so I'm going to offer you some general comments on your code, in hopes that a better approach will lead you to a better result.

In general, when doing I/O, try to open and close the file as close together as possible so you don't forget to close it, and so the whole program is easier to debug. Python makes this really easy for you if you can use the with statement as a context manager .

with open('filename.txt', 'r') as filename:
    some_var = filename.read()

After this block, filename is automatically closed for you, and some_var still has its entire contents as a string.

Second, while I think it's really cool that you're using functions in this way to abstract bits of your code (this is a worthwhile approach!), I think you should abstract things that are a bit more specific to your problem set. For instance,

def open_file(file_name, mode):
    """Open a file."""
    try:
        the_file = open(file_name, mode)
    except(IOError), e:
        print "Unable to open the file", file_name, "Ending program.\n", e
        raw_input("\n\nPress the enter key to exit.")
        sys.exit()
    else:
        return the_file

This function of yours takes a filename as a parameter and a mode argument and tries to open a file, and deals with an IOError in case it can't be opened. Sounds an awful lot like the built-in open , doesn't it? So just use that! If you need to handle the IOError , you can do that in a normal try / except block, but sometimes it's OK to just let it bubble up. After all, your program isn't really handling the exception, it's just reporting it then exiting, which is exactly what would have happened had you not caught it. (Additionally, it would be more proper to re-raise the Exception or at least print your error message to sys.stderr , but that's another story.)

The last thing I want to impart to you is about data structures. When I see your data blocks, here's what I see:

{
    'category': line1,
    'question': line2,
    'answers': [line3, line4, line5, line6],
    'correct_answer': line7,
    'points': int(line7.strip()),
}

Each block is a dict grouping one set of data for a question. If you stored this as q you could then call q['category'] , q[answers][0] , and the like. This groups things together in a more natural way than your tuple (which also requires you to repeat the line category, question, answers, correct, explanation, point_val = next_block(trivia_file) ). Notice I have also grouped the answers into a list -- it's a list of answers! You can put each such dict in a list (a list of dicts), then you have your whole set of trivia questions. You can even randomize the order by using random.shuffle on the whole list!

Try reorganizing your file so that you do one thing at a time. Read the file, get what you want from it, then be done with it . Don't stretch the read operation over the entire script. Parse out the questions, store them somewhere useful (hint: have you thought about making this a class?), then be done with it . Then loop through the already structured questions and ask away. This will make your programs easier to debug and your life easier. Might even help with what you have now. :)


Quick Example

"""Trivia challenge example"""

from __future__ import print_function, with_statement

import sys


questions = []
with open('trivia_file.txt', 'r') as trivia_file:
    title = trivia_file.readline()
    line = trivia_file.readline()
    while line:
        q = {}
        q['category'] = line
        q['question'] = trivia_file.readline()
        if q['question'].endswith('/'):
            q['question'] = q['question'][:-1] + trivia_file.readline()
        q['answers'] = [trivia_file.readline() for i in range(4)]
        q['correct'] = trivia_file.readline()
        q['explanation'] = trivia_file.readline()
        q['points'] = int(trivia_file.readline())
        questions.append(q)
        line = trivia_file.readline()

I was actually thinking you might read it in something like this. There are certainly prettier ways to iterate through a file in Python, but for you every line is not meaningful, every several lines is, so this is arguably clearer. (Also you have to deal with that bad line continuation syntax; better if that wasn't there, but I don't think you established the file formatting.)

Just read the file in, parse its contents, and move on. Now it's in memory and will close in the background. You're ready to play trivia. All the dicts I described before are grouped in a nice long list now, so you can just randomize them:

import random
# if the questions are supposed to stay in order skip this step
random.shuffle(questions)

then play the game by iterating over them:

for question in questions:
    print('Next category: ', question['category'])
    print('Q: ', question['question'])
    print('The possible answers are:')
    for i in range(4):
        print('{}. {}'.format(i+1, question['answers'][i]))
    # etc...

This will ask each question once. Once you reach the end of the list, you are out of questions, so it's time for the game to end!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM