296 lines
8.2 KiB
C#
296 lines
8.2 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using Kill.Managers;
|
||
using Kill.UI.Pages;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
public class SafetylearningTestPage : MonoBehaviour
|
||
{
|
||
public Transform questionContainer;
|
||
public GameObject questionPrefab;
|
||
public Button nextButton;
|
||
public Button submitButton;
|
||
public GameObject answerPrefab;
|
||
public List<GameObject> sonObjs;
|
||
|
||
// 题库(所有未答对2次的题目)
|
||
private List<QuestionInfo> questionBank = new List<QuestionInfo>();
|
||
// 答题队列(当前答题顺序)
|
||
public List<QuestionInfo> questionQueue = new List<QuestionInfo>();
|
||
// 答题记录(记录每道题答对次数)
|
||
private Dictionary<int, int> correctCountMap = new Dictionary<int, int>();
|
||
|
||
private int currentQuestionIndex = 0;
|
||
private int totalAnsweredCount = 0;
|
||
private SafetylearningQuestion currentQuestion;
|
||
private GameObject currentAnswerObj;
|
||
|
||
public void Init(List<QuestionInfo> questions)
|
||
{
|
||
// 初始化题库
|
||
questionBank = new List<QuestionInfo>(questions);
|
||
correctCountMap.Clear();
|
||
totalAnsweredCount = 0;
|
||
|
||
// 初始化答题队列(按顺序)
|
||
InitializeQueue();
|
||
|
||
// 显示第一题
|
||
ShowQuestion(0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化答题队列(按顺序)
|
||
/// </summary>
|
||
private void InitializeQueue()
|
||
{
|
||
questionQueue.Clear();
|
||
// 按顺序将题库中所有题目加入队列
|
||
foreach (var question in questionBank)
|
||
{
|
||
questionQueue.Add(question);
|
||
}
|
||
currentQuestionIndex = 0;
|
||
Debug.Log($"初始化答题队列,共 {questionQueue.Count} 道题");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重新生成队列(答错时调用)
|
||
/// 清空队列,将题库中所有题目打乱顺序生成新队列
|
||
/// </summary>
|
||
private void RegenerateQueue()
|
||
{
|
||
questionQueue.Clear();
|
||
|
||
// 将题库中所有题目加入队列
|
||
foreach (var question in questionBank)
|
||
{
|
||
questionQueue.Add(question);
|
||
}
|
||
|
||
// 打乱队列
|
||
ShuffleList(questionQueue);
|
||
|
||
currentQuestionIndex = 0;
|
||
Debug.Log($"重新生成答题队列,共 {questionQueue.Count} 道题");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从题库中移除题目(答对2次时调用)
|
||
/// </summary>
|
||
private void RemoveFromBank(int questionId)
|
||
{
|
||
var question = questionBank.Find(q => q.id == questionId);
|
||
if (question != null)
|
||
{
|
||
questionBank.Remove(question);
|
||
Debug.Log($"题目 {questionId} 已从题库中移除");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Fisher-Yates 洗牌算法
|
||
/// </summary>
|
||
private void ShuffleList<T>(List<T> list)
|
||
{
|
||
System.Random rng = new System.Random();
|
||
int n = list.Count;
|
||
while (n > 1)
|
||
{
|
||
n--;
|
||
int k = rng.Next(n + 1);
|
||
T value = list[k];
|
||
list[k] = list[n];
|
||
list[n] = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示指定题目
|
||
/// </summary>
|
||
private void ShowQuestion(int index)
|
||
{
|
||
// 检查队列是否为空,为空则通过
|
||
if (questionQueue.Count == 0)
|
||
{
|
||
Debug.Log("答题队列已空,通过!");
|
||
// 显示完成页面
|
||
SafetylearningPageCtrl.Instance?.ShowFinishPage();
|
||
return;
|
||
}
|
||
|
||
// 清除旧题目和解析
|
||
ClearCurrentQuestion();
|
||
|
||
currentQuestionIndex = index;
|
||
|
||
// 如果超出范围,从第一题开始
|
||
if (currentQuestionIndex >= questionQueue.Count)
|
||
{
|
||
currentQuestionIndex = 0;
|
||
}
|
||
|
||
// 创建新题目
|
||
GameObject questionObj = Instantiate(questionPrefab, questionContainer);
|
||
sonObjs.Add(questionObj);
|
||
currentQuestion = questionObj.GetComponent<SafetylearningQuestion>();
|
||
|
||
// 使用总答题序号作为题号(累加)
|
||
totalAnsweredCount++;
|
||
currentQuestion.Init(totalAnsweredCount, questionQueue[currentQuestionIndex]);
|
||
|
||
// 订阅选项选择事件
|
||
currentQuestion.OnOptionSelected += OnOptionSelected;
|
||
|
||
// 初始状态:隐藏提交和下一题按钮
|
||
submitButton.gameObject.SetActive(false);
|
||
nextButton.gameObject.SetActive(false);
|
||
|
||
// 绑定按钮事件
|
||
submitButton.onClick.RemoveAllListeners();
|
||
submitButton.onClick.AddListener(OnSubmitClick);
|
||
|
||
nextButton.onClick.RemoveAllListeners();
|
||
nextButton.onClick.AddListener(OnNextClick);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 选项被选择
|
||
/// </summary>
|
||
private void OnOptionSelected()
|
||
{
|
||
// 有选择时显示提交按钮
|
||
if (currentQuestion != null && currentQuestion.HasSelectedAnswer())
|
||
{
|
||
submitButton.gameObject.SetActive(true);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 提交答案
|
||
/// </summary>
|
||
private void OnSubmitClick()
|
||
{
|
||
if (currentQuestion == null) return;
|
||
|
||
// 禁用选项交互
|
||
currentQuestion.DisableAllOptions();
|
||
submitButton.gameObject.SetActive(false);
|
||
|
||
// 显示答案判断
|
||
currentQuestion.CheckAnswer();
|
||
|
||
// 判断是否正确
|
||
string userAnswer = currentQuestion.GetUserAnswer();
|
||
string correctAnswer = questionQueue[currentQuestionIndex].correctAnswer;
|
||
bool isCorrect = userAnswer == correctAnswer;
|
||
|
||
// 获取当前题目ID
|
||
int currentQuestionId = questionQueue[currentQuestionIndex].id;
|
||
|
||
if (isCorrect)
|
||
{
|
||
// 更新答对次数
|
||
if (!correctCountMap.ContainsKey(currentQuestionId))
|
||
{
|
||
correctCountMap[currentQuestionId] = 0;
|
||
}
|
||
correctCountMap[currentQuestionId]++;
|
||
|
||
// 检查是否答对2次
|
||
if (correctCountMap[currentQuestionId] >= 2)
|
||
{
|
||
// 从题库中移除
|
||
RemoveFromBank(currentQuestionId);
|
||
}
|
||
|
||
// 从队列中移除当前题目
|
||
questionQueue.RemoveAt(currentQuestionIndex);
|
||
// 索引保持不变,因为移除后后面的题目会前移
|
||
|
||
// 2秒后自动下一题
|
||
StartCoroutine(DelayNextQuestion());
|
||
}
|
||
else
|
||
{
|
||
CreateAnswerExplanation();
|
||
// 答错:清空队列,重新生成
|
||
RegenerateQueue();
|
||
|
||
// 显示解析和下一题按钮
|
||
|
||
nextButton.gameObject.SetActive(true);
|
||
|
||
// 重置索引,确保点击下一题从第一题开始
|
||
currentQuestionIndex = -1;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 延迟下一题
|
||
/// </summary>
|
||
private IEnumerator DelayNextQuestion()
|
||
{
|
||
yield return new WaitForSeconds(1f);
|
||
ShowQuestion(currentQuestionIndex);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建答案解析
|
||
/// </summary>
|
||
private void CreateAnswerExplanation()
|
||
{
|
||
if (answerPrefab == null) return;
|
||
|
||
currentAnswerObj = Instantiate(answerPrefab, questionContainer);
|
||
sonObjs.Add(currentAnswerObj);
|
||
currentAnswerObj.GetComponent<SafetylearningAnswer>().Init(questionQueue[currentQuestionIndex]);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 下一题
|
||
/// </summary>
|
||
private void OnNextClick()
|
||
{
|
||
currentQuestionIndex++;
|
||
ShowQuestion(currentQuestionIndex);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除当前题目和解析
|
||
/// </summary>
|
||
private void ClearCurrentQuestion()
|
||
{
|
||
// 取消订阅事件
|
||
if (currentQuestion != null)
|
||
{
|
||
currentQuestion.OnOptionSelected -= OnOptionSelected;
|
||
}
|
||
|
||
// 销毁所有子对象
|
||
foreach (var obj in sonObjs)
|
||
{
|
||
if (obj != null)
|
||
Destroy(obj);
|
||
}
|
||
sonObjs.Clear();
|
||
|
||
currentQuestion = null;
|
||
currentAnswerObj = null;
|
||
}
|
||
|
||
void OnDestroy()
|
||
{
|
||
submitButton?.onClick.RemoveAllListeners();
|
||
nextButton?.onClick.RemoveAllListeners();
|
||
|
||
if (currentQuestion != null)
|
||
{
|
||
currentQuestion.OnOptionSelected -= OnOptionSelected;
|
||
}
|
||
}
|
||
}
|