Lashtw commited on
Commit
78bf12a
·
verified ·
1 Parent(s): 938bb2b

Upload 40 files

Browse files
Files changed (4) hide show
  1. .gitattributes +1 -0
  2. Theme.mp3 +3 -0
  3. index.html +2 -3
  4. tower.js +228 -205
.gitattributes CHANGED
@@ -42,3 +42,4 @@ valley.jpg filter=lfs diff=lfs merge=lfs -text
42
  valley.mp3 filter=lfs diff=lfs merge=lfs -text
43
  tower.jpg filter=lfs diff=lfs merge=lfs -text
44
  tower.mp3 filter=lfs diff=lfs merge=lfs -text
 
 
42
  valley.mp3 filter=lfs diff=lfs merge=lfs -text
43
  tower.jpg filter=lfs diff=lfs merge=lfs -text
44
  tower.mp3 filter=lfs diff=lfs merge=lfs -text
45
+ Theme.mp3 filter=lfs diff=lfs merge=lfs -text
Theme.mp3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:91fe1ace3e637b39f05c9d5067b91c78d06d4a62217416dffd2998e75633304f
3
+ size 2676118
index.html CHANGED
@@ -9,7 +9,7 @@
9
  <body class="home-page">
10
  <!-- 音效元素 -->
11
  <audio id="bgm" loop>
12
- <source src="bgm.mp3" type="audio/mpeg">
13
  </audio>
14
 
15
  <div class="game-container">
@@ -24,8 +24,7 @@
24
 
25
  <!-- 音樂來源註記 -->
26
  <div class="music-credit">
27
- <p>背景音樂:샛별 - Level Up</p>
28
- <p>推廣:J&B無版權音樂庫 <a href="https://bit.ly/2YfWIhw" target="_blank">https://bit.ly/2YfWIhw</a></p>
29
  <button id="toggle-bgm" class="small-btn">音樂開/關</button>
30
  </div>
31
  </div>
 
9
  <body class="home-page">
10
  <!-- 音效元素 -->
11
  <audio id="bgm" loop>
12
+ <source src="Theme.mp3" type="audio/mpeg">
13
  </audio>
14
 
15
  <div class="game-container">
 
24
 
25
  <!-- 音樂來源註記 -->
26
  <div class="music-credit">
27
+ <p>背景音樂:由Suno智做</p>
 
28
  <button id="toggle-bgm" class="small-btn">音樂開/關</button>
29
  </div>
30
  </div>
