| 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(); |
|
|
| }); |