Chào mừng các bạn đến với Rcom Dăm Yi blog - Kho tài liệu bổ ích!, Chúng tôi sẽ từng bước hoàn thiện để bạn đọc cảm thấy hài lòng, hữu ích!

Thứ Sáu, 23 tháng 1, 2026

Bài 12: Mini Project – Quiz trắc nghiệm (có chấm điểm)

🎯 Mục tiêu

  • Biết tạo câu hỏi trắc nghiệm bằng HTML (radio)
  • Biết xử lý chấm điểm bằng JavaScript
  • Hiểu cách lưu dữ liệu câu hỏi trong mảng (array) và đối tượng (object)
  • Biết cập nhật giao diện bằng DOM

📘 Mô tả bài toán

Bạn sẽ làm một trang Quiz có 5 câu hỏi:

  • Chọn đáp án (A/B/C/D)
  • Bấm “Nộp bài” để chấm điểm
  • Hiển thị số câu đúng + tổng điểm
  • Tô màu câu đúng/sai
  • (Nâng cao) Có nút “Làm lại”

📘 Kiến thức dùng trong bài

  • Radio: chỉ chọn 1 đáp án trong một nhóm (cùng name).
  • Array/Object: lưu danh sách câu hỏi để dễ mở rộng.
  • DOM: JS đọc đáp án người dùng chọn và cập nhật kết quả.

💻 Code mẫu (Quiz hoàn chỉnh)


