Jason Vignochi
Jason Vignochi

Reputation: 33

list indices must be integers not str ( easy answer probably)

I recently asked a question about the high scores issue on a previous post. This is a class project so it should be relatively simple. I am still new to this website so I am unsure how to cleanly post new revisions so if you have read part of this I apologize. This time I am just going to put the entire program here. Everything works except the high scores part. When I select to just check the high scores list before playing the game the output works nicely, however, after playing the game, returning to the main menu and then checking high scores again I get the error that

list indices must be integers not str

. I assume that means my original scores list is set up incorrectly but I'm not entirely sure. Here is the code and I truly appreciate the help. This site is fantastic for such.

import random
loop_game = True

while loop_game:
    questions= [
                {"question": "Who won the 2012 NFL Superbowl?",
                 "answers": ["Jacksonville Jaguars",
                            "Oakland Raiders",
                            "New York Giants",
                            "Baltimore Ravens"],
                 "correct": "4"},
                {"question": "Which song was at the top of the charts in early 2001, by OutKast?",
                 "answers": ["Bootylicious",
                             "Angel",
                             "Ms. Jackson",
                             "U Got It Bad"],
                "correct": "3"},
                {"question": "How many centimeters are one inch?",
                 "answers": ["2.12",
                             "2.54",
                             "3.24",
                             "3.38"],
                "correct": "2"}]

    scores=[{'initials': None,
             'score': -500}]

#main menu
    def main_menu():
        global loop_game
        print("""
***********************************************  
Welcome to The Greatest Trivia Show on Earth!!!
***********************************************
1. Play Game
2. High Scores
3. Credits
4. Instuctions
5. Quit
""")
        needs_input = True
        while needs_input:
          selection = input("Which Selection would you like? ")
          if selection == "1":
              play_game()
              needs_input = False
          elif selection == "2":
              display_scores()
              needs_input = False
          elif selection == "3":
              credits()
              needs_input = False
          elif selection == "4":
              instructions()
              needs_input == False
          elif selection == "5":
              needs_input = False
              loop_game = False
          else:
              print("\nSelect a valid option\n")

    def play_game():
        #definitions
        global total_points
        global questions
        loop_pa = True
        total_points = 3
        random.shuffle(questions)
        counter = 0
        #gets name in case of high score
        global hs_name
        hs_name = input("What are your initials?: ")


        #main play loop
        while counter < 2:
            for j in questions:
                counter += 1
                print("\n",j["question"])
                for i, choice in enumerate(j["answers"]):
                    print(str(i+1) + ". " + choice)
                answer = str(input("\nChoose an answer 1-4: "))
                if answer == j["correct"]:
                    print("\nGood job! You keep your precious points...this time!\n")
                else:
                    print("\nSorry, that is not correct. You lose one point.\n")
                    total_points -= 1
                    print("\nTotal Points: ",  total_points)

        #all questions have been read
        print("\nThat's it, your score is: ", total_points)

        #check/append best scores list
        best_scores()

        #keep playing loop
        while loop_pa:
            keep_playing = input("Play again?  (y, n) \n")
            if keep_playing == "y":
                print("\nAwesome! Here we go! \n\n")
                loop_pa = False
                play_game()
            elif keep_playing == "n":
                print("Ahh, too bad.  Thanks for playing!")
                loop_pa = False
                main_menu()
            else:
                print("Select a valid option\n")

    def best_scores():
        for i, score in enumerate(scores):
            if total_points > score['score']:
                scores[i:i+1] = {'initials': hs_name, 'score': total_points}
                del scores[5:]
                break

    def display_scores():
        print("HIGH\tSCORES")
        for score in scores:
            print(score['initials'], "\t", score['score'])

    def instructions():
        print("""

*************
Instructions
*************
The game is quite simple:  You start out with 12 points.
You lose a point for every incorrect answer.
If you get an answer correct, your score stays the same
and you move forward through the question set.  Try to
see how many points you can keep!
         """)
        main_menu()

    def credits():
        print("\nCreated by Jessica Gregg and Jason Vignochi\n")
        main_menu()


    main_menu()

edit: oh! The line the error is at is in the display_scores function at (line 119)

print(score['initials'], "\t", score['score'])

Upvotes: 2

Views: 10257

Answers (3)

cmd
cmd

Reputation: 5830

You are messing up your scores with best_scores(). After the first time through it looks like ['score', 'initials']. The slice assignment expects an iterable, and sure enough a dict iterates over its keys when used as an iterable. Try this, looks a little simpler (though I would probably just append and sort):

def best_scores():
    global scores
    for i, score in enumerate(scores):
        if total_points > score['score']:
            scores.insert(i, {'initials': hs_name, 'score': total_points})
            scores = scores[:5]
            break

my way:

from operator import itemgetter

def best_scores():
    global scores
    scores.append({'initials': hs_name, 'score': total_points})
    scores = sorted(scores, key=itemgetter('score'), reverse=True)[:5]

Upvotes: 2

CDspace
CDspace

Reputation: 2689

You defined scores as a list of a list by using [{}], so to reference it as it appears you want to, use scores[ 0 ][ 'initial' ], etc.

Upvotes: -1

abarnert
abarnert

Reputation: 365747

The problem is this line:

scores[i:i+1] = {'initials': hs_name, 'score': total_points}

When you replacing a subslice of a sequence, you have to replace it with another iterable. For example:

>>> a = [0, 1, 2, 3, 4]
>>> a[2:3] = [3] # fine
>>> a[2] = 3 # fine
>>> a[2:3] = 3
TypeError: can only assign an iterable

So, why isn't your code a TypeError? Because a dict actually is an iterable—it acts like a list of its keys. So, when you try to replace the sub-list [{'initials': old_name, 'score': old_score}] with the dictionary {'initials': new_initials, 'score': new_score}, what it actually sees is, effectively, ['initials', 'score'].

So, later on, when you get down to trying to print out the scores, one of them isn't a dict, it's the string 'initials'. And you're trying to use that as a dict, hence the error.

You can see this more easily if you print(scores) before and after calling best_scores, and print out each score in display_scores.

Upvotes: 2

Related Questions