#πŸ”’ Difficulty in Updating the correct value for a difficulty's completion status in a Python Quiz Gam

140 messages Β· Page 1 of 1 (latest)

velvet thicketBOT
#

@opaque cairn

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

opaque cairn
#
class DifficultySelection(BaseFrame):
    def __init__(self, parent, subject):
        super().__init__(parent)
        self.subject = subject
        game_frame = parent.frames.get("game")
        if game_frame:
            self.completed = game_frame.completed.get(subject, {'Easy': False, 'Medium': False, 'Hard': False})
        else:
            self.completed = {'Easy': False, 'Medium': False, 'Hard': False}
        self.create_widgets()

    def create_widgets(self):
        ttk.Label(self, text='Select Difficulty', justify="center").grid(row=0, column=2)

        easy_completed = self.check_if_easy_completed()
        mid_completed = self.check_if_mid_completed()
        hard_completed = self.check_if_hard_completed()

        ttk.Button(self, text='Easy', command=lambda: self.start_game('Easy'), padding=15).grid(row=1, column=2)
        ttk.Button(self, text='Medium', command=lambda: self.start_game('Medium'), padding=15, state='normal' if easy_completed else 'disabled').grid(row=2, column=2)
        ttk.Button(self, text='Hard', command=lambda: self.start_game('Hard'), padding=15, state='normal' if easy_completed and mid_completed else 'disabled').grid(row=3, column=2)

    def check_if_easy_completed(self):
        return self.completed['Easy']

    def check_if_mid_completed(self):
        return self.completed['Medium']
    
    def check_if_hard_completed(self):
        return self.completed['Hard']

    def start_game(self, difficulty):
        self.master.start_game(self.subject, difficulty)
#
    def next_question(self):
        self.current_question += 1

        if self.current_question < len(self.question_set):
            self.show_question()
        else:
            difficulty = self.master.frames["game"].difficulty
            self.completed[difficulty] = True
            messagebox.showinfo(f"Quiz Completed", f"Quiz Completed! Current Score: {self.scores[difficulty]}")
            self.master.show_frame("menu")
#

I've been trying to figure out what it is exactly that is causing the program to not properly update the completion state of a difficulty in this python script

I've tried to troubleshoot it and the main problem seems to be that

opaque cairn
opaque cairn
covert wasp
#

is game_frame suppoed to be the previous "game session"?

opaque cairn
#

yes

covert wasp
#

so it's resetting because of this self.completed = game_frame.completed.get(subject, {'Easy': False, 'Medium': False, 'Hard': False})

opaque cairn
#

I believe so, I've been trying to fix it on my own for the past 2 hours but I just can't seem to properly update it's value without breaking the program

covert wasp
#

ok what is that line supposed to do?

#

nvm i see

#

so the subject is supposed to give the difficulty

#

right?

opaque cairn
#

yes

covert wasp
#

so if there's no "subject" difficulty in self.completed, it just resets it, which is whats happening

#

shouldn't self.completed = game_frame.completed just work?

opaque cairn
#

-I haven't tried that yet;;

covert wasp
#

if your goal is to carry the difficulty status from the last question i think that should work

opaque cairn
#

It worked but it also gave the completion status of the easy difficulty to the other subjects and not just the one specific subject the user took

covert wasp
#

oh okay, can you explain how the game works?

#

if every question or session has different subjects and youre using only one self.completed dict for every subject, then its normal that it updates for every subject

opaque cairn
#

The game is basically a quiz game that allows the user to select one subject and the easy difficulty at the start. After completing the easy difficulty of one selected subject, the subsequent difficulty (medium) should then be unlocked for the user to take, then after completing both difficulties, it would then allow the user to take the hardest difficulty.

covert wasp
#

okay i see

#

so we need to store the completed status for each subject

#

self there is the game frame right?

#

if so, i'd turn the self.completed dict from {'Easy': False, 'Medium': False, 'Hard': False} into somthing like {"Subject1": {'Easy': False, 'Medium': False, 'Hard': False}, "Subject2": {'Easy': False, 'Medium': False, 'Hard': False}}

