The Trivia API The Quizzler App

Trivia Question API 과제

1️⃣ import requests

  • 물음표 앞까지가 API

1

2


2️⃣ 파라미터 넣어주기


3️⃣ 예외처리


4️⃣ JSON을 사용해 데이터 받기


5️⃣ 원하는 키값을 받아 객체 저장



HTML 개체 unescape

3

HTML Entities 사이트


  • Freeformatter 툴을 이용해서 우리가 API로부터 받는 HTML 결과를 unescape할 수 있음

Freeformatter 사이트


1️⃣ import html 모듈


2️⃣ unescape 메소드 사용

4



클래스 기반 Tkinter UI

1️⃣ class 키워드 사용, init생성

  • 파스칼 표기법


2️⃣ init 안에 사용자 인터페이스 생성

  • window
  • label
  • canvas
    (캔버스에 뭔가를 추가할 때는 언제나 x,y값을 인자로 넣어줘야 함)
  • button


true_image = PhotoImage(file=”images/true.png”)에 self가 붙지 않는 이유
true_image는 QuizInterface 클래스의 init 메서드 내에서만 사용되는 지역 변수이다.
해당 메서드 내에서만 존재하며, 메서드 외부에서는 접근할 수 없음
self가 붙는 변수는 클래스의 인스턴스 변수로, 클래스의 다른 메서드나 인스턴스 외부에서도 해당 변수에 접근할 수 있다.
true_image 변수의 경우, init 메서드 내에서 이미지를 로드한 후 바로 self.true_button을 만드는 데 사용되었고,
이후에는 true_image에 대한 참조가 필요하지 않기 때문에 인스턴스 변수로 만들 필요가 없음
self.true_image로 만들면 해당 이미지는 객체가 존재하는 동안 계속 메모리에 남아있게 된다.
true_image로 만들면 init 메서드가 종료되면서 해당 이미지의 참조도 사라지게 되지만,
이미지 자체는 self.true_button에서 계속 사용되고 있기 때문에 문제 없이 동작한다.
임시적으로만 사용되는 변수는 지역 변수로 선언하는 것이 메모리 관리 측면에서 효율적임


3️⃣ main.py에 import

5



파이썬 타이핑 & GUI에서 다음 질문 표시하기

1️⃣ 콘솔에 input으로 띄운 질문을 함수의 반환값으로

6


2️⃣ main.py에서 QuizInterface에 quiz넣어주고 init안에 매개변수 추가

7

  • import QuizBrain
  • 데이터 타입 넣어주기

8


3️⃣ 캔버스 업데이트


4️⃣ 메소드 init안에서 호출

9



파이썬 타이핑 : Type Hints와 화살표

동적 타이핑: 변수를 생성 후 데이터형 변경

x = int(2.59)


  • 오류를 덜 발생하기 위해 다루는 데이터형
  • 디버깅 시간을 줄여줌

10



정답 확인하고 버튼 적용

  • 메소드 생성

11



플레이어에게 피드백 주기, 점수 유지하기, 버그 수정

1️⃣check_answer메소드 수정

12


2️⃣ give_feedback메소드 생성

13


3️⃣ 점수 유지 기능

14


4️⃣ 질문 개수 끝나면 알리기

15

16


5️⃣ 게임을 마치면 버튼 기능 끄고 배경 흰색으로 돌리기

17



Final Code

main.py

from question_model import Question
from data import question_data
from quiz_brain import QuizBrain
from ui import QuizInterface

question_bank = []
for question in question_data:
    question_text = question["question"]
    question_answer = question["correct_answer"]
    new_question = Question(question_text, question_answer)
    question_bank.append(new_question)


quiz = QuizBrain(question_bank)
quiz_ui = QuizInterface(quiz)

while quiz.still_has_questions():
    quiz.next_question()

print("You've completed the quiz")
print(f"Your final score was: {quiz.score}/{quiz.question_number}")



quiz_brain.py

import html


class QuizBrain:

    def __init__(self, q_list):
        self.question_number = 0
        self.score = 0
        self.question_list = q_list
        self.current_question = None

    def still_has_questions(self):
        return self.question_number < len(self.question_list)

    def next_question(self):
        self.current_question = self.question_list[self.question_number]
        self.question_number += 1
        q_text = html.unescape(self.current_question.text)
        return f"Q.{self.question_number}: {q_text}"
        # user_answer = input(f"Q.{self.question_number}: {q_text} (True/False): ")
        # self.check_answer(user_answer)

    def check_answer(self, user_answer):
        correct_answer = self.current_question.answer
        if user_answer.lower() == correct_answer.lower():
            self.score += 1
            # print("You got it right!")
            return True
        else:
            # print("That's wrong.")
            return False

        # print(f"Your current score is: {self.score}/{self.question_number}")
        # print("\n")



ui.py

from tkinter import *
from quiz_brain import QuizBrain

THEME_COLOR = "#375362"


class QuizInterface:

    def __init__(self, quiz_brain: QuizBrain):
        self.quiz = quiz_brain
        self.window = Tk()
        self.window.title("Quizzler")
        self.window.config(padx=20 ,pady=20, bg=THEME_COLOR)

        self.score_label = Label(text="Score: 0", fg="white", bg=THEME_COLOR)
        self.score_label.grid(row=0, column=1)

        self.canvas = Canvas(width=300, height=250, bg="white")
        self.question_text = self.canvas.create_text(
            150,
            125,
            width=280,
            text="Some Question Text",
            fill=THEME_COLOR,
            font=("Arial", 20, "italic")
        )
        self.canvas.grid(row=1, column=0, columnspan=2, pady=50)

        true_image = PhotoImage(file="images/true.png")
        self.true_button = Button(image=true_image, highlightthickness=0, command=self.true_pressed)
        self.true_button.grid(row=2, column=0)

        false_image = PhotoImage(file="images/false.png")
        self.false_button = Button(image=false_image, highlightthickness=0, command=self.false_pressed)
        self.false_button.grid(row=2, column=1)
        self.get_next_question()

        self.window.mainloop()

    def get_next_question(self):
        self.canvas.config(bg="white")
        if self.quiz.still_has_questions():
            self.score_label.config(text=f"Score:{self.quiz.score}")
            q_text = self.quiz.next_question()
            self.canvas.itemconfig(self.question_text, text=q_text)
        else:
            self.canvas.itemconfig(self.question_text, text="You've reached the end of the quiz.")
            self.true_button.config(state="disabled")
            self.false_button.config(state="disabled")

    def true_pressed(self):
        self.give_feedback(self.quiz.check_answer("True"))

    def false_pressed(self):
        self.give_feedback(self.quiz.check_answer("False"))

    def give_feedback(self, is_right):
        if is_right:
            self.canvas.config(bg="green")
        else:
            self.canvas.config(bg="red")
        self.window.after(1000, self.get_next_question)