Computer Programming 1 (JavaScript) • Problem Solving & Mini-Projects

Building Quiz App — I can build a quiz app that tracks score using variables/arrays and updates the UI.

Combine variables, arrays, and DOM manipulation to create an interactive quiz that tracks and displays your score in real time.

A JavaScript data file with code brackets and a laptop.
Inside this lesson 10 sections 5 questions 8 figures

SECTION 1

Historical Context & Motivation

Interactive quizzes have been a part of software development since the earliest days of computing education. Before the web existed, teachers and hobbyists wrote simple text-based quiz programs in BASIC and Pascal that asked questions on the command line and tallied right and wrong answers. The core idea—store questions, accept user input, check correctness, and track a score—has remained remarkably constant even as our technology evolved from green-screen terminals to modern web browsers.

When JavaScript was created in 1995, it brought interactivity to web pages for the first time. Suddenly, developers could respond to button clicks, change text on a page without reloading, and validate form input—all within the browser. These capabilities made JavaScript the natural language for building interactive quiz apps on the web, and the pattern of storing data in variables and arrays, then pushing updates to the UI (User Interface) became a foundational skill for front-end developers everywhere.

1964 • BASIC & Text-Based Quizzes

The BASIC programming language is created at Dartmouth College, enabling students to write their first quiz programs using simple INPUT and PRINT commands on mainframe terminals.

1995 • JavaScript Is Born

Brendan Eich creates JavaScript at Netscape in just 10 days. For the first time, web pages can respond to user clicks and update content dynamically without a page reload.

2004 • AJAX & Dynamic Web Apps

AJAX techniques popularized by Gmail allow web apps to fetch and display data without refreshing. Quiz apps can now load questions on demand and provide instant feedback.

2010s • Rise of Interactive Learning

Platforms like Kahoot!, Quizlet, and Khan Academy use JavaScript-powered quizzes as core learning tools. The quiz app becomes one of the most common beginner coding projects.

Today • Modern Quiz Frameworks

React, Vue, and other frameworks make building quiz apps easier than ever, but the underlying logic—arrays of questions, score variables, and UI updates—remains the same foundational pattern.

The central question this lesson addresses is: How do you combine variables, arrays, conditional logic, and DOM manipulation into a single cohesive program that feels like a real application? Building a quiz app pulls together nearly every beginner JavaScript concept you've learned so far and gives you a practical, portfolio-worthy project.

SECTION 2

Core Principles & Definitions

Before writing any code, it helps to understand the fundamental building blocks of a quiz app. Every quiz—from a simple trivia game to a standardized test platform—relies on the same core ideas. Let's break them down.

1

Data Storage with Arrays

An array holds all of your quiz questions, answer choices, and correct answers in a single organized structure. Each element in the array is typically an object containing the question text, an array of choices, and the index or value of the correct answer.
2

State Tracking with Variables

Variables like currentQuestion and score act as the program's memory. They keep track of where the user is in the quiz and how many questions they've answered correctly. This concept is called application state.
3

Conditional Logic for Grading

An if/else statement compares the user's selected answer against the correct answer. If they match, the score variable is incremented. This decision-making logic is the brain of the quiz.
4

DOM Manipulation for UI Updates

The DOM (Document Object Model) is the browser's live representation of your HTML. Using methods like document.getElementById() and properties like innerHTML or textContent, your JavaScript updates what the user sees on screen.
5

Event Handling for Interaction

An event listener waits for the user to click a button or select an answer. When the event fires, a callback function runs to check the answer, update the score, and load the next question.
✦

KEY TAKEAWAY

Think of a quiz app like a board game. The array of questions is the deck of cards you draw from. The score variable is your scoreboard. The if/else logic is the rulebook that decides if you got a point. And DOM updates are like flipping the scoreboard so everyone can see. The game loop is: draw a card → answer → check → update score → next card.

SECTION 3

Visual Explanation — Quiz App Architecture