#

so now you have difficulty status for each subject

#

and now this would work self.completed = game_frame.completed.get(subject, {'Easy': False, 'Medium': False, 'Hard': False})

#

wait no

covert wasp
#

you'd then have to pass subject into each function that checks the difficulty is completed

#
def check_if_easy_completed(self, subject):
        return self.completed[subject]['Easy']
#

or just use self.subject yeah

#
def check_if_easy_completed(self):
        return self.completed[self.subject]['Easy']
opaque cairn
#

Hmmm I see I see, alright. Let me try to implement the changes you've suggested to see if that would resolve the problem ^^

covert wasp
#

alright

opaque cairn
#

After implementing the changes, I tried running the program

After completing the easy difficulty on the English subject, I got this error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "c:\Users\James\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test.py", line 52, in <lambda>
    ttk.Button(self, text="English", padding=20, command=lambda: self.open_difficulty_selection('English')).grid(row=1, column=1)
                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test.py", line 60, in open_difficulty_selection
    self.master.frames["difficulty"] = DifficultySelection(self.master, subject)
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test.py", line 86, in __init__
    self.create_widgets()
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test.py", line 91, in create_widgets
    easy_completed = self.check_if_easy_completed()
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test.py", line 100, in check_if_easy_completed
    return self.completed[self.subject]['Easy']
           ~~~~~~~~~~~~~~^^^^^^^^^^^^^^
KeyError: 'English'
covert wasp
#

how does your code look now?

#

most likely you didn't add the subjects to your self.completed

opaque cairn
#
class DifficultySelection(BaseFrame):
    def __init__(self, parent, subject):
        super().__init__(parent)
        self.subject = subject
        game_frame = parent.frames.get("game")
        if game_frame:
            self.completed = game_frame.completed
        else:
            self.completed = {
                'English': {'Easy': False, 'Medium': False, 'Hard': False},
                'Math': {'Easy': False, 'Medium': False, 'Hard': False},
                'Filipino': {'Easy': False, 'Medium': False, 'Hard': False},
                'Science': {'Easy': False, 'Medium': False, 'Hard': False},
                'Social Sciences': {'Easy': False, 'Medium': False, 'Hard': False}
            }
        self.create_widgets()

    def create_widgets(self):
        ttk.Label(self, text='Select Difficulty', justify="center").grid(row=0, column=2)

        easy_completed = self.check_if_easy_completed()
        mid_completed = self.check_if_mid_completed()
        hard_completed = self.check_if_hard_completed()

        ttk.Button(self, text='Easy', command=lambda: self.start_game('Easy'), padding=15).grid(row=1, column=2)
        ttk.Button(self, text='Medium', command=lambda: self.start_game('Medium'), padding=15, state='normal' if easy_completed else 'disabled').grid(row=2, column=2)
        ttk.Button(self, text='Hard', command=lambda: self.start_game('Hard'), padding=15, state='normal' if (easy_completed and mid_completed) else 'disabled').grid(row=3, column=2)

    def check_if_easy_completed(self):
        return self.completed[self.subject]['Easy']

    def check_if_mid_completed(self):
        return self.completed[self.subject]['Medium']
    
    def check_if_hard_completed(self):
        return self.completed[self.subject]['Hard']

    def start_game(self, difficulty):
        self.master.start_game(self.subject, difficulty)
covert wasp
#

uhhhhhhhhh idk why that doesnt work

#

one sec

opaque cairn
#

alrighty ^^

covert wasp
#

somehow 'English' is not in the dict, altho you put it there

#

!e

completed = {
                'English': {'Easy': False, 'Medium': False, 'Hard': False},
                'Math': {'Easy': False, 'Medium': False, 'Hard': False},
                'Filipino': {'Easy': False, 'Medium': False, 'Hard': False},
                'Science': {'Easy': False, 'Medium': False, 'Hard': False},
                'Social Sciences': {'Easy': False, 'Medium': False, 'Hard': False}
            }

print(completed['English']['Easy'])
velvet thicketBOT
#