tower.js CHANGED
@@ -316,7 +316,7 @@ document.addEventListener('DOMContentLoaded', function() {
316
  const dropZoneSortable = new Sortable(dropZone, {
317
  group: {
318
  name: 'formula',
319
- pull: true,
320
  put: true
321
  },
322
  animation: 100,
@@ -352,6 +352,11 @@ document.addEventListener('DOMContentLoaded', function() {
352
  evt.from.classList.remove('filled');
353
  evt.from.style.backgroundColor = 'rgba(100, 100, 100, 0.5)';
354
 
 
 
 
 
 
355
  // 更新保存的答案
356
  updateSavedAnswers();
357
  }
@@ -382,6 +387,8 @@ document.addEventListener('DOMContentLoaded', function() {
382
  dragItem.id = `drag-item-${index}`;
383
  dragItem.textContent = item;
384
  dragItem.dataset.value = item;
 
 
385
 
386
  // 添加點擊事件,點擊可移除(如果在拖放區內)
387
  dragItem.addEventListener('click', function() {
@@ -406,8 +413,8 @@ document.addEventListener('DOMContentLoaded', function() {
406
  const dragItemsSortable = new Sortable(dragItemsContainer, {
407
  group: {
408
  name: 'formula',
409
- pull: 'clone', // 設置為clone模式,拖拽時複製元素
410
- put: true
411
  },
412
  animation: 100,
413
  delay: 0,
@@ -415,20 +422,17 @@ document.addEventListener('DOMContentLoaded', function() {
415
  ghostClass: "drag-ghost",
416
  forceFallback: true,
417
  fallbackTolerance: 3,
418
- sort: false, // 禁止在容器內排序
419
  filter: '.disabled', // 禁止拖拽的元素
420
- onStart: function(evt) {
421
- evt.item.style.opacity = '0.8';
422
- },
423
- onEnd: function(evt) {
424
- evt.item.style.opacity = '1';
425
- },
426
- // 當元素被複製時
427
  onClone: function(evt) {
428
- const clone = evt.clone;
 
 
 
 
429
 
430
- // 為複製的元素添加點擊事件,點擊可移除(如果在拖放區內)
431
- clone.addEventListener('click', function() {
432
  const parent = this.parentElement;
433
  if (parent && parent.classList.contains('drop-zone')) {
434
  parent.classList.remove('filled');
@@ -446,19 +450,19 @@ document.addEventListener('DOMContentLoaded', function() {
446
 
447
  sortableInstances.push(dragItemsSortable);
448
 
449
- // 恢復已保存的答案
450
- if (savedAnswers.length > 0) {
451
  savedAnswers.forEach((value, index) => {
452
- if (index < dropZones.length) {
453
  // 找到對應值的拖拽項
454
- const dragItem = Array.from(dragItemElements).find(item => item.dataset.value === value);
455
- if (dragItem) {
456
- // 複製拖拽項
457
- const clonedItem = dragItem.cloneNode(true);
458
- clonedItem.dataset.value = value;
459
 
460
  // 添加點擊事件,點擊可移除
461
- clonedItem.addEventListener('click', function() {
462
  const parent = this.parentElement;
463
  if (parent && parent.classList.contains('drop-zone')) {
464
  parent.classList.remove('filled');
@@ -473,7 +477,7 @@ document.addEventListener('DOMContentLoaded', function() {
473
  });
474
 
475
  // 添加到拖放區
476
- dropZones[index].appendChild(clonedItem);
477
  dropZones[index].classList.add('filled');
478
  dropZones[index].style.backgroundColor = 'rgba(255, 140, 0, 0.3)';
479
  }
@@ -482,247 +486,243 @@ document.addEventListener('DOMContentLoaded', function() {
482
  }
483
 
484
  // 顯示檢查答案按鈕,隱藏下一題按鈕
485
- checkAnswerBtn.style.display = 'block';
486
  nextQuestionBtn.style.display = 'none';
487
 
488
- // 隱藏反饋容器
 
489
  feedbackContainer.style.display = 'none';
490
- feedbackContainer.className = 'feedback-container';
491
  }
492
 
493
  // 更新保存的答案
494
  function updateSavedAnswers() {
495
  const answers = [];
496
 
497
- // 獲取所有拖放區的值
498
  dropZones.forEach(zone => {
499
- const items = Array.from(zone.children);
500
  if (items.length > 0) {
501
- const value = items[0].dataset.value;
502
- answers.push(value);
503
  } else {
504
  answers.push(null);
505
  }
506
  });
507
 
508
- // 過濾掉null值
509
- const filteredAnswers = answers.filter(answer => answer !== null);
510
-
511
  // 保存答案
512
  if (currentStage === 1) {
513
- stage1Answers[currentQuestionIndex] = filteredAnswers;
514
  } else {
515
- stage2Answers[currentQuestionIndex] = filteredAnswers;
516
  }
517
  }
518
 
519
- // 檢查答案按鈕點擊事件
520
- checkAnswerBtn.addEventListener('click', function() {
521
  // 獲取當前階段的問題數據
522
  const stageData = currentStage === 1 ? questions[currentQuestionIndex].stage1 : questions[currentQuestionIndex].stage2;
523
 
524
  // 獲取用戶答案
525
- const userAnswers = currentStage === 1 ? stage1Answers[currentQuestionIndex] : stage2Answers[currentQuestionIndex];
 
 
 
 
 
 
 
 
526
 
527
- // 檢查是否拖放區都有值
528
- if (userAnswers.length < dropZones.length) {
529
- feedbackContainer.textContent = '請填寫所有空格!';
530
- feedbackContainer.className = 'feedback-container incorrect';
531
  feedbackContainer.style.display = 'block';
532
- wrongSound.play();
533
- return;
534
  }
535
 
536
  // 檢查答案是否正確
537
- const isCorrect = checkAnswer(userAnswers, stageData.answers);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
538
 
539
  if (isCorrect) {
540
- // 答案正確
541
- feedbackContainer.textContent = '答對了!';
542
- feedbackContainer.className = 'feedback-container correct';
543
- feedbackContainer.style.display = 'block';
544
- correctSound.play();
 
 
 
 
 
 
 
545
 
546
- // 如果是第一階段,啟用第二階段按鈕
547
  if (currentStage === 1) {
548
- stage2Btn.disabled = false;
549
-
550
- // 顯示下一題按鈕,隱藏檢查答案按鈕
551
- checkAnswerBtn.style.display = 'none';
552
- nextQuestionBtn.style.display = 'block';
553
  nextQuestionBtn.textContent = '進入第二階段';
554
  nextQuestionBtn.onclick = function() {
555
  loadQuestion(currentQuestionIndex, 2);
556
  };
557
  } else {
558
- // 如果是第二階段,標記問為已完成
559
- correctAnswers++;
560
-
561
- // 打開對應的門
562
- if (currentQuestionIndex < doorsProgress.length) {
563
- doorsProgress[currentQuestionIndex].classList.add('opened');
564
- }
565
-
566
- // 如果還有下一題,顯示下一題按鈕
567
  if (currentQuestionIndex < questions.length - 1) {
568
- checkAnswerBtn.style.display = 'none';
569
- nextQuestionBtn.style.display = 'block';
570
  nextQuestionBtn.textContent = '下一題';
571
  nextQuestionBtn.onclick = function() {
572
  loadQuestion(currentQuestionIndex + 1, 1);
573
  };
574
  } else {
575
- // 如果是最後一題,顯示結果
576
- showResult();
 
 
577
  }
578
  }
 
 
 
 
 
 
 
 
 
 
579
  } else {
580
- // 答案錯誤
 
 
 
 
581
  wrongAttempts++;
582
- wrongSound.play();
583
 
 
584
  if (currentStage === 1) {
585
- // 第一階段答錯
586
- if (wrongAttempts === 1) {
587
- // 第一次答錯,顯示提示圖片
588
- showHintImage();
 
 
 
 
 
 
 
589
 
590
- feedbackContainer.textContent = '答錯了,請參考上方提示修正答案!';
591
- feedbackContainer.className = 'feedback-container incorrect';
592
- feedbackContainer.style.display = 'block';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
593
  } else {
594
- // 第二次或更多次,顯示正確答案
595
- showHintImage();
596
-
597
- const correctAnswerText = questions[currentQuestionIndex].stage1.correctAnswer;
598
- feedbackContainer.innerHTML = `答錯了,請參考上方提示修正答案!<br><br>正確答案應為:<br>「${correctAnswerText}」<br>請依照此答案填入,才能進入第二階段。`;
599
- feedbackContainer.className = 'feedback-container incorrect';
600
- feedbackContainer.style.display = 'block';
601
  }
 
 
 
 
 
 
 
 
602
  } else {
603
- // 第二階段
604
- feedbackContainer.textContent = '答錯了,請再試一次!';
605
- feedbackContainer.className = 'feedback-container incorrect';
606
- feedbackContainer.style.display = 'block';
 
607
  }
608
- }
609
- });
610
-
611
- // 顯示提示圖片
612
- function showHintImage() {
613
- // 移除現有的提示容器
614
- const existingHintContainers = document.querySelectorAll('.hint-container');
615
- existingHintContainers.forEach(container => container.remove());
616
-
617
- // 創建提示容器
618
- const hintContainer = document.createElement('div');
619
- hintContainer.className = 'hint-container';
620
- hintContainer.style.marginBottom = '15px';
621
- hintContainer.style.padding = '10px';
622
- hintContainer.style.backgroundColor = 'rgba(60, 60, 60, 0.7)';
623
- hintContainer.style.borderRadius = '8px';
624
- hintContainer.style.border = '1px solid rgba(255, 140, 0, 0.5)';
625
- hintContainer.style.textAlign = 'center';
626
-
627
- // 創建提示圖片
628
- const hintImage = document.createElement('img');
629
- hintImage.src = `towerhint${currentQuestionIndex + 1}1.jpg`;
630
- hintImage.style.maxWidth = '50%';
631
- hintImage.style.height = 'auto';
632
- hintImage.style.marginBottom = '10px';
633
- hintContainer.appendChild(hintImage);
634
-
635
- // 創建提示文字
636
- const hintText = document.createElement('div');
637
- hintText.textContent = '請仔細觀察上方提示圖,按照分配律的方式展開填入正確答案。';
638
- hintText.style.color = 'white';
639
- hintText.style.fontSize = '1rem';
640
- hintContainer.appendChild(hintText);
641
-
642
- // 插入到公式模板前面
643
- formulaTemplate.parentNode.insertBefore(hintContainer, formulaTemplate);
644
- }
645
-
646
- // 檢查答案是否正確
647
- function checkAnswer(userAnswers, correctAnswerSets) {
648
- // 如果用戶答案長度不符合任何一組正確答案,直接返回false
649
- const isLengthMatch = correctAnswerSets.some(set => set.length === userAnswers.length);
650
- if (!isLengthMatch) return false;
651
-
652
- // 檢查每組正確答案
653
- for (const correctSet of correctAnswerSets) {
654
- // 如果長度不同,跳過這組
655
- if (correctSet.length !== userAnswers.length) continue;
656
-
657
- // 複製用戶答案和正確答案,以便進行排序和比較
658
- const sortedUserAnswers = [...userAnswers].sort();
659
- const sortedCorrectAnswers = [...correctSet].sort();
660
-
661
- // 比較排序後的答案
662
- const isMatch = sortedUserAnswers.every((answer, index) => answer === sortedCorrectAnswers[index]);
663
 
664
- // 如果找到匹配的答案組,返回true
665
- if (isMatch) return true;
666
  }
667
-
668
- // 如果沒有匹配的答案組,返回false
669
- return false;
670
  }
671
 
672
- // 階段按鈕點擊事件
673
- stage1Btn.addEventListener('click', function() {
674
- if (currentStage !== 1) {
675
- loadQuestion(currentQuestionIndex, 1);
676
- }
677
- });
678
-
679
- stage2Btn.addEventListener('click', function() {
680
- // 只有在第一階段答對後才能進入第二階段
681
- if (currentStage !== 2 && checkAnswer(stage1Answers[currentQuestionIndex], questions[currentQuestionIndex].stage1.answers)) {
682
- loadQuestion(currentQuestionIndex, 2);
683
- }
684
- });
685
-
686
  // 顯示結果
687
  function showResult() {
688
  quizContainer.style.display = 'none';
689
  resultContainer.style.display = 'block';
690
 
691
- // 計算得分(0-3星)
692
- const score = Math.min(3, Math.max(0, Math.floor(correctAnswers / 2)));
693
 
694
- // 更新結果標題和訊息
695
- if (score >= 3) {
696
- resultTitle.textContent = '試煉完成!';
697
- resultMessage.innerHTML = `恭喜你成功通過展開之塔的考驗!<br>你已經掌握了平方展開公式的應用,獲得了「展開融合」的力量。<br>這股力量將幫助你在未來的數學旅程中更加得心應手。`;
698
-
699
- // 顯示成功按鈕
700
- successButtons.style.display = 'flex';
 
 
 
 
 
 
 
 
701
  failButtons.style.display = 'none';
702
  } else {
703
- resultTitle.textContent = '試煉未完成';
704
- resultMessage.innerHTML = `你完成了 ${correctAnswers} 道題目,但還未能完全掌握平方展開公式。<br>不要氣餒,再試一次吧`;
705
-
706
- // 顯示失敗按鈕
707
  successButtons.style.display = 'none';
708
- failButtons.style.display = 'flex';
709
  }
710
 
711
- // 更新星星
712
- starResults.forEach((star, index) => {
713
- if (index < score) {
714
- star.classList.add('earned');
715
- } else {
716
- star.classList.remove('earned');
717
- }
718
- });
719
-
720
  // 更新遊戲進度
721
- gameProgress.completedTrials["展開之塔"].completed = score >= 3;
722
  gameProgress.completedTrials["展開之塔"].score = score;
723
 
724
- // 標記已完成的挑戰
725
- for (let i = 0; i < correctAnswers && i < 6; i++) {
726
  gameProgress.completedTrials["展開之塔"].challengesCompleted[i] = true;
727
  }
728
 
@@ -730,37 +730,39 @@ document.addEventListener('DOMContentLoaded', function() {
730
  gameProgress.lastSaved = new Date().toISOString();
731
  localStorage.setItem(`gameProgress_${currentPlayerId}`, JSON.stringify(gameProgress));
732
 
733
- // 檢查成就解鎖
734
  if (window.achievementSystem) {
735
  const gameState = {
736
  currentTrial: "展開之塔",
737
  totalStars: score,
738
- currentTrialScore: score,
739
- currentTrialCompleted: score >= 3,
740
- totalTrialsCompleted: Object.values(gameProgress.completedTrials).filter(trial => trial.completed).length
741
  };
742
 
743
  window.achievementSystem.checkAllAchievements(gameState);
744
  }
745
  }
746
 
747
- // 重新挑戰按鈕點擊事件
 
 
 
 
 
748
  retryBtn.addEventListener('click', function() {
749
- // 重置遊戲狀態
750
- currentQuestionIndex = 0;
751
- currentStage = 1;
752
  correctAnswers = 0;
753
- stage1Answers = Array(questions.length).fill(null).map(() => []);
754
- stage2Answers = Array(questions.length).fill(null).map(() => []);
755
 
756
- // 重置門的狀態
757
  Array.from(doorsProgress).forEach(door => {
758
- door.classList.remove('opened');
759
  });
760
 
761
- // 顯示問題容器,隱藏結果容器
762
- resultContainer.style.display = 'none';
763
- quizContainer.style.display = 'block';
764
 
765
  // 載入第一題
766
  loadQuestion(0, 1);
@@ -775,4 +777,25 @@ document.addEventListener('DOMContentLoaded', function() {
775
  nextTrialBtn.addEventListener('click', function() {
776
  window.location.href = 'kingdom_map.html';
777
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
778
  });
 
316
  const dropZoneSortable = new Sortable(dropZone, {
317
  group: {
318
  name: 'formula',
319
+ pull: 'clone', // 允許從答案區拖出,但會被移除
320
  put: true
321
  },
322
  animation: 100,
 
352
  evt.from.classList.remove('filled');
353
  evt.from.style.backgroundColor = 'rgba(100, 100, 100, 0.5)';
354
 
355
+ // 從答案格拖出的方塊直接移除,不回到拖拉區
356
+ if (evt.item && evt.item.parentNode) {
357
+ evt.item.remove();
358
+ }
359
+
360
  // 更新保存的答案
361
  updateSavedAnswers();
362
  }
 
387
  dragItem.id = `drag-item-${index}`;
388
  dragItem.textContent = item;
389
  dragItem.dataset.value = item;
390
+ dragItem.style.willChange = 'transform';
391
+ dragItem.style.touchAction = 'none';
392
 
393
  // 添加點擊事件,點擊可移除(如果在拖放區內)
394
  dragItem.addEventListener('click', function() {
 
413
  const dragItemsSortable = new Sortable(dragItemsContainer, {
414
  group: {
415
  name: 'formula',
416
+ pull: 'clone', // 設置為clone模式,拖拽項不會消失
417
+ put: false // 不允許放回拖拽區
418
  },
419
  animation: 100,
420
  delay: 0,
 
422
  ghostClass: "drag-ghost",
423
  forceFallback: true,
424
  fallbackTolerance: 3,
425
+ sort: false, // 禁止排序
426
  filter: '.disabled', // 禁止拖拽的元素
 
 
 
 
 
 
 
427
  onClone: function(evt) {
428
+ // 克隆元素時添加相同的樣式和數據
429
+ evt.clone.className = evt.item.className;
430
+ evt.clone.dataset.value = evt.item.dataset.value;
431
+ evt.clone.style.willChange = 'transform';
432
+ evt.clone.style.touchAction = 'none';
433
 
434
+ // 添加點擊事件,點擊可移除(如果在拖放區內)
435
+ evt.clone.addEventListener('click', function() {
436
  const parent = this.parentElement;
437
  if (parent && parent.classList.contains('drop-zone')) {
438
  parent.classList.remove('filled');
 
450
 
451
  sortableInstances.push(dragItemsSortable);
452
 
453
+ // 如果有已保存的答案,恢復它們
454
+ if (savedAnswers && savedAnswers.length > 0) {
455
  savedAnswers.forEach((value, index) => {
456
+ if (index < dropZones.length && value) {
457
  // 找到對應值的拖拽項
458
+ const matchingItem = Array.from(dragItemElements).find(item => item.dataset.value === value);
459
+ if (matchingItem) {
460
+ // 克隆拖拽項
461
+ const clone = matchingItem.cloneNode(true);
462
+ clone.dataset.value = value;
463
 
464
  // 添加點擊事件,點擊可移除
465
+ clone.addEventListener('click', function() {
466
  const parent = this.parentElement;
467
  if (parent && parent.classList.contains('drop-zone')) {
468
  parent.classList.remove('filled');
 
477
  });
478
 
479
  // 添加到拖放區
480
+ dropZones[index].appendChild(clone);
481
  dropZones[index].classList.add('filled');
482
  dropZones[index].style.backgroundColor = 'rgba(255, 140, 0, 0.3)';
483
  }
 
486
  }
487
 
488
  // 顯示檢查答案按鈕,隱藏下一題按鈕
489
+ checkAnswerBtn.style.display = 'inline-block';
490
  nextQuestionBtn.style.display = 'none';
491
 
492
+ // 清空反饋容器
493
+ feedbackContainer.innerHTML = '';
494
  feedbackContainer.style.display = 'none';
 
495
  }
496
 
497
  // 更新保存的答案
498
  function updateSavedAnswers() {
499
  const answers = [];
500
 
501
+ // 獲取所有拖放區的值
502
  dropZones.forEach(zone => {
503
+ const items = zone.querySelectorAll('.drag-item');
504
  if (items.length > 0) {
505
+ answers.push(items[0].dataset.value);
 
506
  } else {
507
  answers.push(null);
508
  }
509
  });
510
 
 
 
 
511
  // 保存答案
512
  if (currentStage === 1) {
513
+ stage1Answers[currentQuestionIndex] = answers;
514
  } else {
515
+ stage2Answers[currentQuestionIndex] = answers;
516
  }
517
  }
518
 
519
+ // 檢查答案
520
+ function checkAnswer() {
521
  // 獲取當前階段的問題數據
522
  const stageData = currentStage === 1 ? questions[currentQuestionIndex].stage1 : questions[currentQuestionIndex].stage2;
523
 
524
  // 獲取用戶答案
525
+ const userAnswerValues = [];
526
+ dropZones.forEach(zone => {
527
+ const items = zone.querySelectorAll('.drag-item');
528
+ if (items.length > 0) {
529
+ userAnswerValues.push(items[0].dataset.value);
530
+ } else {
531
+ userAnswerValues.push(null);
532
+ }
533
+ });
534
 
535
+ // 檢查是否有空白答案
536
+ if (userAnswerValues.includes(null)) {
537
+ feedbackContainer.innerHTML = '<p class="error">請填寫所有空格!</p>';
 
538
  feedbackContainer.style.display = 'block';
539
+ return false;
 
540
  }
541
 
542
  // 檢查答案是否正確
543
+ let isCorrect = false;
544
+
545
+ if (currentStage === 1) {
546
+ // 第一階段:檢查兩組答案是否匹配
547
+ const group1 = [userAnswerValues[0], userAnswerValues[1]];
548
+ const group2 = [userAnswerValues[2], userAnswerValues[3]];
549
+
550
+ // 檢查每個答案組合是否匹配任何一個正確答案組合
551
+ isCorrect = stageData.answers.some(answer => {
552
+ return (
553
+ (group1.includes(answer[0]) && group1.includes(answer[1])) &&
554
+ (group2.includes(answer[0]) && group2.includes(answer[1]))
555
+ );
556
+ });
557
+ } else {
558
+ // 第二階段:檢查三個值是否匹配
559
+ isCorrect = stageData.answers.some(answer => {
560
+ // 第一個值必須是2
561
+ if (userAnswerValues[0] !== answer[0]) return false;
562
+
563
+ // 其他兩個值順序不限
564
+ const otherValues = [userAnswerValues[1], userAnswerValues[2]];
565
+ return (
566
+ otherValues.includes(answer[1]) &&
567
+ otherValues.includes(answer[2])
568
+ );
569
+ });
570
+ }
571
+
572
+ // 顯示反饋
573
+ feedbackContainer.innerHTML = '';
574
+ feedbackContainer.style.display = 'block';
575
 
576
  if (isCorrect) {
577
+ // 播放正確音效
578
+ correctSound.currentTime = 0;
579
+ correctSound.play().catch(e => console.log('播放音效失敗:', e));
580
+
581
+ // 顯示正確反饋
582
+ const correctFeedback = document.createElement('p');
583
+ correctFeedback.className = 'success';
584
+ correctFeedback.textContent = '答對了!';
585
+ feedbackContainer.appendChild(correctFeedback);
586
+
587
+ // 更新UI
588
+ checkAnswerBtn.style.display = 'none';
589
 
 
590
  if (currentStage === 1) {
591
+ // 第一階段完成,進入第二階段
 
 
 
 
592
  nextQuestionBtn.textContent = '進入第二階段';
593
  nextQuestionBtn.onclick = function() {
594
  loadQuestion(currentQuestionIndex, 2);
595
  };
596
  } else {
597
+ // 第二階段完成進入下一完成挑戰
 
 
 
 
 
 
 
 
598
  if (currentQuestionIndex < questions.length - 1) {
 
 
599
  nextQuestionBtn.textContent = '下一題';
600
  nextQuestionBtn.onclick = function() {
601
  loadQuestion(currentQuestionIndex + 1, 1);
602
  };
603
  } else {
604
+ nextQuestionBtn.textContent = '完成挑戰';
605
+ nextQuestionBtn.onclick = function() {
606
+ showResult();
607
+ };
608
  }
609
  }
610
+
611
+ nextQuestionBtn.style.display = 'inline-block';
612
+
613
+ // 更新進度
614
+ if (currentStage === 2) {
615
+ doorsProgress[currentQuestionIndex].classList.add('completed');
616
+ correctAnswers++;
617
+ }
618
+
619
+ return true;
620
  } else {
621
+ // 播放錯誤音效
622
+ wrongSound.currentTime = 0;
623
+ wrongSound.play().catch(e => console.log('播放音效失敗:', e));
624
+
625
+ // 增加錯誤嘗試次數
626
  wrongAttempts++;
 
627
 
628
+ // 第一階段特殊處理
629
  if (currentStage === 1) {
630
+ // 創建提示容器(如果不存在)
631
+ let hintContainer = document.querySelector('.hint-container');
632
+ if (!hintContainer) {
633
+ hintContainer = document.createElement('div');
634
+ hintContainer.className = 'hint-container';
635
+ hintContainer.style.marginBottom = '15px';
636
+ hintContainer.style.padding = '10px';
637
+ hintContainer.style.backgroundColor = 'rgba(60, 60, 60, 0.7)';
638
+ hintContainer.style.borderRadius = '8px';
639
+ hintContainer.style.border = '1px solid rgba(255, 0, 0, 0.5)';
640
+ hintContainer.style.textAlign = 'center';
641
 
642
+ // 插入到公式模板前面
643
+ formulaTemplate.parentNode.insertBefore(hintContainer, formulaTemplate);
644
+ }
645
+
646
+ // 清空提示容器
647
+ hintContainer.innerHTML = '';
648
+
649
+ // 添加提示圖片
650
+ const hintImage = document.createElement('img');
651
+ hintImage.src = `towerhint${currentQuestionIndex + 1}1.jpg`;
652
+ hintImage.style.maxWidth = '50%';
653
+ hintImage.style.display = 'block';
654
+ hintImage.style.margin = '0 auto 10px';
655
+ hintContainer.appendChild(hintImage);
656
+
657
+ // 添加提示文字
658
+ const hintText = document.createElement('p');
659
+ hintText.style.color = 'white';
660
+ hintText.style.margin = '5px 0';
661
+
662
+ if (wrongAttempts === 1) {
663
+ // 第一次錯誤
664
+ hintText.textContent = '請仔細觀察上方提示圖,按照分配律的方式展開填入正確答案。';
665
  } else {
666
+ // 第二次或更多次錯
667
+ hintText.textContent = `正確答案應為:\n「${stageData.correctAnswer}」\n請依照此答案填入,才能進入第二階段。`;
 
 
 
 
 
668
  }
669
+
670
+ hintContainer.appendChild(hintText);
671
+
672
+ // 顯示錯誤反饋
673
+ const errorFeedback = document.createElement('p');
674
+ errorFeedback.className = 'error';
675
+ errorFeedback.textContent = '答錯了,請參考上方提示修正答案!';
676
+ feedbackContainer.appendChild(errorFeedback);
677
  } else {
678
+ // 第二階段錯
679
+ const errorFeedback = document.createElement('p');
680
+ errorFeedback.className = 'error';
681
+ errorFeedback.textContent = '答錯了,請再試一次!';
682
+ feedbackContainer.appendChild(errorFeedback);
683
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
684
 
685
+ return false;
 
686
  }
 
 
 
687
  }
688
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
689
  // 顯示結果
690
  function showResult() {
691
  quizContainer.style.display = 'none';
692
  resultContainer.style.display = 'block';
693
 
694
+ // 計算得分(滿分3星)
695
+ const score = Math.min(3, Math.max(1, Math.ceil(correctAnswers / questions.length * 3)));
696
 
697
+ // 更新星星顯示
698
+ for (let i = 0; i < starResults.length; i++) {
699
+ starResults[i].style.opacity = i < score ? '1' : '0.3';
700
+ }
701
+
702
+ // 更新結果文字
703
+ if (score === 3) {
704
+ resultTitle.textContent = '恭喜完成挑戰!';
705
+ resultMessage.textContent = '你已完美掌握平方展開的技巧!';
706
+ successButtons.style.display = 'block';
707
+ failButtons.style.display = 'none';
708
+ } else if (score === 2) {
709
+ resultTitle.textContent = '挑戰成功!';
710
+ resultMessage.textContent = '你已基本掌握平方展開的技巧,繼續加油!';
711
+ successButtons.style.display = 'block';
712
  failButtons.style.display = 'none';
713
  } else {
714
+ resultTitle.textContent = '再接再厲!';
715
+ resultMessage.textContent = '平方展開需要更多練習,不要氣餒!';
 
 
716
  successButtons.style.display = 'none';
717
+ failButtons.style.display = 'block';
718
  }
719
 
 
 
 
 
 
 
 
 
 
720
  // 更新遊戲進度
721
+ gameProgress.completedTrials["展開之塔"].completed = score >= 2;
722
  gameProgress.completedTrials["展開之塔"].score = score;
723
 
724
+ // 標記所有問題為已完成
725
+ for (let i = 0; i < questions.length; i++) {
726
  gameProgress.completedTrials["展開之塔"].challengesCompleted[i] = true;
727
  }
728
 
 
730
  gameProgress.lastSaved = new Date().toISOString();
731
  localStorage.setItem(`gameProgress_${currentPlayerId}`, JSON.stringify(gameProgress));
732
 
733
+ // 檢查成就
734
  if (window.achievementSystem) {
735
  const gameState = {
736
  currentTrial: "展開之塔",
737
  totalStars: score,
738
+ currentTrialCompleted: true,
739
+ currentTrialErrors: questions.length - correctAnswers,
740
+ currentTrialCombo: correctAnswers
741
  };
742
 
743
  window.achievementSystem.checkAllAchievements(gameState);
744
  }
745
  }
746
 
747
+ // 檢查答案按鈕點擊事件
748
+ checkAnswerBtn.addEventListener('click', function() {
749
+ checkAnswer();
750
+ });
751
+
752
+ // 重試按鈕點擊事件
753
  retryBtn.addEventListener('click', function() {
754
+ resultContainer.style.display = 'none';
755
+ quizContainer.style.display = 'block';
 
756
  correctAnswers = 0;
 
 
757
 
758
+ // 重置進度指示器
759
  Array.from(doorsProgress).forEach(door => {
760
+ door.classList.remove('completed');
761
  });
762
 
763
+ // 重置答案
764
+ stage1Answers = Array(questions.length).fill(null).map(() => []);
765
+ stage2Answers = Array(questions.length).fill(null).map(() => []);
766
 
767
  // 載入第一題
768
  loadQuestion(0, 1);
 
777
  nextTrialBtn.addEventListener('click', function() {
778
  window.location.href = 'kingdom_map.html';
779
  });
780
+
781
+ // 階段按鈕點擊事件(僅用於顯示,不可切換)
782
+ stage1Btn.addEventListener('click', function() {
783
+ if (currentStage !== 1) {
784
+ // 檢查是否已完成第一階段
785
+ if (stage1Answers[currentQuestionIndex].length > 0) {
786
+ loadQuestion(currentQuestionIndex, 1);
787
+ }
788
+ }
789
+ });
790
+
791
+ stage2Btn.addEventListener('click', function() {
792
+ if (currentStage !== 2) {
793
+ // 檢查是否已完成第一階段
794
+ if (stage1Answers[currentQuestionIndex].length > 0) {
795
+ loadQuestion(currentQuestionIndex, 2);
796
+ } else {
797
+ alert('請先完成第一階段!');
798
+ }
799
+ }
800
+ });
801
  });