{"id":4172,"date":"2025-07-05T04:47:10","date_gmt":"2025-07-05T04:47:10","guid":{"rendered":"https:\/\/aaaschoolkh.com\/?p=4172"},"modified":"2025-07-05T04:48:41","modified_gmt":"2025-07-05T04:48:41","slug":"pygame-exam","status":"publish","type":"post","link":"https:\/\/aaaschoolkh.com\/km\/pygame-exam\/","title":{"rendered":"Python Pygame Exam"},"content":{"rendered":"<div data-elementor-type=\"wp-post\" data-elementor-id=\"4172\" class=\"elementor elementor-4172\" data-elementor-post-type=\"post\">\n\t\t\t\t<div class=\"elementor-element elementor-element-4d84211 e-con-full e-flex e-con e-parent\" data-id=\"4d84211\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1de79da elementor-widget elementor-widget-html\" data-id=\"1de79da\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<!DOCTYPE html>\n<html lang=\"en\" class=\"scroll-smooth\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Interactive Pygame Exam<\/title>\n    <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n    <script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js\"><\/script>\n    <!-- Chosen Palette: Stone & Teal -->\n    <!-- Application Structure Plan: The application is now a single-page exam form. This structure was chosen to allow users to see all questions at once, review their answers before submitting, and get a comprehensive feedback report in-place. The wizard-like flow is replaced by a more traditional, scrollable test format which simplifies navigation. -->\n    <!-- Visualization & Content Choices: \n        - All Questions: Goal: Test -> Method: Radio buttons styled as checkboxes. -> Interaction: User selects one option per question. After submitting, JS validates all answers and applies color-coded feedback. Justification: This provides a familiar test-taking experience while retaining instant, comprehensive feedback upon submission.\n        - Coding Challenge Section: Goal: Demonstrate -> Method: Interactive Canvas. -> Interaction: A live canvas animation simulates the correct code's behavior. Justification: Visualizes the abstract code, making the solution tangible.\n        - Results Section: Goal: Summarize -> Method: Chart.js Doughnut Chart. -> Interaction: The chart dynamically appears at the bottom of the page after grading to display the final score. Justification: Provides a clear, visually appealing summary of performance without navigating away.\n        - Library\/Method: Chart.js for the final score chart and native Canvas API for the coding challenge visualization, confirming NO SVG\/Mermaid. -->\n    <!-- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->\n    <style>\n        body { font-family: 'Inter', sans-serif; }\n        @import url('https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;700&family=Fira+Code:wght@400;600&display=swap');\n        .code-block { font-family: 'Fira Code', monospace; }\n        .chart-container {\n            position: relative;\n            width: 100%;\n            max-width: 300px;\n            height: 300px;\n            max-height: 300px;\n            margin-left: auto;\n            margin-right: auto;\n        }\n        input[type=\"radio\"] { display: none; }\n        input[type=\"radio\"] + label {\n            transition: all 0.2s ease-in-out;\n            cursor: pointer;\n            display: flex;\n            align-items: center;\n        }\n        .checkbox-box {\n            width: 1.25rem;\n            height: 1.25rem;\n            border: 2px solid #a8a29e; \/* stone-400 *\/\n            border-radius: 0.25rem;\n            margin-right: 0.75rem;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            flex-shrink: 0;\n            transition: all 0.2s ease-in-out;\n        }\n        input[type=\"radio\"]:checked + label {\n            border-color: #14b8a6; \/* teal-500 *\/\n            background-color: #f0fdfa; \/* teal-50 *\/\n            box-shadow: 0 0 0 2px #14b8a6;\n        }\n        input[type=\"radio\"]:checked + label .checkbox-box {\n            background-color: #14b8a6;\n            border-color: #0f766e;\n        }\n        input[type=\"radio\"]:checked + label .checkbox-box::after {\n            content: '\u2714';\n            color: white;\n            font-size: 0.8rem;\n            font-weight: bold;\n        }\n        .feedback-correct {\n             border-color: #14b8a6 !important;\n             background-color: #f0fdfa !important;\n        }\n        .feedback-incorrect {\n             border-color: #f43f5e !important;\n             background-color: #fff1f2 !important;\n        }\n    <\/style>\n<\/head>\n<body class=\"bg-stone-50 text-stone-700\">\n\n    <div id=\"quiz-container\" class=\"max-w-3xl mx-auto p-4 sm:p-8 my-10 bg-white rounded-2xl shadow-lg\">\n\n        <!-- Initial Welcome Screen -->\n        <div id=\"welcome-screen\">\n            <h1 class=\"text-3xl sm:text-4xl font-bold text-stone-900 mb-4 text-center\">Pygame Fundamentals Exam<\/h1>\n            <p class=\"text-stone-600 mb-8 text-center\">Test your knowledge with this interactive quiz. All questions are on one page. Submit at the end to see your score.<\/p>\n            <div class=\"text-center\">\n                <button id=\"start-btn\" class=\"px-8 py-3 bg-teal-500 text-white font-bold rounded-lg hover:bg-teal-600 transition-colors shadow-md\">Start Exam<\/button>\n            <\/div>\n        <\/div>\n\n        <!-- Exam Form -->\n        <form id=\"exam-form\" class=\"hidden\" action=\"\">\n            <!-- MCQ Section -->\n            <div class=\"mb-12\">\n                <h2 class=\"text-2xl font-bold text-stone-800 border-b-2 border-stone-200 pb-2 mb-6\">Part 1: Multiple Choice<\/h2>\n                <div id=\"mcq-questions-container\" class=\"space-y-8\"><\/div>\n            <\/div>\n            \n            <!-- Terminology Section -->\n            <div class=\"mb-12\">\n                <h2 class=\"text-2xl font-bold text-stone-800 border-b-2 border-stone-200 pb-2 mb-6\">Part 2: Terminology Check<\/h2>\n                <div id=\"terminology-questions-container\" class=\"space-y-8\"><\/div>\n            <\/div>\n\n            <!-- Coding Challenge Section -->\n            <div class=\"mb-12\">\n                 <h2 class=\"text-2xl font-bold text-stone-800 border-b-2 border-stone-200 pb-2 mb-6\">Part 3: Coding Challenge Review<\/h2>\n                 <p class=\"text-stone-600 mb-6\">Review the objective for the coding challenge. A live demonstration of the correct solution is running below.<\/p>\n                 <div class=\"text-center\">\n                    <div class=\"w-full max-w-md h-80 bg-stone-800 rounded-lg overflow-hidden mx-auto shadow-inner\">\n                        <canvas id=\"gameCanvas\"><\/canvas>\n                    <\/div>\n                    <p class=\"mt-2 font-semibold text-teal-600\">Move your mouse to control the player!<\/p>\n                <\/div>\n            <\/div>\n\n            <!-- Submission and Results -->\n            <div class=\"text-center border-t-2 border-stone-200 pt-8\">\n                <button type=\"submit\" id=\"finish-btn\" class=\"px-8 py-3 bg-teal-500 text-white font-bold text-lg rounded-lg hover:bg-teal-600 transition-colors shadow-md\">Finish & Grade Exam<\/button>\n            <\/div>\n\n            <div id=\"results-section\" class=\"hidden text-center mt-12\">\n                <h2 class=\"text-3xl font-bold text-stone-900 mb-2\">Exam Complete!<\/h2>\n                <p class=\"text-stone-600 mb-6\">Here's how you did:<\/p>\n                <div class=\"chart-container\">\n                    <canvas id=\"resultsChart\"><\/canvas>\n                <\/div>\n                <p id=\"score-text\" class=\"text-xl font-bold mt-4\"><\/p>\n                <div class=\"mt-8\">\n                    <button type=\"button\" id=\"restart-btn\" class=\"px-8 py-3 bg-stone-700 text-white font-bold rounded-lg hover:bg-stone-800 transition-colors shadow-md\">Try Again<\/button>\n                <\/div>\n            <\/div>\n        <input type=\"hidden\" name=\"trp-form-language\" value=\"km\"\/><\/form>\n    <\/div>\n\n<script>\ndocument.addEventListener('DOMContentLoaded', () => {\n\n    const quizData = {\n        mcq: [\n            { question: \"What is the main purpose of the `pygame.init()` function?\", options: [\"To set the screen dimensions.\", \"To initialize all the Pygame modules.\", \"To start the game loop.\", \"To load an image.\"], answer: \"To initialize all the Pygame modules.\" },\n            { question: \"In a standard game loop, which of these is NOT one of the three core phases?\", options: [\"Handling events (user input).\", \"Updating the game state.\", \"Drawing to the screen.\", \"Installing new libraries.\"], answer: \"Installing new libraries.\" },\n            { question: \"What does the `pygame.display.flip()` function do?\", options: [\"It flips all the images on the screen upside down.\", \"It updates the entire screen surface to show everything that has been drawn.\", \"It quits the game.\", \"It checks for user input.\"], answer: \"It updates the entire screen surface to show everything that has been drawn.\" },\n            { question: \"In Pygame, what is a `Surface`?\", options: [\"The physical computer screen.\", \"A rectangular object used only for collision detection.\", \"A blank canvas that can be drawn on, including the main display window.\", \"A function for playing sound effects.\"], answer: \"A blank canvas that can be drawn on, including the main display window.\" },\n            { question: \"How do you check if the user has pressed the `ESC` key in the event loop?\", options: [\"if event.key == pygame.K_ESCAPE:\", \"if event.type == pygame.KEYDOWN:\", \"if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:\", \"if pygame.key.get_pressed(pygame.K_ESCAPE):\"], answer: \"if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:\" }\n        ],\n        terminology: [\n            { question: \"The continuous cycle that runs the game is called the ___.\", options: [\"Game Loop\", \"Event Handler\", \"Render Cycle\", \"Main Function\"], answer: \"Game Loop\" },\n            { question: \"To draw a `Surface` onto another `Surface`, you use the `screen.`___`(image, rect)` method.\", options: [\"blit\", \"draw\", \"render\", \"paste\"], answer: \"blit\" },\n            { question: \"A `pygame.`___ object is used to store rectangular coordinates.\", options: [\"Rect\", \"Surface\", \"Shape\", \"Box\"], answer: \"Rect\" },\n            { question: \"To load a background music file, you would use `pygame.mixer.music.`___`('music.mp3')`.\", options: [\"load\", \"play\", \"open\", \"stream\"], answer: \"load\" },\n            { question: \"To detect a collision between two rects (`rect1`, `rect2`), you can use `rect1.`___`(rect2)`.\", options: [\"colliderect\", \"has_collided\", \"touches\", \"overlaps\"], answer: \"colliderect\" }\n        ]\n    };\n\n    const welcomeScreen = document.getElementById('welcome-screen');\n    const examForm = document.getElementById('exam-form');\n    const mcqContainer = document.getElementById('mcq-questions-container');\n    const termContainer = document.getElementById('terminology-questions-container');\n    const resultsSection = document.getElementById('results-section');\n    const startBtn = document.getElementById('start-btn');\n    const restartBtn = document.getElementById('restart-btn');\n    \n    function buildQuestion(questionData, index, type) {\n        const q = questionData;\n        const questionIndex = type === 'mcq' ? index : index + quizData.mcq.length;\n        \n        const questionWrapper = document.createElement('div');\n        questionWrapper.id = `question-${questionIndex}`;\n\n        const questionText = document.createElement('h3');\n        questionText.classList.add('text-lg', 'font-semibold', 'text-stone-800', 'mb-4');\n        const questionNumber = document.createElement('span');\n        questionNumber.classList.add('mr-2', 'font-bold', 'text-teal-600');\n        questionNumber.textContent = `${questionIndex + 1}.`;\n        \n        const questionContent = document.createElement('span');\n        questionContent.innerHTML = q.question.replace('___', '<span class=\"font-bold text-teal-600\">___<\/span>');\n\n        questionText.appendChild(questionNumber);\n        questionText.appendChild(questionContent);\n        \n        const optionsWrapper = document.createElement('div');\n        optionsWrapper.classList.add('flex', 'flex-col', 'space-y-3');\n        \n        q.options.forEach((optionText, optionIndex) => {\n            const optionId = `q${questionIndex}-o${optionIndex}`;\n            \n            const radio = document.createElement('input');\n            radio.type = 'radio';\n            radio.id = optionId;\n            radio.name = `question-${questionIndex}`;\n            radio.value = optionText;\n            \n            const label = document.createElement('label');\n            label.htmlFor = optionId;\n            label.classList.add('p-3', 'border-2', 'border-stone-300', 'rounded-lg', 'text-left', 'hover:bg-stone-100', 'hover:border-teal-400');\n            \n            const checkboxBox = document.createElement('span');\n            checkboxBox.classList.add('checkbox-box');\n\n            const optionTextSpan = document.createElement('span');\n            optionTextSpan.textContent = optionText;\n\n            label.appendChild(checkboxBox);\n            label.appendChild(optionTextSpan);\n            \n            optionsWrapper.appendChild(radio);\n            optionsWrapper.appendChild(label);\n        });\n        \n        questionWrapper.appendChild(questionText);\n        questionWrapper.appendChild(optionsWrapper);\n        \n        return questionWrapper;\n    }\n    \n    function startExam() {\n        welcomeScreen.classList.add('hidden');\n        examForm.classList.remove('hidden');\n        resultsSection.classList.add('hidden');\n        mcqContainer.innerHTML = '';\n        termContainer.innerHTML = '';\n\n        quizData.mcq.forEach((q, i) => mcqContainer.appendChild(buildQuestion(q, i, 'mcq')));\n        quizData.terminology.forEach((q, i) => termContainer.appendChild(buildQuestion(q, i, 'term')));\n        \n        initGameCanvas();\n    }\n\n    function gradeExam(event) {\n        event.preventDefault();\n        let score = 0;\n        const totalQuestions = quizData.mcq.length + quizData.terminology.length;\n\n        const processAnswers = (questions, type, offset) => {\n            questions.forEach((q, index) => {\n                const questionIndex = index + offset;\n                const questionWrapper = document.getElementById(`question-${questionIndex}`);\n                const selectedRadio = questionWrapper.querySelector(`input[name=\"question-${questionIndex}\"]:checked`);\n                const labels = questionWrapper.querySelectorAll('label');\n\n                labels.forEach(label => {\n                    label.classList.remove('feedback-correct', 'feedback-incorrect');\n                });\n\n                if (selectedRadio) {\n                    const selectedLabel = questionWrapper.querySelector(`label[for=\"${selectedRadio.id}\"]`);\n                    if (selectedRadio.value === q.answer) {\n                        score++;\n                        selectedLabel.classList.add('feedback-correct');\n                    } else {\n                        selectedLabel.classList.add('feedback-incorrect');\n                        const correctRadio = Array.from(questionWrapper.querySelectorAll('input')).find(r => r.value === q.answer);\n                        if (correctRadio) {\n                           const correctLabel = questionWrapper.querySelector(`label[for=\"${correctRadio.id}\"]`);\n                           correctLabel.classList.add('feedback-correct');\n                        }\n                    }\n                } else {\n                    \/\/ No answer selected, mark the correct one\n                    const correctRadio = Array.from(questionWrapper.querySelectorAll('input')).find(r => r.value === q.answer);\n                    if (correctRadio) {\n                        const correctLabel = questionWrapper.querySelector(`label[for=\"${correctRadio.id}\"]`);\n                        correctLabel.classList.add('feedback-correct');\n                    }\n                }\n            });\n        };\n\n        processAnswers(quizData.mcq, 'mcq', 0);\n        processAnswers(quizData.terminology, 'term', quizData.mcq.length);\n\n        showResults(score, totalQuestions);\n    }\n    \n    function showResults(finalScore, totalQuestions) {\n        resultsSection.classList.remove('hidden');\n        document.getElementById('score-text').textContent = `You scored ${finalScore} out of ${totalQuestions}!`;\n        \n        const chartEl = document.getElementById('resultsChart');\n        if (chartEl.chart) {\n            chartEl.chart.destroy();\n        }\n        const resultsChartCtx = chartEl.getContext('2d');\n        chartEl.chart = new Chart(resultsChartCtx, {\n            type: 'doughnut',\n            data: {\n                labels: ['Correct', 'Incorrect'],\n                datasets: [{\n                    data: [finalScore, totalQuestions - finalScore],\n                    backgroundColor: ['#14b8a6', '#f43f5e'],\n                    borderColor: ['#ffffff'],\n                    borderWidth: 4\n                }]\n            },\n            options: {\n                responsive: true, maintainAspectRatio: false, cutout: '70%',\n                plugins: { legend: { display: false } }\n            }\n        });\n        resultsSection.scrollIntoView({ behavior: 'smooth' });\n    }\n\n    function restartExam() {\n        welcomeScreen.classList.remove('hidden');\n        examForm.classList.add('hidden');\n    }\n\n    \/\/ --- Canvas Logic ---\n    let gameCanvas, gameCtx, player, coin, canvasWidth, canvasHeight;\n    let mousePos = { x: 0, y: 0 };\n    let animationFrameId;\n\n    function initGameCanvas() {\n        gameCanvas = document.getElementById('gameCanvas');\n        if (!gameCanvas) return;\n        const parent = gameCanvas.parentElement;\n        gameCanvas.width = parent.clientWidth;\n        gameCanvas.height = parent.clientHeight;\n        canvasWidth = gameCanvas.width;\n        canvasHeight = gameCanvas.height;\n        gameCtx = gameCanvas.getContext('2d');\n        \n        player = { radius: 20 };\n        coin = { x: Math.random() * (canvasWidth - 30), y: Math.random() * (canvasHeight - 30), w: 30, h: 30 };\n        \n        gameCanvas.addEventListener('mousemove', e => {\n            const rect = gameCanvas.getBoundingClientRect();\n            mousePos = { x: e.clientX - rect.left, y: e.clientY - rect.top };\n        });\n        \n        if (animationFrameId) cancelAnimationFrame(animationFrameId);\n        gameLoop();\n    }\n    \n    function gameLoop() {\n        \/\/ Update\n        const playerRect = { x: mousePos.x - player.radius, y: mousePos.y - player.radius, w: player.radius * 2, h: player.radius * 2 };\n        if (playerRect.x < coin.x + coin.w && playerRect.x + playerRect.w > coin.x &&\n            playerRect.y < coin.y + coin.h && playerRect.y + playerRect.h > coin.y) {\n            coin.x = Math.random() * (canvasWidth - 30);\n            coin.y = Math.random() * (canvasHeight - 30);\n        }\n\n        \/\/ Draw\n        gameCtx.fillStyle = '#1e293b'; \/\/ slate-800\n        gameCtx.fillRect(0, 0, canvasWidth, canvasHeight);\n        gameCtx.fillStyle = '#facc15'; \/\/ yellow-400\n        gameCtx.fillRect(coin.x, coin.y, coin.w, coin.h);\n        gameCtx.fillStyle = '#3b82f6'; \/\/ blue-500\n        gameCtx.beginPath();\n        gameCtx.arc(mousePos.x, mousePos.y, player.radius, 0, Math.PI * 2);\n        gameCtx.fill();\n\n        animationFrameId = requestAnimationFrame(gameLoop);\n    }\n    \n    \/\/ Event Listeners\n    startBtn.addEventListener('click', startExam);\n    examForm.addEventListener('submit', gradeExam);\n    restartBtn.addEventListener('click', restartExam);\n});\n<\/script>\n<\/body>\n<\/html>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>Interactive Pygame Exam Pygame Fundamentals Exam Test your knowledge with this interactive quiz. All questions are on one page. Submit at the end to see your score. Start Exam Part 1: Multiple Choice Part 2: Terminology Check Part 3: Coding Challenge Review Review the objective for the coding challenge. A live demonstration of the correct [&hellip;]<\/p>","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"om_disable_all_campaigns":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4172","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/aaaschoolkh.com\/km\/wp-json\/wp\/v2\/posts\/4172","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/aaaschoolkh.com\/km\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/aaaschoolkh.com\/km\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/aaaschoolkh.com\/km\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/aaaschoolkh.com\/km\/wp-json\/wp\/v2\/comments?post=4172"}],"version-history":[{"count":4,"href":"https:\/\/aaaschoolkh.com\/km\/wp-json\/wp\/v2\/posts\/4172\/revisions"}],"predecessor-version":[{"id":4176,"href":"https:\/\/aaaschoolkh.com\/km\/wp-json\/wp\/v2\/posts\/4172\/revisions\/4176"}],"wp:attachment":[{"href":"https:\/\/aaaschoolkh.com\/km\/wp-json\/wp\/v2\/media?parent=4172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/aaaschoolkh.com\/km\/wp-json\/wp\/v2\/categories?post=4172"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/aaaschoolkh.com\/km\/wp-json\/wp\/v2\/tags?post=4172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}