@covert wasp :white_check_mark: Your 3.12 eval job has completed with return code 0.

False
covert wasp
#

this works

opaque cairn
#

aaaaa

do you think it has something to do with this:

    def start_game(self, subject, difficulty):
        subject_index = {'English': 0, 'Math': 1, 'Science': 2, 'Filipino': 3, 'Social Sciences': 4}[subject]
        difficulty_index = {'Easy': 0, 'Medium': 1, 'Hard': 2}[difficulty]
        question_set = Quiz_Data[subject_index][difficulty_index]

        game_frame = Game(self, question_set)
        game_frame.difficulty = difficulty  
        self.frames["game"] = game_frame
        self.show_frame("game")

or this

    def __init__(self, parent):
        super().__init__(parent)
        ttk.Label(self, text="Select Subject", justify="center", padding=20).grid(row=0, column=1)
        ttk.Button(self, text="English", padding=20, command=lambda: self.open_difficulty_selection('English')).grid(row=1, column=1)
        ttk.Button(self, text="Math", padding=20, command=lambda: self.open_difficulty_selection('Math')).grid(row=2, column=1)
        ttk.Button(self, text="Filipino", padding=20, command=lambda: self.open_difficulty_selection('Filipino')).grid(row=3, column=1)
        ttk.Button(self, text="Science", padding=20, command=lambda: self.open_difficulty_selection('Science')).grid(row=4, column=1)
        ttk.Button(self, text="Social Sciences", padding=20, command=lambda: self.open_difficulty_selection('Social Sciences')).grid(row=5, column=1)
        ttk.Button(self, text="Back", padding=20, command=lambda: parent.show_frame("menu")).grid(row=6, column=1)
covert wasp
#

maybe

#

if any of those messes with self.completed

#

or with self.subject

#

can you put a print(self.completed) in check_if_easy_completed(self) and run it again?

#

to see what it has

opaque cairn
#

alright, one second

#
{'English': {'Easy': False, 'Medium': False, 'Hard': False}, 'Math': {'Easy': False, 'Medium': False, 'Hard': False}, 'Filipino': {'Easy': False, 'Medium': False, 'Hard': False}, 'Science': {'Easy': False, 'Medium': False, 'Hard': False}, 'Social Sciences': {'Easy': False, 'Medium': False, 'Hard': False}}
{'Easy': True, 'Medium': False, 'Hard': False}
covert wasp
#

do a print(self.subject) there too

opaque cairn
#
English
{'English': {'Easy': False, 'Medium': False, 'Hard': False}, 'Math': {'Easy': False, 'Medium': False, 'Hard': False}, 'Filipino': {'Easy': False, 'Medium': False, 'Hard': False}, 'Science': {'Easy': False, 'Medium': False, 'Hard': False}, 'Social Sciences': {'Easy': False, 'Medium': False, 'Hard': False}}
covert wasp
#

waaaaa

#

that should be working so bad

tulip folio
#

Any landing page please

opaque cairn
tulip folio
#

Yes

covert wasp
#

well, self.completed[self.subject][β€˜Easy’] gives a KeyError

#

altho english is literally there in self.completed

tulip folio
#

I mean redirect pages that I can use for my marketing

covert wasp
#

and self.subject is β€˜English’

opaque cairn
# tulip folio Yes

I'm sorry, I'm unfamiliar with the term, I'm pretty new to programming

opaque cairn
#

could it have something to do with how I get my data for the quiz

import tkinter as tk
from tkinter import messagebox, ttk
from QuizData import Quiz_Data
English = [English_Easy, English_Mid, English_Hard]
Math = [Math_Easy, Math_Mid, Math_Hard]
Science = [Science_Easy, Science_Mid, Science_Hard]
Filipino = [Filipino_Easy, Filipino_Mid, Filipino_Hard]
Social_Sciences = [Social_Sciences_Easy, Social_Sciences_Mid, Social_Sciences_Hard]

Quiz_Data = [English, Math, Science, Filipino, Social_Sciences]
covert wasp
#

is self.subject a string?

opaque cairn
#

apparently it is

covert wasp
#

