You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C# WinForms trivia游戏中实现Fisher-Yates洗牌算法随机排序题目

实现步骤

1. 定义题目实体类

先创建专门存储题目信息的类,把题干、选项、正确答案序号、题目配图封装在一起,方便后续存入数组统一管理:

// 可以直接写在categoryquestion_form类的同级,或者单独存为.cs文件
public class Question
{
    // 题干内容
    public string Text { get; set; }
    // 四个选项
    public string[] Options { get; set; }
    // 正确答案的序号(对应btn1到btn4的1-4编号,和你原有逻辑保持一致)
    public int CorrectAnswerNo { get; set; }
    // 题目配图
    public Image Img { get; set; }
}

2. 新增窗体全局变量

在你原有quiz game variables变量区新增3个变量:

// 存储所有题目的数组
private Question[] _questionBank;
// 记录当前展示的题目在打乱后数组中的下标
private int _currentQuestionIndex = 0;
// 随机数实例,供洗牌算法调用
private Random _rnd = new Random();

3. 实现Fisher-Yates洗牌算法

在窗体类里添加通用洗牌方法,支持打乱任意类型的数组,该算法是公认的无偏置公平洗牌实现:

private void ShuffleArray<T>(T[] array)
{
    for (int i = array.Length - 1; i > 0; i--)
    {
        int j = _rnd.Next(i + 1);
        // 交换i和j位置的元素
        (array[i], array[j]) = (array[j], array[i]);
    }
}

4. 修改构造函数逻辑,初始化题库并洗牌

把原有构造函数替换为以下内容,先把所有题目存入数组,调用洗牌算法打乱后再加载第一题:

public categoryquestion_form()
{
    InitializeComponent();
    // 初始化所有题目到题库数组
    _questionBank = new Question[]
    {
        new Question()
        {
            Text = "Which famous inventor worked at a patent office?",
            Options = new string[]{"Nikola Tesla", "Thomas Edison", "Albert Einstein", "Albert Wesker"},
            CorrectAnswerNo = 3,
            Img = Properties.Resources.alberteinstein
        },
        new Question()
        {
            Text = "The Niepce Crater on the Moon was named in recognition of the famous inventor Joseph Niepce. What did Niepce invent?",
            Options = new string[]{"A telescope", "A camera", "A microscope", "A nanoscope"},
            CorrectAnswerNo = 2,
            Img = Properties.Resources.niepcecamera
        },
        new Question()
        {
            Text = "What do inventors, Tesla, Popov and Lodge have in common?",
            Options = new string[]{"They invented engines.", "They invented telephone technology.", "They invented electric motors.", "They invented radio technology."},
            CorrectAnswerNo = 4,
            Img = Properties.Resources.inventionofradio
        },
        new Question()
        {
            Text = "The invention of the refrigerator made a significant improvement to our standard of living. When it was invented, not many people wanted one. Who invented the refrigerator ?",
            Options = new string[]{"Oliver Evans", "Michael Faraday", "Carl Von Linde", "Benjamin Franklin"},
            CorrectAnswerNo = 1,
            Img = Properties.Resources.oliverevans
        },
        new Question()
        {
            Text = "Many inventors contributed to the technology that created the television. There were conflicts between inventors over their rights to various aspects of this technology. Who invented the television?",
            Options = new string[]{"John Baird", "Philo Farnsworth", "Vladimir Zworykin", "Carl Von Linde"},
            CorrectAnswerNo = 2,
            Img = Properties.Resources.farnsworth
        }
    };
    // 调用洗牌算法打乱题目顺序
    ShuffleArray(_questionBank);
    // 总题数直接取数组长度,后续加题无需手动修改
    totalQuestions2 = _questionBank.Length;
    // 加载第一题
    askquestionInventors(_currentQuestionIndex);
}

5. 重写askquestionInventors方法,删除原有switch逻辑

原有硬编码题目的switch逻辑可以完全删除,现在直接从打乱的数组里取对应下标的题目赋值即可:

private void askquestionInventors(int qIndex)
{
    // 取出当前要展示的题目
    Question currentQ = _questionBank[qIndex];
    // 赋值配图、题干
    pictureBox_2.Image = currentQ.Img;
    question_label2.Text = currentQ.Text;
    // 赋值四个选项
    btn1.Text = currentQ.Options[0];
    btn2.Text = currentQ.Options[1];
    btn3.Text = currentQ.Options[2];
    btn4.Text = currentQ.Options[3];
    // 赋值正确答案
    correctAnswer2 = currentQ.CorrectAnswerNo;
}

6. 微调答题事件的题号逻辑

把checkAnswerEvent2方法里原来操作questionNumber2的逻辑,替换为操作_currentQuestionIndex即可:

private void checkAnswerEvent2(object sender, EventArgs e)
{
    var senderObject2 = (Button)sender;
    int buttonTag2 = Convert.ToInt32(senderObject2.Tag);
    if (buttonTag2 == correctAnswer2)
    {
        score2++;
    }
    _currentQuestionIndex++;
    // 所有题目答完
    if (_currentQuestionIndex == totalQuestions2)
    {
        percentage2 = (int)Math.Round((double)(score2 * 100) / totalQuestions2);
        MessageBox.Show(
            "Quiz Ended!" + Environment.NewLine +
            "You have answered " + score2 + " questions correctly." + Environment.NewLine +
            "Your total percentage is " + percentage2 + "%" + Environment.NewLine + "Click OK to return menu" + Environment.NewLine
            );
        score2 = 0;
        this.Close();
        mainmenu_form f1 = new mainmenu_form();
        f1.ShowDialog();
        return;
    }
    // 加载下一题
    askquestionInventors(_currentQuestionIndex);
}

补充说明

  • 后续新增题目只需要在_questionBank数组初始化的位置按照原有格式新增Question实例即可,无需修改其他逻辑
  • 每次打开答题窗体,题目顺序都会随机打乱

内容的提问来源于stack exchange,提问作者Joshua

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 00:45:04