<!doctype html>
<html lang="vi">
<head>
  <meta charset="utf-8">
  <title>Bài 12 - Quiz trắc nghiệm</title>

  <style>
    body{
      font-family: Arial;
      background:#f7f8fa;
      padding: 24px;
      line-height: 1.7;
    }
    .app{
      max-width: 760px;
      margin: 0 auto;
      background:#fff;
      border:1px solid #e5e5e5;
      border-radius: 14px;
      padding: 18px;
    }
    h1{ margin-top:0; text-align:center; }
    .q{
      border:1px solid #e5e5e5;
      border-radius: 12px;
      padding: 14px;
      margin: 12px 0;
      background:#fff;
    }
    .q.correct{ background:#ecfdf5; border-color:#bbf7d0; }
    .q.wrong{ background:#fff1f2; border-color:#fecdd3; }

    .answers label{
      display:block;
      padding: 6px 0;
      cursor:pointer;
    }
    .row{
      display:flex;
      gap: 10px;
      flex-wrap: wrap;
      justify-content: center;
      margin-top: 14px;
    }
    button{
      padding: 10px 14px;
      border:0;
      border-radius: 10px;
      cursor:pointer;
      background:#2563eb;
      color:#fff;
      font-weight: 700;
    }
    button.gray{ background:#111; }
    .result{
      margin-top: 14px;
      padding: 12px;
      border-radius: 12px;
      background:#f3f4f6;
      border:1px solid #e5e7eb;
    }
    small{ color:#555; }
  </style>
</head>

<body>

  <div class="app">
    <h1>🧠 Quiz trắc nghiệm</h1>
    <p>Chọn đáp án đúng rồi bấm <b>Nộp bài</b>.</p>

    <div id="quiz"></div>

    <div class="row">
      <button id="btnSubmit">Nộp bài</button>
      <button class="gray" id="btnReset">Làm lại</button>
    </div>

    <div class="result" id="result">
      <small>Kết quả sẽ hiển thị ở đây.</small>
    </div>
  </div>

  <script>
    // 1) Dữ liệu câu hỏi (có thể thêm bớt dễ dàng)
    const questions = [
      {
        text: "HTML dùng để làm gì?",
        options: ["Tạo cấu trúc", "Làm đẹp", "Tạo tương tác", "Lưu dữ liệu"],
        answer: 0
      },
      {
        text: "CSS dùng để làm gì?",
        options: ["Chấm điểm", "Làm đẹp giao diện", "Tạo server", "Tạo database"],
        answer: 1
      },
      {
        text: "Thẻ nào tạo liên kết?",
        options: ["<img>", "<a>", "<p>", "<div>"],
        answer: 1
      },
      {
        text: "Trong JS, từ khóa khai báo biến có thể đổi giá trị là?",
        options: ["const", "let", "varrr", "fixed"],
        answer: 1
      },
      {
        text: "Thuộc tính nào bắt buộc nhập form?",
        options: ["required", "checked", "href", "alt"],
        answer: 0
      }
    ];

    const quizEl = document.getElementById("quiz");
    const resultEl = document.getElementById("result");
    const btnSubmit = document.getElementById("btnSubmit");
    const btnReset = document.getElementById("btnReset");

    // 2) Render câu hỏi ra HTML
    function renderQuiz(){
      quizEl.innerHTML = "";
      questions.forEach((q, i) => {
        const box = document.createElement("div");
        box.className = "q";
        box.setAttribute("data-index", i);

        let html = "<h3>Câu " + (i+1) + ": " + q.text + "</h3>";
        html += '<div class="answers">';

        q.options.forEach((opt, j) => {
          html +=
            '<label>' +
            '<input type="radio" name="q' + i + '" value="' + j + '"> ' +
            opt +
            '</label>';
        });

        html += "</div>";
        box.innerHTML = html;
        quizEl.appendChild(box);
      });

      resultEl.innerHTML = "<small>Kết quả sẽ hiển thị ở đây.</small>";
    }

    // 3) Chấm điểm
    function grade(){
      let correct = 0;

      const boxes = document.querySelectorAll(".q");
      boxes.forEach((box, i) => {
        box.classList.remove("correct", "wrong");

        const checked = document.querySelector('input[name="q' + i + '"]:checked');
        const userAnswer = checked ? Number(checked.value) : -1;

        if(userAnswer === questions[i].answer){
          correct++;
          box.classList.add("correct");
        } else {
          box.classList.add("wrong");
        }
      });

      const total = questions.length;
      const score = Math.round((correct / total) * 10);

      resultEl.innerHTML =
        "✅ Đúng: <b>" + correct + "/" + total + "</b> câu" +
        "<br>🎯 Điểm: <b>" + score + "/10</b>";
    }

    // 4) Reset
    function resetQuiz(){
      renderQuiz();
    }

    btnSubmit.addEventListener("click", grade);
    btnReset.addEventListener("click", resetQuiz);

    // chạy lần đầu
    renderQuiz();
  </script>

</body>
</html>
    

👉 Copy code → lưu thành bai12.html → mở bằng Chrome.
Bấm “Nộp bài” để chấm điểm và xem câu đúng/sai được tô màu.

✍️ Bài tập

  1. Thêm 3 câu hỏi mới vào mảng questions.
  2. Đổi thang điểm từ 10 sang 100.
  3. (Nâng cao) Nếu người học bỏ trống câu nào, thông báo “Bạn chưa làm hết”.
  4. (Nâng cao) Hiển thị đáp án đúng sau khi nộp bài.

✅ Đáp án gợi ý

1) Thang điểm 100


const score = Math.round((correct / total) * 100);
    

2) Kiểm tra bỏ trống


let unanswered = 0;
const checked = document.querySelector('input[name="q' + i + '"]:checked');
if(!checked) unanswered++;

if(unanswered > 0){
  resultEl.innerHTML = "⚠️ Bạn chưa làm hết: " + unanswered + " câu.";
  return;
}
    

3) Hiển thị đáp án đúng (gợi ý)


// Sau khi chấm, bạn có thể thêm dòng:
box.innerHTML += "<p><b>Đáp án đúng:</b> " + questions[i].options[questions[i].answer] + "</p>";
    

Không có nhận xét nào:

Đăng nhận xét

Bài đăng phổ biến

💬 Bình luận

💬 Bình luận

📌 Danh sách bình luận