The diagram below illustrates the overall flow of a quiz app, from loading the first question to displaying the final score. Follow the arrows to see how data moves through the system. Notice how the state variables sit at the center, connecting the question data to what appears on screen.

Quiz App — Data Flow ArchitectureQuestions Array[ {question, choices,correctAnswer}, ... ]State Variableslet currentQuestion = 0let score = 0DOM / UIinnerHTML, textContentclassList, styleEvent Listener (click)User selects an answer choiceCheck Answer (if/else)selected === correctAnswer?Update Score & Indexscore++; currentQuestion++Load Next Question or Show ResultsRender updated UI via DOM methods
The Questions Array feeds data into State Variables, which determine what is rendered in the DOM/UI. When a user clicks an answer, the Event Listener fires, the answer is checked with conditional logic, the state is updated, and the next question loads.

As you can see, the program follows a loop: render a question, wait for input, process the answer, update state, and render again. This render-listen-update cycle is the heartbeat of nearly every interactive web application, not just quiz apps. Understanding this pattern now will serve you well when you move on to larger projects and modern frameworks like React or Vue.

SECTION 4

How It Works — Data Structures & Logic

Structuring the Question Data

The most important design decision in your quiz app is how you store the questions. The cleanest approach is an array of objects. Each object bundles together all the information for a single question: the question text, the answer choices, and which choice is correct. Here is the pattern:

QUESTION DATA STRUCTURE

constquestions=[question:"WhatdoesHTMLstandfor?",choices:["HyperTextMarkupLanguage","HotMail","HowToMakeLasagna"],correctAnswer:0,...,...];const questions = [ { question: "What does HTML stand for?", choices: ["Hyper Text Markup Language", "Hot Mail", "How To Make Lasagna"], correctAnswer: 0 }, { ... }, { ... } ];

question — a string holding the question text. choices — an array of strings representing possible answers. correctAnswer — the index (position) in the choices array that is the right answer. Using an index (0, 1, 2…) makes comparison simple.

Tracking State with Variables

You need at least two variables to manage the quiz state. The variable currentQuestion (initialized to 0) tells the app which question index to pull from the array. The variable score (also initialized to 0) counts the number of correct answers. Each time a user answers, currentQuestion is incremented by 1, and if the answer was right, score is also incremented by 1.

STATE VARIABLES

letcurrentQuestion=0;letscore=0;let currentQuestion = 0; let score = 0;

Use let (not const) because these values will change as the quiz progresses.

Checking Answers with Conditionals

ANSWER-CHECK LOGIC

functioncheckAnswer(selectedIndex)if(selectedIndex===questions[currentQuestion].correctAnswer)score++;//show"Correct!"feedbackelse//show"Incorrect"feedbackcurrentQuestion++;if(currentQuestion<questions.length)loadQuestion();elseshowResults();function checkAnswer(selectedIndex) { if (selectedIndex === questions[currentQuestion].correctAnswer) { score++; // show "Correct!" feedback } else { // show "Incorrect" feedback } currentQuestion++; if (currentQuestion < questions.length) { loadQuestion(); } else { showResults(); } }

The === operator checks strict equality between the user's selected index and the stored correct answer index. After checking, the function either loads the next question or, if all questions are done, calls showResults() to display the final score.

Updating the UI with DOM Methods

DOM UPDATE PATTERN

functionloadQuestion()constq=questions[currentQuestion];document.getElementById("question").textContent=q.question;constbtns=document.querySelectorAll(".choice−btn");btns.forEach((btn,i)=>btn.textContent=q.choices[i];btn.onclick=()=>checkAnswer(i););document.getElementById("score").textContent="Score:"+score;function loadQuestion() { const q = questions[currentQuestion]; document.getElementById("question").textContent = q.question; const btns = document.querySelectorAll(".choice-btn"); btns.forEach((btn, i) => { btn.textContent = q.choices[i]; btn.onclick = () => checkAnswer(i); }); document.getElementById("score").textContent = "Score: " + score; }