where are you calling your DifficultySelection object?

opaque cairn
#
class Main(BaseFrame):
    def __init__(self, parent):
        super().__init__(parent)
        ttk.Label(self, text="Select Subject", justify="center", padding=20).grid(row=0, column=1)
        ttk.Button(self, text="English", padding=20, command=lambda: self.open_difficulty_selection('English')).grid(row=1, column=1)
        ttk.Button(self, text="Math", padding=20, command=lambda: self.open_difficulty_selection('Math')).grid(row=2, column=1)
        ttk.Button(self, text="Filipino", padding=20, command=lambda: self.open_difficulty_selection('Filipino')).grid(row=3, column=1)
        ttk.Button(self, text="Science", padding=20, command=lambda: self.open_difficulty_selection('Science')).grid(row=4, column=1)
        ttk.Button(self, text="Social Sciences", padding=20, command=lambda: self.open_difficulty_selection('Social Sciences')).grid(row=5, column=1)
        ttk.Button(self, text="Back", padding=20, command=lambda: parent.show_frame("menu")).grid(row=6, column=1)

    def open_difficulty_selection(self, subject):
        self.master.frames["difficulty"] = DifficultySelection(self.master, subject)
        self.master.show_frame("difficulty")
covert wasp
#

is it still giving you the error?

#

if you run it

#

because it really shouldn't be giving the error

opaque cairn
#

yes

English
{'English': {'Easy': False, 'Medium': False, 'Hard': False}, 'Math': {'Easy': False, 'Medium': False, 'Hard': False}, 'Filipino': {'Easy': False, 'Medium': False, 'Hard': False}, 'Science': {'Easy': False, 'Medium': False, 'Hard': False}, 'Social Sciences': {'Easy': False, 'Medium': False, 'Hard': False}}
English
{'Easy': True, 'Medium': False, 'Hard': False}
Exception in Tkinter callback
Traceback (most recent call last):
  File "c:\Users\James\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test.py", line 52, in <lambda>
    ttk.Button(self, text="English", padding=20, command=lambda: self.open_difficulty_selection('English')).grid(row=1, column=1)
                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test.py", line 60, in open_difficulty_selection
    self.master.frames["difficulty"] = DifficultySelection(self.master, subject)
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test.py", line 86, in __init__
    self.create_widgets()
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test.py", line 91, in create_widgets
    easy_completed = self.check_if_easy_completed()
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test.py", line 102, in check_if_easy_completed
    return self.completed[self.subject]['Easy']
           ~~~~~~~~~~~~~~^^^^^^^^^^^^^^
KeyError: 'English'
covert wasp
#

oh

opaque cairn
#

it gives me the error after the first run it makes

covert wasp
#

we got something

#

can you show your next_question function?

opaque cairn
#
    def next_question(self):
        self.current_question += 1

        if self.current_question < len(self.question_set):
            self.show_question()
        else:
            difficulty = self.master.frames["game"].difficulty
            self.completed[difficulty] = True
            messagebox.showinfo(f"Quiz Completed", f"Quiz Completed! Current Score: {self.scores[difficulty]}")
            self.master.show_frame("menu")
covert wasp
#

self.completed[difficulty] = True should be self.completed[self.subject][difficulty] = True

#

now every time you edit the difficulty completion status, youll need to say in which subject it updates

#

any other occurrences of self.completed in your code?

opaque cairn
#

yes, i need to change all of them right?

covert wasp
#

yeah

opaque cairn
covert wasp
#

oh

#

so you game already has a self.completed dict

#

i guess?

opaque cairn
#

should I remove it?

covert wasp
#

idk

#

would it be possible to see the whole code?

#

!pastebin

velvet thicketBOT
#
Pasting large amounts of code

If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/

After pasting your code, save it by clicking the Paste! button in the bottom left, or by pressing CTRL + S. After doing that, you will be navigated to the new paste's page. Copy the URL and post it here so others can see it.

opaque cairn
covert wasp
#

yea

#

yeah well the problem is definitely in that line in the __init__ of Game()

