Quiz - Викторина
Quiz - викторина или тест, программа с тестовыми вопросами.
Наш вид компьютерной викторины будет состоять из окна приветствия и нескольких вопросов, по очереди выводимых в окне.
Для выполнения цели: нужно уметь разбивать задачу на шаги и выполнять их в дальнейшем.
Будем придумывать, записывать и выполнять шаги по мере решения.😉
Step 1 - Шаг 1: приветствие
Создадим окно приветствия.
Для подключения библиотек tkinter используем рекомендованный формат подключения:
from tkinter import *
from tkinter.ttk import *
2
Создадим пустое окно с названием «My quiz».
Создадим рамку - LabelFrame, с названием «Generate screen» для наглядной визуализации. Далее все элементы будут создаваться в этой рамке:
frm = LabelFrame(text="Generate screen")
frm.pack()
2
Виджеты первого окна приветствия создадим отдельной функцией с параметром, в котором будет передаваться сам фрейм. В Label добавим текст приветствия: «Welcome to my quiz!n Press start to continue…». Последовательность символов n - означает, что следующий текст будет выводиться с новой строки. Добавив метку - Label и кнопку. Для которых укажем родительский элемент, переданный в функцию параметром el:
def first_screen(el):
Label(el, text='Welcome to my quiz!\n Press "Start" to continue...').pack()
Button(el, text="Start", command=lambda e=el: ask_question(e)).pack()
2
3
Для вызова функции поле создания окна и фрейма в вызовем функцию командой:
first_screen(frm)
Результат выполнения:
Step 2 - Шаг 2: меняем содержание фрейма
Теперь создадим функцию с параметром, которая будет отображать вопросы с вариантами ответов. Вызываться эта функция будет кнопкой в которой задана команда: command=lambda e=el: ask_question(e). Имя функции будет соответственно: ask_question(el):
def ask_question(el):
for widget in el.winfo_children():
widget.destroy()
Label(el, text="Здесь могла быть Ваша реклама! \n Или вопрос с вариантами ответов.").pack()
2
3
4
При вызове этой функции происходит следующее:
- функция принимает аргумент, которым является основной виждет LabelFrame;
- функция for перебирает все вложенные элементы в этот фрейм ранее и удаляет их;
- далее создаем новые элемент метку - Label(text=»Здесь могла быть Ваша реклама! n Или вопрос с вариантами ответов.»)
Результат выполнения, после нажатия кнопки:
Step 3 - Шаг 3: вопрос с ответами
Предположим первый вопрос с вариантами ответов: Вопрос:
Какие виждеты используют для вывода текста с возможностью его редактирования? Which widgets using to display text with the ability to edit it?
Ответы:
- Canvas
- Listbox
- Entry
- Text
- Label
Для сохранения результата наших ответов, после строк импорта создадим переменную с пустым массивом (листом), в котором будем сохранять ответы:
from tkinter import *
from tkinter.ttk import *
answers = []
...
2
3
4
5
Внесем изменения в функцию def ask_question(el): Для вопроса будем использовать виджет метку - Label():
def ask_question(el):
for widget in el.winfo_children():
widget.destroy()
question = Label(el, text="Which widgets using to display text with the ability to edit it?").pack()
2
3
4
5
А для вариантов ответа используем флажки - Checkbutton(), и у каждого флажка должна быть своя переменная. Выберем для неё тип переменной BooleanVar(), и хранить её будем в массиве answer. Чтобы добавить переменную в массив будем использовать метод .append(…) с параметром задающим тип переменной BooleanVar():
answers.append(BooleanVar())
ch_1 = Checkbutton(el, text="Canvas", variable=answers[0], onvalue=1, offvalue=0).pack(anchor=W)
2
Остальные варианты ответа добавьте самостоятельно, используя копировать-вставить (copy-paste). Привязка новых элементов обязательно должна быть к передаваемому фрейм элементу el. Результат выполнения:
Step 4 - Шаг 4: проверка ответов
Создадим функцию проверки ответов check(), после объявленной переменной answer, которая будет перебирать массив (лист) answer:
...
answers = []
def check():
for i in answers:
print(i.get())
...
2
3
4
5
6
7
В конце функции def ask_question(el): создадим кнопку «Next >>», которая вызывает функцию проверки:
button_next = Button(el, text="Next >>", command=check).pack()
Пример результата вывода в консоль, который только отражает какие флажки были выбраны:
False
True
False
True
False
2
3
4
5
Для сохранения итоговых баллов создадим переменную points и переменную true_answers в которой будет храниться строка, состоящая из 0 и 1 (пример: 000110, где длинна это количество предлагаемых ответов, а 1 обозначают какие ответы правильные):
...
answer = []
points = 0
true_answers = "10110"
...
2
3
4
5
Для проверки выбранных ответов с правильными изменим check() функцию. Для одновременного перебора двух списков параллельно можно воспользоваться функцией zip():
...
for t, a in zip(true_answers, answers):
print(bool(t), a.get())
...
2
3
4
Переменная t будет перебирать список true_answers, переменная a - answers. После преобразования bool(int(t)) в булевый тип, пример вывода в консоль:
True False
False False
True True
True True
False False
2
3
4
5
Осталось вписать условие сравнения для подсчета результата. За каждый правильный ответ будем увеличивать баллы на 1 в результате неправильного уменьшать на 1, если вариант ответа не выбран, то баллы не изменяются:
def check(el):
global points
for t, a in zip(true_answers, answers):
if bool(int(t)) and bool(int(t)) == a.get():
points += 1
elif bool(int(t)) != a.get():
points -= 1
print(points)
points = 0 # для обнуления результата при пересчете
2
3
4
5
6
7
8
9
Пример вывода в консоль:
-5
Step 5 - Шаг 5: вывод баллов в окно
Для вывода результата в окно продолжим изменять функцию check(), она должна принимать параметр, а именно фрейм в который выводится результат:
...
def check(el):
...
2
3
А также нужно изменить кнопку «Next >>»:
button_next = Button(el, text="Next >>", command=lambda e=el: check(e)).pack()
При запуске программы все должно работать как и ранее.
Теперь вместо строки print(points) пишем код очищающий фрейм:
for widget in el.winfo_children():
widget.destroy()
2
А затем добавляем метку - Label() который выводит, например: «Ваш результат: -4 балла», количество баллов соответствует подсчету после ответа.
Упражнения
Добавьте на последней форме кнопку «Try again», которая будет предлагать выполнение программы сначала.
Создайте переменную типа лист, в которой последовательно хранятся вопрос, ответы и правильная вариация ответов:
q1 = ["Which widgets using to display text with the ability to edit it?",
"Canvas",
"Listbox",
"Entry",
"Text",
"Label",
"10110"]
2
3
4
5
6
7
Измените программу так, чтобы данные для генерации вопросов брались из этой переменной. Желательно использовать срезы и перебор циклом.
Добавьте переменную с вопросом и ответами, с использованием дополнительного символа перед строкой:
«?» - означает вопрос, «+» - означает правильный ответ, «-» - означает неправильный ответ, «10110» - последовательность правильных вариантов вычеркиваем.
q2 = [«?What widgets using for positioning other widgets?»,
«-Button», «-Radiobutton», «+Frame», «-Text», «+LabelFrame»]
2
Добавьте этот вопрос в форму, с последующим отображением и подсчетом общего результата.
- Добавьте любой вопрос с ответами, с последующим отображением и подсчетом результатов.