textContent sets the visible text of an HTML element. querySelectorAll selects all elements matching a CSS class. The forEach loop assigns each choice's text and click handler dynamically.

SECTION 5

Anatomy of the HTML & CSS Structure

Your quiz app needs a simple HTML skeleton that JavaScript can manipulate. The key elements are a container for the question text, a set of buttons for the answer choices, a score display area, and optionally a progress indicator. Let's visualize how these pieces fit together.

Quiz App — HTML Element Map<div id="quiz-container"><p id="question">"What does HTML stand for?"<button class="choice-btn">Choice A<button class="choice-btn">Choice B<button class="choice-btn">Choice C<button class="choice-btn"><button class="choice-btn">Choice D<span id="score">Score: 2<span id="progress">Q 3 of 5<div id="feedback">"Correct!" or "Wrong — the answer was..."</div>
This diagram maps each HTML element to its role. The question paragraph displays the current question. The choice buttons are dynamically populated with answer text and click handlers. The score span and progress span keep users informed, while the feedback div shows right/wrong messages.

Your CSS can be as simple or as creative as you'd like. A good starting point is centering the quiz container on the page, giving the buttons a hover effect, and using color to distinguish correct (green) and incorrect (red) feedback. The JavaScript doesn't depend on specific styling—it only needs the id and class attributes to find and update elements.

💡

Pro Tip

Separate your concerns: keep your HTML structure clean, your CSS in a separate stylesheet, and your JavaScript in its own file. Use <script src="quiz.js"></script> at the bottom of the body (or with the defer attribute) so the DOM is fully loaded before your script runs.

SECTION 6

Worked Example — Building a 3-Question Quiz

Let's walk through building a complete, working quiz app from start to finish. This example has three questions about JavaScript fundamentals and displays the user's score at the end.

Building a 3-Question JavaScript Quiz

  1. 1

    Step 1 — Define the Question Data

    Create an array called questions containing three objects. Each object has a question string, a choices array, and a correctAnswer index.
    const questions = [ { question: "Which keyword declares a variable that can be reassigned?", choices: ["const", "let", "var", "Both let and var"], correctAnswer: 3 }, { question: "What does === check?", choices: ["Value only", "Type only", "Value and type", "Neither"], correctAnswer: 2 }, { question: "Arrays are indexed starting at?", choices: ["1", "0", "-1", "It depends"], correctAnswer: 1 } ];
  2. 2

    Step 2 — Initialize State Variables

    Declare let currentQuestion = 0 to track which question we're on and let score = 0 to track correct answers. These are declared with let because their values will change during the quiz.
    let currentQuestion = 0; let score = 0;
  3. 3

    Step 3 — Write the loadQuestion Function

    This function reads the current question object from the array using questions[currentQuestion] and updates the DOM. It sets the question text, updates all button labels, and attaches click handlers to each button that call checkAnswer(i) where i is the button's index.
    function loadQuestion() { const q = questions[currentQuestion]; document.getElementById("question").textContent = q.question; const btns = document.querySelectorAll(".choice-btn"); btns.forEach((btn, i) => { btn.textContent = q.choices[i]; btn.onclick = () => checkAnswer(i); }); }
  4. 4

    Step 4 — Write the checkAnswer Function

    Compare the selected index to questions[currentQuestion].correctAnswer. If they match, increment score. Then increment currentQuestion and either load the next question or show results.
    function checkAnswer(selected) { if (selected === questions[currentQuestion].correctAnswer) { score++; } currentQuestion++; if (currentQuestion < questions.length) { loadQuestion(); } else { showResults(); } }
  5. 5

    Step 5 — Write the showResults Function and Start the Quiz

    The showResults function replaces the quiz container content with the final score. Use template literals to include the score and total. Finally, call loadQuestion() at the bottom of the script to kick things off when the page loads.
    function showResults() { document.getElementById("quiz-container").innerHTML = `<h2>Quiz Complete!</h2> <p>You scored ${score} out of ${questions.length}</p>`; } // Start the quiz loadQuestion();
