2
\$\begingroup\$

I was told that I might get some feed back about the code below. I'm learning and need some criticism.

My initial question was how to save users answers and tally them up to display number correct/wrong.

import random
import os

if __name__=='__main__':

    books=['Genesis', 'Exodus', 'Leviticus', 'Numbers', 'Deuteronomy', 'Joshua',
   'Judges', 'Ruth', 'I Samuel', 'II Samuel', 'I Kings', 'II Kings',
   'I Chronicles', 'II Chronicles', 'Ezra', 'Nehemiah', 'Esther', 'Job', 'Psalms',
   'Proverbs', 'Ecclesiastes', 'Song of Solomon', 'Isaiah', 'Jeremiah',
   'Lamentations', 'Ezekiel', 'Daniel', 'Hosea', 'Joel', 'Amos', 'Obadiah',
   'Jonah', 'Micah', 'Nahum', 'Habakkuk', 'Zephaniah', 'Haggai', 'Zechariah',
   'Malachi', 'Matthew', 'Mark', 'Luke', 'John', 'Acts', 'Romans', 'I Corinthians',
   'II Corinthians', 'Galatians', 'Ephesians', 'Philippians',
   'Colossians', 'I Thessalonians', 'II Thessalonians', 'I Timothy', 'II Timothy',
   'Titus', 'Philemon', 'Hebrews', 'James', 'I Peter', 'II Peter', 'I John',
   'II John', 'III John', 'Jude', 'Revelation']

Title = "{0:^78}".format("Welcome to the Bible book quiz!\n\n")



seleCtion = raw_input(" The Bible has a number of " + str(len(books)) + " books.\n   Select Next to see them below:\n" + "{0:^78}".format("[1]Next    [2]Exit\n") )

if seleCtion == '1':

 #This section displays the books of the Bible and their indexes.
   count = 1
   indexMap = {}

    for i, bname in enumerate(books):
        print '\n{0:3d}. {1}'.format(count, bname)
        indexMap[count] = i
        count +=1


elif seleCtion == '2':
    print Title
    print "\n Let's start the quiz:\n\n\n"


else:
    print 'You must select 1 or 2'



mydict_book = {'Genesis':1, 'Exodus':2, 'Leviticus':3, 'Numbers':4, 'Deuteronomy':5, 'Joshua':6,
   'Judges':7, 'Ruth':8, 'I Samuel':9, 'II Samuel':10, 'I Kings':11, 'II Kings':12,
   'I Chronicles':13, 'II Chronicles':14, 'Ezra':15, 'Nehemiah':16, 'Esther':17, 'Job':18, 'Psalms':19,
   'Proverbs':20, 'Ecclesiastes':21, 'Song of Solomon':22, 'Isaiah':23, 'Jeremiah':24,
   'Lamentations':25, 'Ezekiel':26, 'Daniel':27, 'Hosea':28, 'Joel':29, 'Amos':30, 'Obadiah':31,
   'Jonah':32, 'Micah':33, 'Nahum':34, 'Habakkuk':35, 'Zephaniah':36, 'Haggai':37, 'Zechariah':38,
   'Malachi':39, 'Matthew':40, 'Mark':41, 'Luke':42, 'John':43, 'Acts':44, 'Romans':45, 'I Corinthians':46,
   'II Corinthians':47, 'Galatians':48, 'Ephesians':49, 'Philippians':50,
   'Colossians':51, 'I Thessalonians':52, 'II Thessalonians':53, 'I Timothy':54, 'II Timothy':55,
   'Titus':56, 'Philemon':57, 'Hebrews':58, 'James':59, 'I Peter':60, 'II Peter':61, 'I John':62,
   'II John':63, 'III John':64, 'Jude':65, 'Revelation':66}    



#new_dict = dict.fromkeys(books, counter)
#print new_dict




