天天看點

一個C#版的多選題選項及判分設計方案

問題背景

設計一套試卷,裡面有單選,多選,判斷題(實際上判斷題就是兩個選項的單選題而已)

其他都很好處理,

裡面的關鍵點,顯然是多選題的錯選、漏選、以及選對該如何處理

這裡提供了一種方案,個人感覺比較合理。

思路和方案

  1. 選項用2^n的整數值表示
  2. 判斷對錯用位元算
  3. 多選題如果沒選全,則看選對了的數目占正确答案的選項數目的比例
  4. 可設定題目分數是否一定為整數還是可以是0.5的倍數

方案

using System;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Web.Test.BinaryTest
{
    [Flags]
    public enum Options
    {
        O = 0,
        A = 1,
        B = 1 << 1,
        C = 1 << 2,
        D = 1 << 3
    }

    [TestClass]
    public class UnitTest1
    {
        [DataRow(Options.O)]   //空

        [DataRow(Options.A)] //無錯,未選全
        [DataRow(Options.B)] //無錯,未選全
        [DataRow(Options.C)] //無錯,未選全

        [DataRow(Options.A | Options.B)]//無錯,未選全
        [DataRow(Options.A | Options.C)]//無錯,未選全
        [DataRow(Options.B | Options.C)]//無錯,未選全

        [DataRow(Options.A | Options.B | Options.C)]//對

        [DataRow(Options.A | Options.B | Options.D)]//有對有錯,算錯
        [DataRow(Options.C | Options.B | Options.D)]//有對有錯,算錯
        [DataRow(Options.C | Options.A | Options.D)]//有對有錯,算錯

        [DataRow(Options.A | Options.B | Options.C | Options.D)]//有對有錯,算錯
        [TestMethod]
        public void TestMethod1(Options option, bool isIntegerPoint = false)
        {
            //isIntegerPoint 為true時,每道題隻有整數得分值;否則,可以為0.5的倍數的得分值
            int totalScore = 4;

            int totalAnswer = (int)(Options.A | Options.B | Options.C | Options.D); //ABCD
            int rightAnswer = (int)(Options.A | Options.B | Options.C);  //ABC
            int wrongAnswer = totalAnswer - rightAnswer;


            double score;

            var intOption = (int)option;

            //選對時
            if (rightAnswer == intOption)
            {
                score = totalScore;
                Debug.WriteLine($"score = {score}");
            }
            //選錯時
            else if ((wrongAnswer & intOption) > 0)
            {
                score = 0;
                Debug.WriteLine($"score = {score}");
            }
            //未錯,但未選全時
            else
            {
                var rightOptionsCount = Convert.ToString(rightAnswer, 2).Replace("0", "").Length;  //總選項數
                var userOptionsCount = Convert.ToString(intOption, 2).Replace("0", "").Length; // 使用者選項數

                //整數分值
                if (isIntegerPoint)
                {
                    var point = totalScore * userOptionsCount / rightOptionsCount;
                    score = point;
                }
                //0.5的倍數的分值
                else
                {
                    var point = (double)(totalScore * userOptionsCount) / rightOptionsCount;
                    score = Math.Round((2 * point), MidpointRounding.AwayFromZero);
                }
                Debug.WriteLine($"score = {score / 2}");
            }
        }
    }
}