💡

Try It Yourself

Copy this code into a file called quiz.js, create a simple HTML page with a <div id="quiz-container"> containing a <p id="question"> and four <button class="choice-btn"> elements, and link your script. Open it in a browser and you'll have a working quiz!

SECTION 7

Comparing Approaches — Design Decisions

There is no single "right" way to build a quiz app. Different design choices trade off simplicity for power. The table below compares several common approaches so you can choose what fits your skill level and goals.

Design DecisionSimple ApproachAdvanced Approach
Storing correct answerStore the index of the correct choice (e.g., correctAnswer: 2). Easy to compare with ===.Store the answer text (e.g., correctAnswer: "Value and type"). More readable but requires string comparison.
Rendering choicesPre-create fixed HTML buttons and update their text with JavaScript. Fast to set up.Dynamically generate buttons with createElement(). Supports variable numbers of choices per question.
Showing feedbackUse alert() pop-ups. One line of code, but interrupts flow and looks dated.Update a feedback <div> in the page. Smoother UX, requires more DOM code.
Question orderPresent questions in the array's original order. Predictable and easy to debug.Shuffle the array with a Fisher-Yates algorithm. Prevents memorization on retakes.
Score persistenceScore resets when the page reloads. No extra code needed.Save high scores to localStorage. Score persists across sessions.

Simple vs. Advanced design choices for a quiz app

✦

KEY TAKEAWAY

Start with the simplest approach that works, then level up. A working quiz with alert() feedback is infinitely better than a fancy quiz that never gets finished. In software development, this philosophy is called "Make it work, make it right, make it fast." Get the basic version running first, then iterate.

SECTION 8

Connection to Advanced Concepts

The quiz app you're building uses the exact same patterns found in professional web applications. Understanding how this project connects to more advanced ideas will help you see why these fundamentals matter so much.

Quiz App ConceptAdvanced Equivalent
Array of question objectsFetching data from a REST API or database (e.g., JSON from a server)
currentQuestion and score variablesState management in React (useState), Redux, or Vuex
loadQuestion() functionComponent rendering and virtual DOM diffing in React/Vue
onclick event handlersEvent-driven architecture, pub/sub patterns, and reactive programming
showResults() functionRoute navigation and conditional rendering of different views/pages

How quiz app patterns scale to professional development

As you progress in your programming journey, you'll encounter frameworks like React and Vue that automate the render-listen-update cycle you coded by hand in this project. But under the hood, those frameworks are doing exactly what you're doing: storing state, listening for events, and updating the DOM. By building this quiz app with vanilla JavaScript first, you gain a deep understanding of what those tools are actually doing for you—and that understanding will make you a stronger developer.

ℹ

Challenge Ideas

Once your basic quiz works, try adding a timer that counts down for each question, a progress bar that fills as the user advances, randomized choice order, or a "Review Mistakes" screen at the end that shows which questions were missed. Each of these features exercises a new skill while building on the same foundation.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

Explain why we use let instead of const for the score and currentQuestion variables, but const for the questions array. Doesn't the array "change" as we move through it?
Show answer
The score and currentQuestion variables are reassigned to new values as the quiz progresses (e.g., score++ changes the number stored in score), and let allows reassignment. The questions array is declared with const because we never reassign the variable to a different array—we only read from it. const prevents reassignment of the variable binding, but it does not make the array's contents immutable. We could still push() to or modify items within the array without error.

Question 2: BASIC CALCULATION