while 1:
    try:
        #This section starts the random book selection index match
        user_sel = []


        print '\n\n\n Here are the first 5 books in the quiz: \n'    
        sampler =random.sample(books, 5)
        first = str(sampler[0])
        second = str(sampler[1])
        third = str(sampler[2])
        fourth = str(sampler[3])
        fifth = str(sampler[4])
        user_sel = mydict_book[first], mydict_book[second], mydict_book[third], mydict_book[fourth], mydict_book[fifth]
        num_sampler = random.sample(user_sel, 5)

        print sampler
        print '\nMatch the correct numeric position below:'
        print '\n', num_sampler

        samp1 = int(raw_input('\nWhich number is ' + sampler[0] +': '))
        samp2 = int(raw_input('Which number is ' + sampler[1] +': '))
        samp3 = int(raw_input('Which number is ' + sampler[2] +': '))
        samp4 = int(raw_input('Which number is ' + sampler[3] +': '))
        samp5 = int(raw_input('Which number is ' + sampler[4] +': '))


        # taking the the users answer and finding the resultant book
        # need to put an if statement condition for !< 1 and ! < 66
        answer1=books[samp1-1]
        answer2=books[samp2-1]
        answer3=books[samp3-1]
        answer4=books[samp4-1]
        answer5=books[samp5-1]

        # taking the book and finding the numeric value associated with it


        right1 = mydict_book[answer1]
        right2 = mydict_book[answer2]
        right3 = mydict_book[answer3]
        right4 = mydict_book[answer4]
        right5 = mydict_book[answer5]



        #display what my answers yield
        print '\nYour Answers yield:\n'
        print "1. " + str(answer1) 
        print "2. " + str(answer2) 
        print "3. " + str(answer3)
        print "4. " + str(answer4)
        print "5. " + str(answer5)

        #takes the random books converts them to strings
        first = str(sampler[0])
        second = str(sampler[1])
        third = str(sampler[2])
        fourth = str(sampler[3])
        fifth = str(sampler[4])

        # print the numeric value and string value of the correct answers.         
        print "\nThe Correct Answers are:\n"
        print sampler[0] + " - " , mydict_book[first], tstmnt
        print sampler[1] + " - " , mydict_book[second], tstmnt
        print sampler[2] + " - " , mydict_book[third], tstmnt
        print sampler[3] + " - " , mydict_book[fourth], tstmnt
        print sampler[4] + " - " , mydict_book[fifth], tstmnt


        continue


except ValueError:
    break
\$\endgroup\$
3
\$\begingroup\$
import random
import os

