Самая простая викторина на Python
Самая простая версия — это 3 одинаковых блока: вывести вопрос, получить ответ через input(), сравнить его с правильным и прибавить балл. Такой код пишется за 10 минут и сразу работает.
score = 0
answer = input("Сколько будет 7 * 8? ")
if answer == "56":
score += 1
answer = input("Сколько бит в одном байте? ")
if answer == "8":
score += 1
answer = input("Какая функция выводит текст? ")
if answer == "print":
score += 1
print("Баллов:", score)
Переменная score — счётчик баллов. Она создаётся до первого вопроса и увеличивается на 1 после каждого верного ответа. Обратите внимание: ответ сравнивается со строкой «56», а не с числом 56, ведь input всегда возвращает текст. Если написать answer == 56, условие никогда не выполнится, и ошибки при этом не будет — программа просто не начислит балл. Каждый верный ответ приносит ровно 1 балл, а неверный — 0, поэтому итоговая сумма баллов равна количеству правильных ответов.
У этой версии есть очевидный недостаток: для 20 вопросов придётся скопировать блок 20 раз. А если захочется изменить формат вывода, правку нужно будет повторить в каждом блоке. Это верный признак того, что пора заводить список и цикл.
Список вопросов и цикл for
Чтобы не копировать код, вопросы хранят в списке: каждый элемент — пара из текста вопроса и правильного ответа. Цикл for проходит по списку, и блок проверки пишется 1 раз.
questions = [
["Сколько будет 7 * 8?", "56"],
["Сколько бит в одном байте?", "8"],
["Какая функция выводит текст?", "print"],
]
score = 0
for q in questions:
answer = input(q[0] + " ")
if answer == q[1]:
score += 1
print("Баллов:", score, "из", len(questions))
Здесь q[0] — текст вопроса, q[1] — ответ. Функция len(questions) сама считает, сколько вопросов в списке, поэтому строку с результатом не нужно править, когда вопросов станет больше. Теперь, чтобы добавить вопрос, достаточно дописать одну строку в список, а логика программы не меняется. Такое разделение данных и кода — главная идея всего проекта. Если списки пока непривычны, загляните в урок о списках в Python.
Проверка ответа без придирок
Если сравнивать строки напрямую, ответ «Print» или «print » с пробелом засчитан не будет. Чтобы проверка была честной, ответ перед сравнением нормализуют: убирают пробелы, приводят к строчным буквам и заменяют «ё» на «е».
def normalize(text):
return text.strip().lower().replace("ё", "е")
print(normalize(" Ёлка "))
print(normalize("PYTHON") == "python")
елка
True
Правильные ответы в списке тоже стоит хранить в нормализованном виде — строчными буквами и без «ё». Иногда верных вариантов несколько: «7», «семь». Тогда вторым элементом пары делают список допустимых ответов и проверяют через in: if normalize(answer) in q[1]. Для вопросов с числовым ответом можно сравнивать числа, но только после проверки, что строка действительно состоит из цифр, иначе int() упадёт с ошибкой ValueError. Методы strip и lower описаны в официальной документации Python в разделе о строках. Подробнее о них — в статье про строки в Python.
Баллы, проценты и оценка
Итог викторины удобнее показывать не только числом баллов, но и процентом: процент — это баллы, умноженные на 100 и делённые на число вопросов. Для целого результата используют деление //.
score = 4
total = 5
percent = score * 100 // total
print(percent)
80
По проценту программа может выставить шуточную оценку. Пороги придумайте сами — ниже пример одной из возможных шкал, а не школьный стандарт.
| Процент верных | Условие в коде | Сообщение |
| 90–100 | percent >= 90 | Знаток! |
| 70–89 | percent >= 70 | Очень неплохо |
| 40–69 | percent >= 40 | Есть что повторить |
| 0–39 | ветка else | Попробуй ещё раз |
Условия проверяются сверху вниз через if и elif, поэтому во второй строке не нужно писать «и меньше 90»: если бы процент был 90 или выше, сработала бы первая ветка. Порядок здесь важен — если поставить проверку на 40 первой, все результаты от 40 до 100 получат одну и ту же оценку.
Перемешивание вопросов: random.shuffle
Чтобы при каждом запуске вопросы шли в новом порядке, список перемешивают функцией random.shuffle. Она меняет сам список и ничего не возвращает — это 1 строка без присваивания.
import random
questions = ["вопрос 1", "вопрос 2", "вопрос 3", "вопрос 4"]
random.shuffle(questions)
print(questions)
Классическая ошибка — написать questions = random.shuffle(questions). Функция вернёт None, и в переменной окажется пустое значение вместо списка: следующий цикл упадёт с TypeError. По официальной документации Python shuffle перемешивает «на месте»[1], поэтому присваивать результат не нужно. Если хочется задать только часть вопросов, после перемешивания возьмите срез questions[:5] — первые пять. Баллы после shuffle считаются так же: порядок вопросов на результат не влияет. Другие функции модуля разобраны в статье о модуле random.
Варианты ответов и словари
Если вопрос с вариантами ответа, удобнее хранить его словарём: ключ "text" — текст вопроса, "options" — список вариантов, "answer" — номер правильного. Тогда игрок вводит цифру, а не слово.
quiz = [
{"text": "Что выведет print(2 ** 3)?", "options": ["6", "8", "9"], "answer": 2},
{"text": "Сколько бит в байте?", "options": ["4", "8", "16"], "answer": 2},
]
points = 0
for item in quiz:
print(item["text"])
for i, option in enumerate(item["options"], start=1):
print(i, option)
choice = input("Номер ответа: ")
if choice == str(item["answer"]):
points += 1
print("Верных ответов:", points)
Функция enumerate нумерует варианты с единицы, чтобы игроку было привычно. Сравнение идёт строк: ввод «2» сравнивается с str(item["answer"]). Словари делают структуру понятной: через месяц не придётся вспоминать, что означает q[2], ведь в коде написано item["answer"]. В такой словарь легко добавить новые поля — подсказку, тему или стоимость вопроса в баллах. О ключах и значениях подробнее рассказано в уроке о словарях Python.
Как придумать хорошие вопросы
Хороший вопрос имеет 1 однозначный ответ, который можно проверить сравнением строк. «Что такое цикл?» для программы не годится, а «Сколько раз выполнится range(4)?» — подходит.
Викторина на Python — не только упражнение в программировании, но и способ учить любой предмет. Исследование Roediger и Karpicke показало, что самопроверка закрепляет материал лучше, чем повторное чтение[2]. Поэтому вопросы по истории, английским словам или таблице умножения, собранные в собственную программу, работают как карточки для запоминания. Начните с 5–7 вопросов по одной теме и добавляйте по несколько штук после каждого урока. Если программа подсказывает правильный ответ после ошибки, повторный прогон через день покажет, что запомнилось.
Викторина на Python как учебный проект
Викторина на Python — проект, который покрывает 5 тем школьного курса сразу: переменные, ввод, ветвления, циклы и списки. Поэтому её удобно делать как итоговую работу после первых уроков программирования.
По федеральной образовательной программе основного общего образования в 8 классе изучают ветвления, циклы и обработку строк, а в 9 классе — одномерные массивы, которым в Python соответствуют списки. Викторина использует всё это одновременно. На ОГЭ по информатике, по материалам ФИПИ, программу в задании 16 можно писать на Python, и привычка аккуратно обрабатывать ввод там тоже пригодится. Хорошая идея для класса — каждый ученик пишет по 3 вопроса, а потом их собирают в один общий список. Баллы считает программа, поэтому спорить о результате не приходится, а каждый автор видит, насколько трудными оказались его вопросы для других.
Когда текстовая викторина не подходит
Текстовая версия не подходит, когда ответ нельзя свести к короткой строке или цифре. Вот 4 таких случая.
- Ответ — развёрнутое объяснение. Сравнение строк не оценит текст из 2–3 предложений, нужен живой проверяющий.
- Ребёнку 7–8 лет. Набор ответов утомляет; проще собрать викторину из блоков, как в статье о викторине в Scratch.
- Нужны картинки и звук. Программа выводит только текст в 1 окне.
- Вопросов больше 100. Держать их в коде неудобно; лучше научиться читать вопросы из файла.
«Чтобы сделать викторину, нужен специальный конструктор или платный сервис». Это миф: хватает стандартного Python — списков, словарей, input и модуля random. Никаких сторонних библиотек не требуется.
«Если перемешать вопросы, проверка ответов собьётся». Это не подтверждается: shuffle перемещает пары целиком, и правильный ответ остаётся рядом со своим вопросом.
Чего делать нельзя
Нельзя выпускать викторину, не пройдя её самому хотя бы 2 раза: опечатка в правильном ответе делает вопрос нерешаемым. Ещё 6 правил:
- Нельзя присваивать результат shuffle — функция вернёт None, и список пропадёт.
- Не стоит сравнивать ответ с числом без преобразования: input возвращает строку.
- Не следует хранить правильные ответы с заглавными буквами, если ввод приводится к строчным.
- Не стоит создавать счётчик внутри цикла: он будет обнуляться перед каждым вопросом.
- Нельзя называть переменную
listилиinput: вы перекроете встроенные функции Python. - Не допускается задавать вопросы с двумя верными ответами, если программа принимает только один.
Имена переменных в примерах записаны по правилам PEP 8[3] — строчными буквами, слова через подчёркивание.
Источники
[1] The Python Tutorial (официальная документация Python 3). Python Software Foundation.
[2] Roediger H. L., Karpicke J. D. Test-enhanced learning: Taking memory tests improves long-term retention // Psychological Science. 2006. Vol. 17, № 3. P. 249–255.
[3] van Rossum G., Warsaw B., Coghlan N. PEP 8 — Style Guide for Python Code. Python Software Foundation, 2001.
Вопросы и ответы
Сколько вопросов должно быть в викторине?
Для первой версии хватит 5. Когда программа заработает, добавляйте сколько угодно: код от этого не меняется.
Как не задавать один вопрос дважды?
Перемешайте список и пройдите его циклом for — каждый элемент встретится ровно один раз. Функция choice в цикле может выбрать один и тот же элемент повторно.
Можно ли ограничить время на ответ?
Модуль time позволяет засечь, сколько секунд прошло между вопросом и ответом, и не начислить балл за слишком долгий ответ. Прервать уже начатый ввод так просто не получится.
Как показать ошибки в конце?
Заведите пустой список и добавляйте в него вопрос через append при неверном ответе. После цикла выведите этот список.
Чем викторина на Python отличается от квиза на этом сайте?
Квиз на сайте — готовый тренажёр с вариантами ответа. Здесь же вы пишете похожую программу сами и решаете, какие вопросы задавать.
Как сделать вопросы разной стоимости?
Добавьте в словарь вопроса поле "cost" и прибавляйте к счёту его значение вместо единицы. Сложные вопросы тогда принесут больше очков.