Given the following array, what value is stored in questions[1].correctAnswer, and what text does it correspond to? const questions = [ { question: "2+2?", choices: ["3","4","5"], correctAnswer: 1 }, { question: "Capital of France?", choices: ["London","Berlin","Paris"], correctAnswer: 2 }, { question: "Largest ocean?", choices: ["Atlantic","Pacific","Indian"], correctAnswer: 1 } ];
Show answer
questions[1].correctAnswer evaluates to 2. This is the index of the correct choice in the choices array for question at index 1 ("Capital of France?"). The choices array for that question is ["London", "Berlin", "Paris"], so index 2 corresponds to "Paris". Therefore questions[1].choices[questions[1].correctAnswer] would give us "Paris".

Question 3: INTERMEDIATE

A student's quiz app has a bug: every time the user clicks a button, the score increments even when the answer is wrong. Here is the checkAnswer function. Find and fix the bug. function checkAnswer(selected) { if (selected = questions[currentQuestion].correctAnswer) { score++; } currentQuestion++; loadQuestion(); }
Show answer
The bug is on the if line: the student used a single equals sign = (assignment) instead of triple equals === (strict equality comparison). The expression selected = questions[currentQuestion].correctAnswer assigns the correct answer index to selected and then evaluates to that value. Since the correct answer index is a number like 0, 1, or 2, any non-zero value is truthy, so the if block runs almost every time. The fix is to change it to if (selected === questions[currentQuestion].correctAnswer).

Question 4: APPLIED

You want to add a feature that shows the user which questions they got wrong at the end of the quiz. Describe what data structure you would add, how you would update it during the quiz, and how you would display the results. Write pseudocode or real JavaScript for each part.
Show answer
Create an array at the top of your script: const wrongAnswers = [];. Inside the checkAnswer function, in the else block (when the answer is wrong), push an object with the question text, the user's answer, and the correct answer: wrongAnswers.push({ question: questions[currentQuestion].question, yourAnswer: questions[currentQuestion].choices[selected], correct: questions[currentQuestion].choices[questions[currentQuestion].correctAnswer] });. In the showResults function, loop through wrongAnswers and build HTML strings that display each missed question, the user's incorrect answer, and the correct answer. Append that HTML to the results container using innerHTML.

Question 5: CRITICAL THINKING

A classmate suggests storing quiz questions directly in the HTML rather than in a JavaScript array—each question as a hidden <div> that gets shown one at a time. Compare this approach to the JavaScript array approach in terms of: (a) how easy it is to add new questions, (b) how the score-tracking logic would differ, and (c) scalability if you had 100 questions. Which approach would you choose and why?
Show answer
(a) With HTML-only storage, adding a question means writing new HTML markup with the correct classes and data attributes, which is more verbose and error-prone than adding an object to an array. (b) Score tracking would require reading data from DOM attributes (e.g., data-correct) rather than simply accessing an object property, making the logic more tightly coupled to the HTML structure. (c) At 100 questions, the HTML file becomes enormous and hard to maintain, while a JavaScript array (or JSON file loaded via fetch) keeps the HTML small and the data portable. The JavaScript array approach is superior in all three dimensions because it separates data from presentation, making the app easier to maintain, extend, and eventually connect to a database or API. The HTML approach might seem simpler at first for 2–3 questions, but it does not scale.

SUMMARY

Lesson Summary

Summary

In this lesson, you learned how to build an interactive quiz app by combining four core JavaScript skills. You structured quiz data using an array of objects, where each object holds a question, its answer choices, and the correct answer index. You tracked the quiz's progress with state variables (currentQuestion and score), used conditional logic (if/else) to check answers and increment the score, and applied DOM manipulation techniques like textContent and innerHTML to update what the user sees on screen.

The render-listen-update cycle at the heart of this app—render a question, listen for a click, update state, render again—is the same pattern used by every modern web framework. You also explored different design decisions (index vs. string comparison, static vs. dynamic buttons, alert vs. in-page feedback) and saw how the patterns in your quiz app map directly to advanced concepts like state management, component rendering, and API-driven data. This project is a milestone: you've proven you can combine variables, arrays, conditionals, functions, and DOM methods into a cohesive, working application.

Varsity Tutors • Computer Programming 1 (JavaScript) • Building Quiz App