if __name__=='__main__':

    books=['Genesis', 'Exodus', 'Leviticus', 'Numbers', 'Deuteronomy', 'Joshua',

The python style guide recommends that global constants be in ALL_CAPS. There is no reason to put such assignments inside if __name__ == '__main__'

Title = "{0:^78}".format("Welcome to the Bible book quiz!\n\n")

Why is this outside of the __main__ bit? You should probably put it all in a function.

seleCtion = raw_input(" The Bible has a number of " + str(len(books)) + " books.\n   Select Next to see them below:\n" + "{0:^78}".format("[1]Next    [2]Exit\n") )

What with the capital C in the middle?

if seleCtion == '1':

 #This section displays the books of the Bible and their indexes.
   count = 1
   indexMap = {}

    for i, bname in enumerate(books):
        print '\n{0:3d}. {1}'.format(count, bname)
        indexMap[count] = i
        count +=1

What are you trying to do here... count always equals i + 1.

elif seleCtion == '2':
    print Title
    print "\n Let's start the quiz:\n\n\n"

Doesn't 2 mean exit?

else:
    print 'You must select 1 or 2'

Should you go back and make them try again?

mydict_book = {'Genesis':1, 'Exodus':2, 'Leviticus':3, 'Numbers':4, 'Deuteronomy':5, 'Joshua':6,
   'Judges':7, 'Ruth':8, 'I Samuel':9, 'II Samuel':10, 'I Kings':11, 'II Kings':12,
   'I Chronicles':13, 'II Chronicles':14, 'Ezra':15, 'Nehemiah':16, 'Esther':17, 'Job':18, 'Psalms':19,
   'Proverbs':20, 'Ecclesiastes':21, 'Song of Solomon':22, 'Isaiah':23, 'Jeremiah':24,
   'Lamentations':25, 'Ezekiel':26, 'Daniel':27, 'Hosea':28, 'Joel':29, 'Amos':30, 'Obadiah':31,
   'Jonah':32, 'Micah':33, 'Nahum':34, 'Habakkuk':35, 'Zephaniah':36, 'Haggai':37, 'Zechariah':38,
   'Malachi':39, 'Matthew':40, 'Mark':41, 'Luke':42, 'John':43, 'Acts':44, 'Romans':45, 'I Corinthians':46,
   'II Corinthians':47, 'Galatians':48, 'Ephesians':49, 'Philippians':50,
   'Colossians':51, 'I Thessalonians':52, 'II Thessalonians':53, 'I Timothy':54, 'II Timothy':55,
   'Titus':56, 'Philemon':57, 'Hebrews':58, 'James':59, 'I Peter':60, 'II Peter':61, 'I John':62,
   'II John':63, 'III John':64, 'Jude':65, 'Revelation':66}    

You shouldn't need to repeat the list of books again.

#new_dict = dict.fromkeys(books, counter)
#print new_dict

Don't leave commented dead code in your code

while 1:

use while True

    try:
        #This section starts the random book selection index match
        user_sel = []


        print '\n\n\n Here are the first 5 books in the quiz: \n'    
        sampler =random.sample(books, 5)
        first = str(sampler[0])
        second = str(sampler[1])
        third = str(sampler[2])
        fourth = str(sampler[3])
        fifth = str(sampler[4])

Don't go around creating variables like first, second, third, fourth. If you have a number of variables like it should virtually always be a list.

        user_sel = mydict_book[first], mydict_book[second], mydict_book[third], mydict_book[fourth], mydict_book[fifth]
        num_sampler = random.sample(user_sel, 5)

Why are you selecting 5 books at random from a selection of 5 books?

        print sampler
        print '\nMatch the correct numeric position below:'
        print '\n', num_sampler

        samp1 = int(raw_input('\nWhich number is ' + sampler[0] +': '))
        samp2 = int(raw_input('Which number is ' + sampler[1] +': '))
        samp3 = int(raw_input('Which number is ' + sampler[2] +': '))
        samp4 = int(raw_input('Which number is ' + sampler[3] +': '))
        samp5 = int(raw_input('Which number is ' + sampler[4] +': '))

In programming, if you find yourself repeating things like the question above, it means you need a loop or a function.

        # taking the the users answer and finding the resultant book
        # need to put an if statement condition for !< 1 and ! < 66
        answer1=books[samp1-1]
        answer2=books[samp2-1]
        answer3=books[samp3-1]
        answer4=books[samp4-1]
        answer5=books[samp5-1]

        # taking the book and finding the numeric value associated with it


        right1 = mydict_book[answer1]
        right2 = mydict_book[answer2]
        right3 = mydict_book[answer3]
        right4 = mydict_book[answer4]
        right5 = mydict_book[answer5]

Use books.index(answer1) rather then creating mydict_book dictionary.

        #display what my answers yield
        print '\nYour Answers yield:\n'
        print "1. " + str(answer1) 
        print "2. " + str(answer2) 
        print "3. " + str(answer3)
        print "4. " + str(answer4)
        print "5. " + str(answer5)

        #takes the random books converts them to strings
        first = str(sampler[0])
        second = str(sampler[1])
        third = str(sampler[2])
        fourth = str(sampler[3])
        fifth = str(sampler[4])

        # print the numeric value and string value of the correct answers.         
        print "\nThe Correct Answers are:\n"
        print sampler[0] + " - " , mydict_book[first], tstmnt
        print sampler[1] + " - " , mydict_book[second], tstmnt
        print sampler[2] + " - " , mydict_book[third], tstmnt
        print sampler[3] + " - " , mydict_book[fourth], tstmnt
        print sampler[4] + " - " , mydict_book[fifth], tstmnt


        continue

Since this is the end of the loop, it does nothing to say continue here.

except ValueError:
    break

If your catching exception like this and its not clear where the exception might come from, add a comment explaining. Or make it clearer where the exception is coming from.

Here is my version of what you did.

import random
BOOKS = [
    'Genesis', 'Exodus', 'Leviticus', 'Numbers', 'Deuteronomy', 'Joshua', 
    'Judges', 'Ruth', 'I Samuel', 'II Samuel', 'I Kings', 'II Kings', 
    'I Chronicles', 'II Chronicles', 'Ezra', 'Nehemiah', 'Esther', 'Job',
    'Psalms', 'Proverbs', 'Ecclesiastes', 'Song of Solomon', 'Isaiah', 
    'Jeremiah', 'Lamentations', 'Ezekiel', 'Daniel', 'Hosea', 'Joel', 'Amos',
    'Obadiah', 'Jonah', 'Micah', 'Nahum', 'Habakkuk', 'Zephaniah', 'Haggai',
    'Zechariah', 'Malachi', 'Matthew', 'Mark', 'Luke', 'John', 'Acts', 
    'Romans', 'I Corinthians', 'II Corinthians', 'Galatians', 'Ephesians',
    'Philippians', 'Colossians', 'I Thessalonians', 'II Thessalonians', 
    'I Timothy', 'II Timothy', 'Titus', 'Philemon', 'Hebrews', 'James',
    'I Peter', 'II Peter', 'I John', 'II John', 'III John', 'Jude', 
    'Revelation'
]

def print_all_books():
    for count, bname in enumerate(BOOKS):
        print '{0:3d}. {1}'.format(count + 1, bname)

def get_response(prompt, valid_responses):
    while True:
        text = raw_input(prompt)
        try:
            value = int(text)
        except ValueError:
            print "Please enter a number"
        else:
            if value not in valid_responses:
                print "Please enter one of: {0}".format(valid_responses)
            else:
                return value


def bible_book_quiz():
    print "{0:^78}".format("Welcome to the Bible book quiz!\n\n")

    while True:
        number_of_questions = get_response('Enter the number of questions you wanna be asked (0 to quit): ', range(10))

        if number_of_questions == 0:
            break


        books_selection = random.sample(BOOKS, number_of_questions)
        positions = sorted([BOOKS.index(book) + 1 for book in books_selection])

        print
        print
        print
        print 'Here are the first {0} books in the quiz: '.format(number_of_questions)

        #This section starts the random book selection index match

        print "\t", books_selection
        print 'Match the correct numeric position below:'
        print "\t", positions

        answers = []
        for book in books_selection:
            answers.append( get_response('Which number is {0}: '.format(book), positions) )

        #display what my answers yield
        print
        print 'Your Answers yield:'
        for i, answer in enumerate(answers):
            print "{0}. {1}".format(i+1, BOOKS[answer-1])

        # print the numeric value and string value of the correct answers.         
        print "\nThe Correct Answers are:\n"
        print positions
        for book in books_selection:
            print "{0} - {1}".format(book, BOOKS.index(book) + 1)

        print

def main():
    print "The Bible has a number of {0} books.".format(len(BOOKS))
    print "Select a menu option:"
    print "[1] Print All Books [2] Start Quiz"
    option = get_response('', [1,2])

    if option == 1:
        print_all_books()
    elif option == 2:
        bible_book_quiz()

if __name__=='__main__':
    main()
\$\endgroup\$
  • \$\begingroup\$ Thanks for explaining the why? I really needed that! \$\endgroup\$ – suffa Sep 6 '11 at 23:11

Not the answer you're looking for? Browse other questions tagged or ask your own question.