ZhangZhouSpecialEquipment/Assets/Scripts/扶梯/QuizSystem.cs

441 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
using static System.Collections.Specialized.BitVector32;
public class QuizSystem : MonoBehaviour
{
public static QuizSystem Instance;
public string FileName;
// UI元素
public TextMeshProUGUI questionText; // 显示问题文本
public ToggleGroup optionsGroup; // 选项组,用于单选题
public List<Toggle> optionToggles; // 选项切换按钮列表
public TextMeshProUGUI progressText; // 显示答题进度
public Button submitButton; // 提交按钮
//上一题下一题页面
public GameObject CtrlPage;
public Button nextButton; // 下一题按钮
//public Button previousButton; // 上一题按钮
public TextMeshProUGUI hintText; // 显示提示文本
//结果页面
public GameObject ResultPage;//结果页面
public TextMeshProUGUI resultText; // 显示结果文本
public Button MoreOnceBtn;//再来一次
//public Button hintButton; // 提示按钮
//public Slider timeSlider; // 时间滑动条
//public TextMeshProUGUI timerText; // 倒计时文本
// 问题列表和当前状态
private List<Question> questions = new List<Question>(); // 问题列表
private int currentQuestionIndex = 0; // 当前问题索引
private List<HashSet<int>> userAnswers = new List<HashSet<int>>(); // 用户答案列表
//private bool isSubmitted = false; // 是否已提交
// 总体倒计时
//private float totalTime = 1800f; // 总时间(秒)
//private float remainingTime; // 剩余时间
private void Awake()
{
Instance = this;
}
void Start()
{
// 加载问题
LoadQuestions();
ToStartQuestion();
// 初始化倒计时
//remainingTime = totalTime;
//UpdateTimerUI();
}
public void ToStartQuestion()
{
//结果和控制页面消失
ResultPage.SetActive(false);
CtrlPage.SetActive(false);
userAnswers.Clear();
// 初始化用户答案列表
for (int i = 0; i < questions.Count; i++)
{
userAnswers.Add(new HashSet<int>());
}
currentQuestionIndex = 0;
// 显示第一个问题
DisplayQuestion();
}
void Update()
{
//// 更新倒计时
//if (remainingTime > 0)
//{
// remainingTime -= Time.deltaTime;
// UpdateTimerUI();
//}
//else if (!isSubmitted)
//{
// // 时间到,自动提交
// OnSubmitButtonClicked();
//}
}
void LoadQuestions()
{
questions = XmlTextReaderTest();
}
void DisplayQuestion()
{
// 检查是否超出问题列表
if (currentQuestionIndex >= questions.Count)
{
return;
}
// 获取当前问题
Question question = questions[currentQuestionIndex];
questionText.text = question.Text;
progressText.text = $"答题进度: {GetAnsweredCount()+1} / {questions.Count}";
// 显示选项
for (int i = 0; i < optionToggles.Count; i++)
{
if (i < question.Options.Length && (!question.IsJudgment || i < 2))
{
optionToggles[i].gameObject.SetActive(true);
var label = optionToggles[i].GetComponentInChildren<Text>();
if (label != null)
{
string sign = "A:";
switch (i)
{
case 0: sign = "A:"; break;
case 1: sign = "B:"; break;
case 2: sign = "C:"; break;
case 3: sign = "D:"; break;
}
label.text = sign+question.Options[i];
}
optionToggles[i].isOn = userAnswers[currentQuestionIndex].Contains(i + 1);
// 判断题或单选题使用 ToggleGroup
optionToggles[i].group = (question.IsSingleChoice || question.IsJudgment) ? optionsGroup : null;
}
else
{
optionToggles[i].gameObject.SetActive(false);
}
}
}
//选择结束后确认该题结果
public void OnSubmitButtonClicked()
{
// 提交答案
SaveUserAnswers();
//检查结果并显示
CheckCurrentAnswer();
}
//保存用户答案
void SaveUserAnswers()
{
// 保存用户选择的答案
userAnswers[currentQuestionIndex].Clear();
int index = 0;
foreach (Toggle toggle in optionToggles)
{
if (toggle.isOn)
{
userAnswers[currentQuestionIndex].Add(index);
}
index++;
}
}
//检查是否正确
void CheckCurrentAnswer()
{
// 检查用户答案是否为正确答案的子集
if (questions[currentQuestionIndex].CorrectAnswers.IsSubsetOf(userAnswers[currentQuestionIndex]))
{
OnHintViewShow("正确");
}
else
{
OnHintViewShow("错误");
}
}
//显示正确还是错误
public void OnHintViewShow(string result)
{
// 显示正确答案提示
Question question = questions[currentQuestionIndex];
string correctAnswerLetters = ConvertNumbersToLetters(question.CorrectAnswers);
hintText.text = $"回答{result},答案为: {correctAnswerLetters}";
CtrlPage.SetActive(true);
}
//下一题
public void OnNextButtonClicked()
{
// 切换到下一题
if (currentQuestionIndex < questions.Count - 1)
{
//SaveUserAnswers();
currentQuestionIndex++;
DisplayQuestion();
//hintText.gameObject.SetActive(false);
}
//计算结果并进入结果页面
else
{
CheckAllAnswers();
}
//控制页面消失
CtrlPage.SetActive(false);
}
//检查所有答案结果并显示结果页面
void CheckAllAnswers()
{
// 检查所有答案并计算正确率
int correctCount = 0;
for (int i = 0; i < questions.Count; i++)
{
// 检查用户答案是否为正确答案的子集
if (questions[i].CorrectAnswers.IsSubsetOf(userAnswers[i]))
{
correctCount++;
}
}
resultText.text = $"正确率: {(float)correctCount / questions.Count * 100:F2}%";
ResultPage.SetActive(true);
}
//再来一遍
public void OnMoreDoOnce()
{
ToStartQuestion();
}
//上一题
public void OnPreviousButtonClicked()
{
// 切换到上一题
if (currentQuestionIndex > 0)
{
SaveUserAnswers();
currentQuestionIndex--;
DisplayQuestion();
//isSubmitted = false; // 重置提交状态
hintText.gameObject.SetActive(false);
}
}
void UpdateTimerUI()
{
//// 更新滑动条和倒计时文本
//if (!isSubmitted) // 仅在未提交时更新
//{
// timeSlider.value = remainingTime / totalTime;
// timerText.text = $"剩余时间: {Mathf.Ceil(remainingTime)}秒";
//}
}
//void LockSliderPosition()
//{
// // 禁用滑块交互
// timeSlider.interactable = false;
//}
//void StopTimer()
//{
// // 停止倒计时并更新文本
// timerText.text = $"本次用时:{totalTime - remainingTime:F0}s";
// timeSlider.value = 0; // 停止滑动条
//}
int GetAnsweredCount()
{
// 获取已回答的问题数量
int count = 0;
foreach (var answer in userAnswers)
{
if (answer.Count > 0)
{
count++;
}
}
return count;
}
string ConvertNumbersToLetters(HashSet<int> numbers)
{
// 将数字转换为字母
StringBuilder letters = new StringBuilder();
foreach (int number in numbers)
{
if (number >= 0 && number <= 3)
{
char letter = (char)('A' + number);
letters.Append(letter);
}
}
return letters.ToString();
}
private List<Question> XmlTextReaderTest()
{
List<Question> questions = new List<Question>();
// 构建文件路径
string filePath = Path.Combine(Application.streamingAssetsPath, FileName+".xml");
if (!File.Exists(filePath))
{
Debug.LogError("Questions file not found at: " + filePath);
return questions;
}
string textmsg = File.ReadAllText(filePath);
XmlDocument xmlDocument = new XmlDocument();
try
{
xmlDocument.LoadXml(textmsg);
}
catch (XmlException e) {
Debug.LogError($"XML格式错误{e.Message}");
return questions;
}
XmlNode rootNode = xmlDocument.SelectSingleNode("root");
if (rootNode == null)
{
Debug.LogError("XML中未找到<root>节点");
return questions;
}
//遍历所有<question>子节点
XmlNodeList questionNodes = rootNode.SelectNodes("question");
if (questionNodes == null || questionNodes.Count == 0)
{
Debug.LogWarning("未找到任何<question>节点");
return questions;
}
// 提取每个question的属性值
foreach (XmlNode node in questionNodes)
{
Question question = new Question();
// 读取id属性转换为int
if (!TryGetIntAttribute(node, "id", out int id))
{
Debug.LogWarning("跳过无效的question节点缺少id或格式错误");
continue;
}
// 读取quesTitle属性字符串
if (!TryGetStringAttribute(node, "quesTitle", out string title))
{
Debug.LogWarning($"id为{id}的节点缺少quesTitle属性");
continue;
}
string[] allMsg = title.Split('|');
question.Text = allMsg[0];
if (allMsg.Length > 1) {
question.Options=new string[allMsg.Length-1];
for (int i = 1;i<allMsg.Length;i++)
{
question.Options[i-1]=allMsg[i];
}
}
else
{
question.Options=null;
}
// 读取answer属性转换为string
if (!TryGetStringAttribute(node, "answer", out string answer))
{
Debug.LogWarning($"id为{id}的节点answer格式错误");
continue;
}
question.CorrectAnswers = new HashSet<int>(Array.ConvertAll(answer.ToCharArray(), c => int.Parse(c.ToString())));
// 读取type属性转换为int
if (!TryGetIntAttribute(node, "type", out int type))
{
Debug.LogWarning($"id为{id}的节点type格式错误");
continue;
}
question.IsSingleChoice = type == 1;
question.IsJudgment = type == 0;// 判断题标识
// 添加到列表
questions.Add(question);
}
return questions;
}
// 辅助方法:获取节点的字符串属性
private bool TryGetStringAttribute(XmlNode node, string attrName, out string value)
{
XmlAttribute attr = node.Attributes[attrName];
if (attr != null)
{
value = attr.Value;
return true;
}
value = null;
return false;
}
// 辅助方法获取节点的int属性并验证格式
private bool TryGetIntAttribute(XmlNode node, string attrName, out int value)
{
if (TryGetStringAttribute(node, attrName, out string strValue))
{
return int.TryParse(strValue, out value);
}
value = 0;
return false;
}
}
public class Question
{
public string Text; // 问题文本
public string[] Options; // 选项数组
public bool IsSingleChoice; // 是否为单选题
public HashSet<int> CorrectAnswers; // 正确答案集合
public bool IsJudgment; // 是否为判断题
}