У цій статті ви дізнаєтеся, як створити інтерактивну вікторину на базі терміналу за допомогою JavaScript та Node.js. Цей проєкт ідеально підходить для початківців, які хочуть практикувати основні програмувальні концепції, такі як модульний код, обробка помилок та управління ввідними даними користувача. Наприкінці цього посібника ви матимете цікаву та функціональну гру, яку можна грати та ділитися з друзями! Давайте почнемо!
Особливості гри у вікторину
- Інтерактивний процес гри: Гравці можуть вибрати тему, відповідати на питання з кількома варіантами відповідей і отримувати негайний зворотний зв'язок.
- Відслідковування балів: Гра відслідковує бали гравця, показуючи їх після кожного питання.
- Безперервний потік: Після вибору теми гра задає питання, поки гравець не вирішить вийти.
4.
Зручний дизайн для користувача: Інтерфейс включає чіткі інструкції, банер-привітання (згенерований за допомогою сайту Text to ASCII Art Generator) і безперервний досвід взаємодії.
Робочий процес гри
Ось покроковий робочий процес гри:
- Відображення банера-привітання.
- Запит гравця вибрати тему (наприклад, Питання з програмування або Загальні знання).
- Безперервне відображення питань з вибраної теми.
- Дозвіл гравцеві вийти в будь-який момент, ввівши "quit".
- Виведення фінального рахунку після завершення гри.
Структура папок
quizGame
┣ data.js
┣ index.js
┣ package.json
┗ questionGenerator.js
Реалізація
data.js
export const generalKnowledgeQA = [
{ question: "Яка столиця Франції?", answer: "Париж" },
{ question: "Хто написав 'Ромео і Джульєтту'?", answer: "Вільям Шекспір" },
{
question: "Яка найменша планета у нашій Сонячній системі?",
answer: "Меркурій",
}.
//додати більше питань
];
export const codingQuestions = [
{
question: "Що таке closure в JavaScript?",
answer:
"Closure — це функція, яка запам'ятовує змінні зі свого зовнішнього оточення, навіть після того, як зовнішня функція завершила своє виконання.",
},
{
question:
"У чому різниця між var, let та const у JavaScript?",
answer:
"var має область видимості функції, тоді як let і const мають область видимості блоку.",
}.
const використовується для змінних, які не повинні бути переназначені.",
},
// Додати більше питань
];
Цей файл містить питання та відповіді.
QuestionsGenerator.js
import { codingQuestions, generalKnowledgeQA } from "./data.js";
export default function generateQuestionWithAssertions(type) {
// Перевірка типу введення
let dataSource = [];
if (type === "codingQuestions") {
dataSource = codingQuestions;
} else if (type === "generalKnowledgeQA") {
dataSource = generalKnowledgeQA;
} else {
throw new Error(
"Невірний тип.");
}
}
Виберіть 'codingQuestions' або 'generalKnowledgeQA'."
);
}
// Перевірка, чи є достатньо питань для створення тверджень
if (dataSource.length < 4) {
throw new Error("Недостатньо питань у джерелі даних.");
}
// Вибір 4 унікальних випадкових питань
const questions = [];
const usedIndices = new Set();
while (questions.length < 4) {
const randomIndex = Math.floor(Math.random() * dataSource.length);
if (!usedIndices.has(randomIndex)) {
questions.push(dataSource[randomIndex]);
usedIndices.add(randomIndex);
}
}
// Вибір одного питання як головного
const choosingQuestionRandomIndex = Math.floor(Math.random() * questions.length);
const mainQst = questions[choosingQuestionRandomIndex];
// Перемішування питань для використання їх як тверджень
let currentIndex = questions.length;
while (currentIndex !== 0) {
const randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[questions[currentIndex], questions[randomIndex]] = [
questions[randomIndex],
questions[currentIndex],
];
}
const indexofAnswer = questions.findIndex((question) => question === mainQst);
const assertions = {
a: questions[0].answer,
b: questions[1].answer,
c: questions[2].answer,
d: questions[3].answer,
};
const correctAnswer = assertions[Object.keys(assertions)[indexofAnswer]];
return {
q: mainQst,
assertions,
correctAnswer,
};
}
Особливості в коді
1.
Динамічна обробка даних
- Функція приймає параметр
type
(наприклад,"codingQuestions"
або"generalKnowledgeQA"
) і динамічно вибирає відповідний набір даних. - Вона перевіряє параметр
type
, щоб упевнитися, що він є або"codingQuestions"
, або"generalKnowledgeQA"
, запобігаючи некоректному вводу.
2. Випадковий вибір питань
- Випадковий вибір питань: Чотири унікальні випадкові питання вибираються з обраного набору даних за допомогою циклу
while
іSet
, що відстежує використані індекси. - Це гарантує, що в твердженнях не буде дублікатів питань.
3.
Випадкові твердження
- Функція перемішує вибрані питання, щоб створити випадкові варіанти для багатоваріантного тесту, використовуючи Алгоритм перемішування Фішера-Йейтса:
let currentIndex = questions.length;
while (currentIndex !== 0) {
const randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[questions[currentIndex], questions[randomIndex]] = [questions[randomIndex], questions[currentIndex], ];
}
- Це гарантує, що правильна відповідь буде з'являтися в випадковій позиції щоразу.
4. Прив'язка тверджень до варіантів
- Після перемішування відповіді прив'язуються до варіантів
a
,b
,c
таd
:
const assertions = {
a: questions[0].answer,
b: questions[1].answer,
c: questions[2].answer,
d: questions[3].answer,
};
- Це спрощує подання варіантів користувачеві в структурованому форматі.
5.
Ідентифікація правильної відповіді
- Функція ідентифікує правильну відповідь, знаходячи оригінальне питання в перемішаному списку:
const indexofAnswer = questions.findIndex((question) => question === qst);
const correctAnswer = assertions[Object.keys(assertions)[indexofAnswer]];
- Це гарантує, що правильна відповідь буде коректно прив'язана до свого випадкового місця (наприклад,
a
,b
тощо).
6. Перевірка та обробка помилок
- Код включає надійну обробку помилок:
- Перевіряє, чи є набір даних дійсним і чи відповідає тип очікуваному значенню.
- Перевіряє, чи містить набір даних хоча б чотири питання, щоб уникнути помилок через недостатню кількість даних:
if (dataSource.length < 4) {
throw new Error("Not enough questions in the data source.");
}
7.
Повертає структурований об'єкт
- Функція повертає об'єкт з:
- Основним питанням (
q
) - Перемішаними варіантами відповідей (
assertions
) - Правильною відповіддю (
correctAnswer
)
- Основним питанням (
Приклад результату:
{ q: { question: "What is JavaScript?",
answer: "A programming language" },
assertions: { a: "HTML", b: "CSS", c: "A programming language", d: "Python"
}, correctAnswer: "c" }
index.js
import * as readline from "node:readline/promises";
import { stdin as input, stdout as output } from "node:process";
import generateQuestionWithAssertions from "./questionGenerator.js";
async function gameInterface() {
const rl = readline.createInterface({ input, output });
const welcomeBanner = `
██╗ ███████████╗ ██████╗██████╗███╗ ██████████╗ ████████╗██████╗ ██████████╗ █████████╗ ██████╗ █████╗███╗ ██████████╗
██║ ████╔════██║ ██╔════██╔═══██████╗ ██████╔════╝ ╚══██╔══██╔═══██╗ ╚══██╔══██║ ████╔════╝ ██╔════╝██╔══██████╗ ██████╔════╝
██║ █╗ ███████╗ ██║ ██║ ██║ ████╔████╔███████╗ ██║ ██║ ██║ ██║ ████████████╗ ██║ ████████████╔████╔███████╗
██║███╗████╔══╝ ██║ ██║ ██║ ████║╚██╔╝████╔══╝ ██║ ██║ ██║ ██║ ██╔══████╔══╝ ██║ ████╔══████║╚██╔╝████╔══╝
╚███╔███╔██████████████╚██████╚██████╔██║ ╚═╝ █████████╗ ██║ ╚██████╔╝ ██║ ██║ █████████╗ ╚██████╔██║ ████║ ╚═╝ █████████╗
╚══╝╚══╝╚══════╚══════╝╚═════╝╚═════╝╚═╝ ╚═╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╚══════╝ ╚═════╝╚═╝ ╚═╚═╝ ╚═╚══════╝
Ласкаво просимо до гри-вікторини! Тестуйте свої знання і отримуйте задоволення! 🎉
`;
console.log(welcomeBanner);
let score = 0;
// Запитати користувача, яку категорію питань вибрати
const questionSet = await rl.question(
"Виберіть набір питань: 1) Питання з програмування 2) Загальні знання: "
);
let data;
if (questionSet === "1") {
console.log("Ви вибрали питання з програмування! 🖥️");
} else if (questionSet === "2") {
console.log("Ви вибрали загальні знання! 🌍");
} else {
console.log(
"Невірний вибір.
Вихід з гри.
Вітаємо в грі! Тестуйте свої знання та насолоджуйтесь! 🎉
## Ключові особливості коду
**Привітальний банер**:
- Візуально привабливий банер ASCII-арт вітає гравців у грі.
- Це додає веселе та захоплююче початок до досвіду гри.
const welcomeBanner = `
██╗ ███████████╗ ██████╗██████╗███╗ ██████████╗ ████████╗██████╗ ██████████╗ █████████╗ ██████╗ █████╗███╗ ██████████╗
██║ ████╔════██║ ██╔════██╔═══██████╗ ██████╔════╝ ╚══██╔══██╔═══██╗ ╚══██╔══██║ ████╔════╝ ██╔════╝██╔══██████╗ ██████╔════╝
██║ █╗ ███████╗ ██║ ██║ ██║ ████╔████╔███████╗ ██║ ██║ ██║ ██║ ████████████╗ ██║ ████████████╔████╔███████╗
██║███╗████╔══╝ ██║ ██║ ██║ ████║╚██╔╝████╔══╝ ██║ ██║ ██║ ██║ ██╔══████╔══╝ ██║ ████╔══████║╚██╔╝████╔══╝
╚███╔███╔██████████████╚██████╚██████╔██║ ╚═╝ █████████╗ ██║ ╚██████╔╝ ██║ ██║ █████████╗ ╚██████╔██║ ████║ ╚═╝ █████████╗
╚══╝╚══╝╚══════╚══════╝╚═════╝╚═════╝╚═╝ ╚═╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╚══════╝ ╚═════╝╚═╝ ╚═╚═╝ ╚═╚══════╝
Вітаємо в грі! Тестуйте свої знання та насолоджуйтесь! 🎉
;
``
Вибір набору запитань:
- Користувач вибирає тему для початку (наприклад, Запитання з програмування або Загальні знання).
- Це забезпечує персоналізовану гру.
const questionSet = await rl.question(
"Оберіть набір запитань: 1) Запитання з програмування 2) Загальні знання: "
);
let data;
if (questionSet === "1") {
console.log("Ви обрали запитання з програмування! 🖥️");
} else if (questionSet === "2") {
console.log("Ви обрали загальні знання! 🌍");
} else {
console.log(
"Невірний вибір.
Вихід з гри.
Будь ласка, перезапустіть і виберіть 1 або 2."
);
rl.close();
return;
}
console.log(
"Гра почалася! Відповідайте на запитання або введіть 'quit', щоб завершити гру."
);
console.log("Ваш поточний рахунок буде показано після кожного запитання.");
Безперервний процес гри:
- Цикл
while (true)
забезпечує безперервне надання запитань, поки гравець не введе "quit". - Це дозволяє уникнути необхідності підтверджувати початок гри кожного разу.
while (true) {
// Генерація запитання
if (questionSet === "1") {
data = generateQuestionWithAssertions("codingQuestions");
} else if (questionSet === "2") {
data = generateQuestionWithAssertions("generalKnowledgeQA");
}
console.log(`\nЗапитання: ${data.q.question}`);
console.log(`a) ${data.assertions.a}`);
console.log(`b) ${data.assertions.b}`);
console.log(`c) ${data.assertions.c}`);
console.log(`d) ${data.assertions.d}`);
const answer = await rl.question(
"Ваша відповідь (a/b/c/d або 'quit' для виходу): "
);
if (answer.toLowerCase() === "quit") {
console.log(`Дякуємо за гру! Ваш фінальний рахунок: ${score}`);
break;
}
if (data.correctAnswer === data.assertions[answer]) {
console.log("Правильна відповідь! 🎉");
score++;
} else {
console.log(`Неправильна відповідь! 😞 Правильна відповідь була: ${data.q.answer}`);
}
console.log(`Ваш поточний рахунок: ${score}`);
}
Відстеження рахунку:
- Змінна
score
відстежує правильні відповіді. - Рахунок відображається після кожного запитання, надаючи миттєвий зворотний зв'язок гравцеві.
let score = 0;
Опція виходу:
- Гравці можуть вийти з гри в будь-який час, ввівши
"quit"
. - Це дає гравцям гнучкість і забезпечує природний кінець гри.
const answer = await rl.question(
"Ваша відповідь (a/b/c/d або 'quit' для виходу): "
);
if (answer.toLowerCase() === "quit") {
console.log(`Дякуємо за гру! Ваш фінальний рахунок: ${score}`);
break;
}
Як це працює
1.
Модулі: Гра використовує модуль readline
в Node.js для обробки введення користувача в терміналі.
2. Динамічне створення запитань: Функція generateQuestionWithAssertions
динамічно створює запитання та відповідні варіанти відповідей.
3. Зворотний зв'язок для користувача: Після кожної відповіді гра надає зворотний зв'язок щодо того, чи була правильна вибрана відповідь.
Остаточний результат
Це фінальна гра, що використовує пакет Chalk
Висновок
Ця вікторина — це веселе та інтерактивне заняття для практики JavaScript, одночасно створюючи значущий проект. Вона вчить основним концепціям, таким як обробка введення користувача, цикли, умовні оператори та модульне програмування.
Ви можете ще більше покращити цю гру, додавши додаткові функції та персоналізацію, щоб зробити її більш захоплюючою.
Тож, чому б не почати? Почніть кодувати свою власну вікторину сьогодні, і нехай навчання — та задоволення — почнеться!
Порада: Використовуйте пакет chalk
або inquirer
для кольорових та інтуїтивно зрозумілих підказок в терміналі.
Це завершує наш урок. Якщо він був корисним, не соромтеся аплодувати або залишити коментар. Будь-які пропозиції або відгуки будуть радісно прийняті. Ви також можете зв'язатися зі мною через Twitter, LinkedIn, GitHub.
Перекладено з: Creating a terminal-based quiz game in JavaScript using Node.js: A Step-by-Step Guide