opaque cairn
#
class Game(BaseFrame):
    def __init__(self, parent, question_set):
        super().__init__(parent)
        self.question_set = question_set
        self.current_question = 0
        self.scores = {'Easy': 0, 'Medium': 0, 'Hard': 0}  
        self.completed = {'Easy': False, 'Medium': False, 'Hard': False} #<<<< This one ?
        self.create_widgets()
covert wasp
#

ok

#

so

#

yeah i think doing

self.completed = {
                'English': {'Easy': False, 'Medium': False, 'Hard': False},
                'Math': {'Easy': False, 'Medium': False, 'Hard': False},
                'Filipino': {'Easy': False, 'Medium': False, 'Hard': False},
                'Science': {'Easy': False, 'Medium': False, 'Hard': False},
                'Social Sciences': {'Easy': False, 'Medium': False, 'Hard': False}
            }

in there should work

#

the Game() is called once right?

opaque cairn
#

yes

#

I've implemented the change you've said, it's now giving me a different error message 😞 :

Exception in Tkinter callback
Traceback (most recent call last):
  File "c:\Users\James\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test.py", line 181, in next_question
    self.completed[self.subject][difficulty] = True
                   ^^^^^^^^^^^^
AttributeError: 'Game' object has no attribute 'subject'
covert wasp
#

well you need to get the subject

#

that it is in rn

#

add a subject attribute to your Game object

#

and declare it in the start_game function

#

so now you can access the subject of the questions in your Game Object

opaque cairn
#

I don't think I'm doing it right, my brain is a bit mushy, would you mind showing me how?

covert wasp
#

well, you need to pass it in the init function of course

#

def __init__(self, parent, subject, question_set):

#

then IN your start_game function

#
def start_game(self, subject, difficulty):
        subject_index = {'English': 0, 'Math': 1, 'Science': 2, 'Filipino': 3, 'Social Sciences': 4}[subject]
        difficulty_index = {'Easy': 0, 'Medium': 1, 'Hard': 2}[difficulty]
        question_set = Quiz_Data[subject_index][difficulty_index]

        game_frame = Game(self, subject, question_set)
        game_frame.difficulty = difficulty  
        self.frames["game"] = game_frame
        self.show_frame("game")
#

you add subject in the Game() call

#

because that is how objects and functions work in python

opaque cairn
#

Did I do it correctly?

covert wasp
#

well

#

the parameters you passed need to be in the same order as theyre specified in init

opaque cairn
#

Ah I think I get what you mean, so like this?

covert wasp
#

yep

opaque cairn
#

I ran it and I got another error;;

Exception in Tkinter callback
Traceback (most recent call last):
  File "c:\Users\James\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test 2.py", line 95, in <lambda>
    ttk.Button(self, text='Easy', command=lambda: self.start_game('Easy'), padding=15).grid(row=1, column=2)
                                                  ^^^^^^^^^^^^^^^^^^^^^^^
TypeError: DifficultySelection.start_game() missing 1 required positional argument: 'difficulty'
covert wasp
#

wait

#

one minute

#

yeah do that

#
def start_game(self, difficulty):
        self.master.start_game(self.subject, difficulty)```
#

keep it like this

opaque cairn
#

Alrighty

#
Exception in Tkinter callback
Traceback (most recent call last):
  File "c:\Users\James\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test 2.py", line 95, in <lambda>
    ttk.Button(self, text='Easy', command=lambda: self.start_game('Easy'), padding=15).grid(row=1, column=2)
                                                  ^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test 2.py", line 111, in start_game
    self.master.start_game(self.subject, difficulty)
  File "c:\Users\James\OneDrive\Desktop\Finals Project 2\Test 2.py", line 25, in start_game
    game_frame = Game(self, question_set)
                 ^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: Game.__init__() missing 1 required positional argument: 'question_set'

T~T

covert wasp
#

yeah you need to add the subject to your Game() call

opaque cairn
#

OH MY GOD YES

#

IT FINALLY WORKS

#

THANK YOU SO MUCH FOR BEING PATIENT WITH HELPING ME!!

velvet thicketBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.