| | document.addEventListener('DOMContentLoaded', () => { |
| | const scoreDisplay = document.getElementById('score'); |
| | const totalQuestionsDisplay = document.getElementById('total-questions'); |
| | const num1Display = document.getElementById('num1'); |
| | const num2Display = document.getElementById('num2'); |
| | const feedbackArea = document.getElementById('feedback-area'); |
| | const fieldChoicesContainer = document.getElementById('field-choices'); |
| |
|
| | const OPTIONS_COUNT = 3; |
| | const MAX_FACTOR = 6; |
| | const TOTAL_ROUNDS = 10; |
| |
|
| | |
| | const farmItems = ['π', 'π₯', 'π', 'π', 'π»', 'π½']; |
| |
|
| | |
| | let possibleProblems = []; |
| | function generateProblems() { |
| | possibleProblems = []; |
| | for (let i = 1; i <= MAX_FACTOR; i++) { |
| | |
| | for (let j = 1; j <= MAX_FACTOR; j++) { |
| | possibleProblems.push({ num1: i, num2: j, answer: i * j }); |
| | } |
| | } |
| | |
| | } |
| |
|
| | |
| | let score = 0; |
| | let currentProblem = null; |
| | let currentRound = 0; |
| | let waitingForNext = false; |
| |
|
| | |
| | function getRandomInt(max) { |
| | return Math.floor(Math.random() * max); |
| | } |
| |
|
| | |
| | function shuffleArray(array) { |
| | for (let i = array.length - 1; i > 0; i--) { |
| | const j = getRandomInt(i + 1); |
| | [array[i], array[j]] = [array[j], array[i]]; |
| | } |
| | } |
| |
|
| | |
| | function setupNewRound() { |
| | if (currentRound >= TOTAL_ROUNDS) { |
| | endGame(); |
| | return; |
| | } |
| |
|
| | waitingForNext = false; |
| | fieldChoicesContainer.innerHTML = ''; |
| | feedbackArea.textContent = "Click the farm plot that matches the problem!"; |
| | feedbackArea.className = ''; |
| |
|
| | currentRound++; |
| |
|
| | |
| | if (!possibleProblems || possibleProblems.length === 0) generateProblems(); |
| | const problemIndex = getRandomInt(possibleProblems.length); |
| | currentProblem = possibleProblems.splice(problemIndex, 1)[0]; |
| |
|
| | num1Display.textContent = currentProblem.num1; |
| | num2Display.textContent = currentProblem.num2; |
| |
|
| | |
| | |
| | const correctOption = { rows: currentProblem.num1, cols: currentProblem.num2 }; |
| | const options = [correctOption]; |
| |
|
| | |
| | while (options.length < OPTIONS_COUNT) { |
| | let wrongRows, wrongCols; |
| | let isDuplicate = true; |
| | let attempts = 0; |
| |
|
| | while(isDuplicate && attempts < 20) { |
| | |
| | const changeRows = Math.random() > 0.5; |
| | wrongRows = changeRows ? getRandomInt(MAX_FACTOR) + 1 : correctOption.rows; |
| | wrongCols = !changeRows ? getRandomInt(MAX_FACTOR) + 1 : correctOption.cols; |
| |
|
| | |
| | if((wrongRows !== correctOption.rows || wrongCols !== correctOption.cols) && |
| | (wrongRows * wrongCols > 0) ) { |
| |
|
| | |
| | isDuplicate = options.some(opt => |
| | (opt.rows === wrongRows && opt.cols === wrongCols) || |
| | (opt.rows === wrongCols && opt.cols === wrongRows) |
| | ); |
| | } else { |
| | isDuplicate = true; |
| | } |
| | attempts++; |
| | } |
| | |
| | if (attempts >= 20) { |
| | wrongRows = correctOption.rows === 1 ? 2 : correctOption.rows -1; |
| | wrongCols = correctOption.cols; |
| | isDuplicate = options.some(opt => |
| | (opt.rows === wrongRows && opt.cols === wrongCols) || |
| | (opt.rows === wrongCols && opt.cols === wrongRows) |
| | ); |
| | } |
| |
|
| |
|
| | if (!isDuplicate) { |
| | options.push({ rows: wrongRows, cols: wrongCols }); |
| | } |
| | } |
| |
|
| | |
| | shuffleArray(options); |
| |
|
| | |
| | options.forEach(plot => { |
| | const fieldDiv = document.createElement('div'); |
| | fieldDiv.classList.add('field-option'); |
| | fieldDiv.dataset.rows = plot.rows; |
| | fieldDiv.dataset.cols = plot.cols; |
| |
|
| | |
| | fieldDiv.style.gridTemplateColumns = `repeat(${plot.cols}, auto)`; |
| | fieldDiv.style.gridTemplateRows = `repeat(${plot.rows}, auto)`; |
| | |
| | fieldDiv.style.maxWidth = `${plot.cols * 35}px`; |
| |
|
| |
|
| | |
| | const itemEmoji = farmItems[getRandomInt(farmItems.length)]; |
| | for (let i = 0; i < plot.rows * plot.cols; i++) { |
| | const itemSpan = document.createElement('span'); |
| | itemSpan.classList.add('item'); |
| | itemSpan.textContent = itemEmoji; |
| | fieldDiv.appendChild(itemSpan); |
| | } |
| |
|
| | fieldDiv.addEventListener('click', handleChoiceClick); |
| | fieldChoicesContainer.appendChild(fieldDiv); |
| | }); |
| |
|
| | console.log("New round setup. Target:", currentProblem); |
| | } |
| |
|
| | |
| | function handleChoiceClick(event) { |
| | if (waitingForNext) return; |
| |
|
| | const clickedField = event.currentTarget; |
| | const clickedRows = parseInt(clickedField.dataset.rows); |
| | const clickedCols = parseInt(clickedField.dataset.cols); |
| |
|
| | waitingForNext = true; |
| |
|
| | |
| | document.querySelectorAll('.field-option').forEach(opt => { |
| | const clone = opt.cloneNode(true); |
| | opt.parentNode.replaceChild(clone, opt); |
| | }); |
| |
|
| | |
| | const isCorrect = (clickedRows === currentProblem.num1 && clickedCols === currentProblem.num2) || |
| | (clickedRows === currentProblem.num2 && clickedCols === currentProblem.num1); |
| |
|
| | if (isCorrect) { |
| | score++; |
| | scoreDisplay.textContent = score; |
| | feedbackArea.textContent = `Yes! ${currentProblem.num1} x ${currentProblem.num2} = ${currentProblem.answer}! π`; |
| | feedbackArea.className = 'correct-feedback'; |
| |
|
| | const newClickedElement = fieldChoicesContainer.querySelector(`.field-option[data-rows="${clickedRows}"][data-cols="${clickedCols}"]`); |
| | if (newClickedElement) newClickedElement.classList.add('correct-choice'); |
| |
|
| | } else { |
| | feedbackArea.textContent = `Oops! That shows ${clickedRows} x ${clickedCols}. The answer was ${currentProblem.answer}. π€`; |
| | feedbackArea.className = 'incorrect-feedback'; |
| |
|
| | const newClickedElement = fieldChoicesContainer.querySelector(`.field-option[data-rows="${clickedRows}"][data-cols="${clickedCols}"]`); |
| | if (newClickedElement) newClickedElement.classList.add('incorrect-choice'); |
| |
|
| | |
| | setTimeout(() => { |
| | const correctElement1 = fieldChoicesContainer.querySelector(`.field-option[data-rows="${currentProblem.num1}"][data-cols="${currentProblem.num2}"]`); |
| | if (correctElement1) correctElement1.classList.add('correct-choice'); |
| | |
| | const correctElement2 = fieldChoicesContainer.querySelector(`.field-option[data-rows="${currentProblem.num2}"][data-cols="${currentProblem.num1}"]`); |
| | if (correctElement2 && correctElement1 !== correctElement2) correctElement2.classList.add('correct-choice'); |
| | }, 300); |
| | } |
| |
|
| | |
| | setTimeout(setupNewRound, 2500); |
| | } |
| |
|
| | |
| | function endGame() { |
| | feedbackArea.textContent = `Game Over! Your final score: ${score} / ${TOTAL_ROUNDS}! Great work! π₯³`; |
| | feedbackArea.className = 'correct-feedback'; |
| | fieldChoicesContainer.innerHTML = '<p style="font-size:1.2em; color: #795548;">Refresh the page to play again!</p>'; |
| | |
| | } |
| |
|
| | |
| | totalQuestionsDisplay.textContent = TOTAL_ROUNDS; |
| | generateProblems(); |
| | setupNewRound(); |
| |
|
| | }); |