본문 바로가기

Studying/Python

24. miniProject(14) - QuizBrain (feat.tkinter, requests)

이번엔 앞서 만든 Quiz 프로그램에서 좀 더 변형을 시키는 프로젝트를 만들려고 한다. 

 

우리가 전에 만들었던 퀴즈의 질문은 직접 타이핑해서 만들어놓은 dict 형태의 파이썬 파일이었다. 

 

따라서 단순히 key, value 만을 사용해서 쉽게 불러와 사용할 수 있었다. 

( 참고 내용 게시물 )

https://headingtocoding.tistory.com/16?category=1042348

 

14. miniProject(5) - Quiz 프로그램

이번엔 일련의 참, 거짓 퀴즈를 풀고 정답인지 아닌지 나타내는 프로그램을 작성해보기로 하자. 이번엔 파일을 4개로 구분해서 진행하자. 먼저 quiz 내용을 저장해놓을 data.py을 만든다. data.py에는

headingtocoding.tistory.com

 

 

이번에는 직접 서버에서 요청을 보내고 받아 json 형식의 data 로 저장하고 이를 활용하는 방식을 사용하려고 한다. 

 

크게 퀴즈 데이터를 가져올 data.py , 받아온 data 를 질문과 답 형태로 구분할 question_model.py ,

프로그램의 규칙혹은 기능을 다룰 quiz_brain.py , 전반적인 tkinter 의 UI 를 다룰 ui.py , 그리고 전체를 관리할 main.py 로 구분해서 진행하도록 하자. 

 


 

먼저 data.py 이다. 

 

data.py

 

data.py 에서 가장 중요한 것은 우리가 해당 사이트로 API 요청을 보내 응답을 받아와야한다는 것이다. 

 

먼저 requests 라이브러리를 import 한다.

 

이 라이브러리는 매우 직관적인 API 를 제공하는데 우리가 사용할 HTTP 요청에 따라 GET, POST, PUT, DELETE 중 골라서 사용하면 된다. 

 

우리가 퀴즈를 가져올 Open Trivia Database 에서 원하는 자료를 받아오려면 설정 변수가 필요하다. 이는 해당 사이트의 api를 참고하면 알 수 있다. 

( open trivia db api 참고 사이트 )

https://opentdb.com/api_config.php

 

Open Trivia DB

Free to use, user-contributed trivia questions!

opentdb.com

 

우리가 먼저 만들어놓은 퀴즈는 질문 10개, 참 거짓 문제, 분야는 21(스포츠) 로 설정하고 parameters 로 지정했다. 

( 이는 언제든지 변경할 수 있다. )

 

이렇게 만든 parametersparams의 속성으로 입력하여 requests.get 을 사용하여 해당사이트로부터 자료를 받아 response 에 저장한다. 

 

그 요청을 json 형식으로 다시 data 로 저장하는데 이 때 data 를 출력해보면 여러 list 가 중첩된 dict 형태로 되어 있는 것을 확인할 수 있다.

 

이를 위해 우리가 필요한 부분 즉, 결과 results 부분만 따로 question_data 로 저장한다. 

 

여기서 가져온 result를 사용할 때 우리는 Question class 를 만들어서 사용할 것이다. 

 

question_model.py

question_model.py 에서 새로운 class  Question 를 선언한다.

 

딱히 특별하게 선언한 것은 없고, q_text,q_answer 만 인자로 설정해준다.  

 

즉 우리가 data로 받아온 dict 형태의 데이터를 q_text, q_answer이란 변수를 필요로 하는 Question 클래스 형식에 맞게 넣으면 우리가 원하는 목록의 퀴즈 형식이 생성되는 것이다. 

 


 

이제 quiz_brain.py 차례이다. 

 

quiz_brain.py

 

초반부에서 구상한대로 quiz_brain.py 에선 전반적으로 퀴즈의 형식, 형태에 대해 설정할 것이다. 

 

이를 위해 우리는 QuizBrain class 를 새로 생성할 것이다. 

 

QuizBrain 의 초기 선언에서 기본속성으로 question_numberscore 는 0으로, question_list 는 변수로 받을 q_list 로, current_questionNone 상태로 설정한다. 

( 여기서 우리가 변수로 받는 q_list 에 Question 클래스를 통해 만들어진 객체가 들어가면 되겠지요? )

 

 

추가적 메소드로 still_has_questions 를 지정한다. 이는 말그대로 변수로 들어온 question_list 의 질문 갯수와 현재 질문 번호를 비교하는 메소드로 boolean 값을 return 한다. 

 

두번째 메소드로는 next_question 이다. question_number 에 맞는 질문을 가져올 것이다. (초기 question_number 는 0 )

 

자동으로 question_number 를 1씩 증가하고, 현재 문제를 html.unescape 처리 해준다. 

 

html.unescape(s) 는 문자열 s의 모든 이름과 숫자 등을 해당 유니코드 문자로 변환하는 기능를 가진다. 

( 우리가 api 를 통해 받아온 결과를 인식 못하는 경우를 대비해 작성 )

 

그렇게 되면 우린 현재 question_number 에 해당하는 q_text 질문을 받아와 우리가 원하는 형태의 질문을 return 하는 것이다. 

 

마지막 메소드는 check_answer 이다. 이는 user_answer 를 변수로 받는다. ( 우리가 분제를 보고 답하는 user_answer )

 

correct_answer 로 정답을 받아오고 우리가 나중에 inputuser_answer 와 비교하여 if 문을 사용해 score 를 조절한다. 

 


이제 UI 차례이다. 

 

이 역시 QuizInterface 라는 새로운 class 를 생성하면서 시작한다. 

 

우리가 위에서 만들었던 quiz_brain 을 변수로 받아오고 원하는 사이즈에 맞게 tkinter 를 사용하여 UI 구성을 한다. 

 

 

우리가 새로운 클래스를 선언하고 그 내부에 여러 메소드를 작성하는 주된 목적은 관리와 사용의 편리를 위한 것이다. 

 

클래스로 선언하고 main.py 에서 클래스를 불러와 실행시키면  main.py 의 코드는 깔끔하면서 가독성이 높다. 

 


 

이제 마지막 main.py 를 통해 앞서 만들어놨던 모든것을 import 해서 마무리하자. 

 

main.py

 

앞서 api 로 받은 question_data 에서 문제를 뽑아서 담을 빈 listquestion_bank 를 만든다. 

 

그리고 for 문을 통해 question_data 에서 질문은 question_text,  정답은 question_answer 로 뽑고, 이 두 변수를 

Question 클래스의 두 인자로 넣어 new_question 이라는 객체를 생성한다. 

 

그리고 이렇게 나온 new_question 을 아까 만든 빈 list 였던 question_bankappend 한다. 

 

이제 list 형식의 question_bankQuizbrain 클래스의 변수로 넣어 quiz 라는 객체를 만들고 

 

quiz 라는 객체를 다시 QuizInterface 의 변수로 넣어 quiz_ui 라는 객체를 만든다. 

 

그리고 실행하게 되면 quiz_uitkinter 가 실행되어 프로그램이 나타나게 된다. 

 

실행화면