// 配列をランダムに並び替える関数 function shuffleArray(array) { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array; } // Leaflet地図の初期化 const map = L.map('map').setView([35.681236, 139.767125], 16); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); let playerMarker; // プレイヤーの現在地マーカー let activeArea = null; // 現在のアクティブなエリア const puzzleAreas = []; // パズルエリア let currentQuestionIndex = 0; // 現在のクイズインデックス let shuffledQuizData = []; // シャッフルされたクイズデータ // クイズデータ const quizData = [ { location: [35.681236, 139.767125], question: "日本の首都は?", options: ["大阪", "東京", "京都"], answer: "東京" }, { location: [35.683236, 139.769125], question: "桜の季節はいつ?", options: ["春", "夏", "冬"], answer: "春" }, { location: [35.685236, 139.771125], question: "日本の通貨単位は?", options: ["ドル", "円", "ユーロ"], answer: "円" }, { location: [35.687236, 139.773125], question: "日本の国旗は何色?", options: ["赤と白", "青と白", "緑と白"], answer: "赤と白" }, { location: [35.689236, 139.775125], question: "富士山の高さは約何メートル?", options: ["3776", "2000", "4500"], answer: "3776" }, ]; // 距離を計算 function calculateDistance(lat1, lng1, lat2, lng2) { const R = 6371000; const dLat = (lat2 - lat1) * Math.PI / 180; const dLng = (lng2 - lng1) * Math.PI / 180; const a = Math.sin(dLat / 2) ** 2 + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLng / 2) ** 2; const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return R * c; } // プレイヤーの初期位置 function initializePlayer() { playerMarker = L.marker(shuffledQuizData[0].location, { draggable: true }).addTo(map).bindPopup('現在地'); map.setView(shuffledQuizData[0].location, 16); playerMarker.on('dragend', () => { const position = playerMarker.getLatLng(); checkProximity(position.lat, position.lng); }); } // パズルエリアを初期化 function initializePuzzleAreas() { shuffledQuizData.forEach(data => { const area = L.circle(data.location, { radius: 100, color: 'blue', fillOpacity: 0.2 }).addTo(map); puzzleAreas.push(area); }); } // 距離チェック function checkProximity(lat, lng) { const activeQuiz = shuffledQuizData[currentQuestionIndex]; const distance = calculateDistance(lat, lng, activeQuiz.location[0], activeQuiz.location[1]); document.getElementById('distance').innerText = Math.round(distance); if (distance < 100 && activeArea !== activeQuiz) { activeArea = activeQuiz; showQuizModal(activeQuiz); } } // クイズモーダルを表示 function showQuizModal(quiz) { const modal = document.getElementById('quizModal'); modal.style.display = 'block'; document.getElementById('quizQuestion').innerText = quiz.question; const optionsContainer = document.getElementById('quizOptions'); optionsContainer.innerHTML = ''; quiz.options.forEach(option => { const input = document.createElement('input'); input.type = 'radio'; input.name = 'quizOption'; input.value = option; input.id = option; const label = document.createElement('label'); label.htmlFor = option; label.innerText = option; const div = document.createElement('div'); div.appendChild(input); div.appendChild(label); optionsContainer.appendChild(div); }); document.getElementById('quizMessage').innerText = ''; } // 回答をチェック function checkAnswer() { const selectedOption = document.querySelector('input[name="quizOption"]:checked'); if (!selectedOption) { document.getElementById('quizMessage').innerText = '回答を選択してください。'; return; } const activeQuiz = shuffledQuizData[currentQuestionIndex]; if (selectedOption.value === activeQuiz.answer) { alert('正解です!次のエリアに進んでください。'); currentQuestionIndex++; if (currentQuestionIndex >= shuffledQuizData.length) { alert('ゲームクリア!すべての問題に正解しました!'); resetGame(); } document.getElementById('quizModal').style.display = 'none'; } else { alert('不正解です。もう一度挑戦してください!'); activeArea = null; // 不正解時にエリアをリセット document.getElementById('quizModal').style.display = 'none'; } } // ゲーム開始 function startGame() { shuffledQuizData = shuffleArray([...quizData]); currentQuestionIndex = 0; activeArea = null; initializePlayer(); initializePuzzleAreas(); } // リセット function resetGame() { map.eachLayer(layer => { if (layer instanceof L.Marker || layer instanceof L.Circle) { map.removeLayer(layer); } }); startGame(); } // イベントリスナー document.getElementById('startGame').addEventListener('click', startGame); document.getElementById('resetGame').addEventListener('click', resetGame); document.getElementById('submitAnswer').addEventListener('click', checkAnswer);