当前位置:编程学习 > C#/ASP.NET >>

请教两个问题

要实现个在线考试系统;C#语言;
问题一:
数据库中有1000道题,随机抽取100道。然后每个学生抽取随机20道,5个学生抽到的都是100道里不同的题目。
请问这个算法如何实现?
问题二,
有关考试的操作题。比如如何判断答题者对WORD文档的操作(比如更改字体大小,颜色,替换等。。。)。 --------------------编程问答-------------------- 你就随机在1000题里面抽取100个
然后分配给每个学生20个,不就可以了

第二个,不知道你是要作题过程中判断,还是交卷了以后要在文档里判断 --------------------编程问答-------------------- 先抽100道题放入集合中,然后每个学生抽题目,抽到题目就在集合去除这一个道题就行了。 --------------------编程问答-------------------- 问题一麻烦提供下代码了。
问题2是在自动批改试卷时候做判断 --------------------编程问答--------------------
            //存放题目的总集合
            List<Subject> lstSubjects = new List<Subject>();

            //存放100个题目的集合
            Hashtable htUsedSubjects = new Hashtable();

            int nCount = 100; //抽取总数
            while (nCount > 0)
            {
                Random rnd = new Random();
                int nCurrNum = rnd.Next(0, 999);
                Subject subject = lstSubjects[nCurrNum];
                if (htUsedSubjects.Contains(subject.Num))
                    continue;

                htUsedSubjects.Add(nCurrNum, subject);
                nCount--;
            }


        /// <summary>
        /// 题目类
        /// </summary>
        private class Subject
        {
            private int m_num = 0;
            private string m_content = string.Empty;
            /// <summary>
            /// 题目编号
            /// </summary>
            public int Num
            {
                get { return this.m_num; }
                set { this.m_num = value; }
            }
            /// <summary>
            /// 题目内容
            /// </summary>
            public int Content
            {
                get { return this.m_content; }
                set { this.m_content = value; }
            }
        }

略微搞了下,供参考 --------------------编程问答-------------------- 有一句有问题,改下:

htUsedSubjects.Add(subject.Num, subject);  --------------------编程问答-------------------- 问题一其实就是随机抽取不重复数的问题。 --------------------编程问答-------------------- if (htUsedSubjects.Contains(subject.Num)) 
                    continue; 

                htUsedSubjects.Add(nCurrNum, subject); 

---------------------
这种写法效率很低的,特别是当总数M和N相差不大的时候,比如在1000道题里抽取800道题。 --------------------编程问答-------------------- 在编程中经常遇到一些类似的问题,比如做一个双色球选号软件,其中6个双色球是从1到33之间选出6个数来,这6个数是不能重复的,这个问题就是我们今天要说的生成不重复数算法。
算法描述如下:从M个数中选出N个数来(0<N<=M),要求N个数之间不能有重复。
这个问题我以前用J2SE实现过,使用了ArrayList,每次随机在指定范围内选定一个数,然后查看结果集合中是否存在该数,如果存在继续下一轮循环,如果不存在,就将该数保存到结果集合中去。使用这种算法虽然也能实现要求,缺点是判断结果集合中是否存在该数时,需要通过一个循环来判断,这会增加算法运行的时间,虽然时间复杂度为n,但多次重复,还是一笔不小的开销。

下面要介绍的算法是,每次随机取出一个数,之后将该数放置到集合的末尾去,这样下次取随机数的时候,只从1到目标集合个数-1个中随机抽取,如此循环,这样就避免了判断在结果集合中判断是否存在相冲突的数的过程。

算法代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Management;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] range = new int[33];
            for (int i = 0; i < 33; i++)//初始化范围集合,从1到33
            {
                range[i] = i + 1;
            }
            int[] result = CreateNumbers(range, 6);
            for(int i=0;i<result.Length;i++)
            {
                Console.WriteLine("result[{0}]={1}", i, result[i]);
            }
            Console.ReadKey();
        }
  
        //取出不重复的6个数
    static int[] CreateNumbers(int[] range, int count)
        {
            int[] result = new int[count];
            Random random=new Random();
            int index = 0;
            int temp = 0;
            for (int i = 0; i < count; i++)
            {
                index=random.Next() % (range.Length-i);
                result[i] = range[index];
                //将当前已使用过的数移至集合末尾,并且将末尾原来没有使用的数放到当前位置
                temp = range[range.Length - 1-i];
                range[range.Length - 1-i] = range[index];
                range[index]=temp;
            }
            return result;
        }
       
    }
}

结果如下:
--------------------编程问答--------------------
引用 7 楼 zhoufoxcn 的回复:
if (htUsedSubjects.Contains(subject.Num)) 
                    continue; 

                htUsedSubjects.Add(nCurrNum, subject); 

--------------------- 
这种写法效率很低的,特别是当总数M和N相差不大的时候,比如在1000道题里抽取800道题。


HashTable哈希表的效率是很高的,这个仁兄不用担心 --------------------编程问答-------------------- 恩。问题1很容易。楼上的已经给出了解答!!
问题2有点麻烦了。关键是什么样的实现形式了。如果是画上去的,可能比较麻烦。你的取到这个画上去的的东西。比如是a的话。你要判断是不是a。这个是识别方面的知识了。
如果是题目后边有一个textbox。就简单了。你就简单的判断下他的内容就可以了
比如。if(textbox.text=="a")
{
messagebox.show("a错");
}
个人觉得还是还后边加个textbox或是combox。或是就跟我们考试一样的。弄个答提卡之类的东西(类似问卷调查)。这样判断起来就很容易了!! --------------------编程问答-------------------- 呵呵,可以这样,随机从数据里面抽取就行,在select时 newid()这个东东,可以给这些数据编号,然后你可以再处理了... --------------------编程问答--------------------
引用 8 楼 zhoufoxcn 的回复:
static int[] CreateNumbers(int[] range, int count)
        {
            int[] result = new int[count];
            Random random=new Random();
            int index = 0;
            int temp = 0;
            for (int i = 0; i < count; i++)
            {
                index=random.Next() % (range.Length-i);
                result[i] = range[index];
                //将当前已使用过的数移至集合末尾,并且将末尾原来没有使用的数放到当前位置
                temp = range[range.Length - 1-i];
                range[range.Length - 1-i] = range[index];
                range[index]=temp;
            }
            return result;
        }


前不久刚学习了这种方法~推荐 --------------------编程问答-------------------- 选题。
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,