none
请教关于随机抽题问题! RRS feed

  • 问题

  • 1.我做了一个考试系统,现在在随机抽题的问题上卡住了。有网友给我提供思路:“你应该先得到试题表中..有多少套试题(多少条记录)...然后使用Random来随机生成0到这范围内的数字...然后根据这数字..Select出你的试题出来..”

    但是具体代码我写不出来,求个示例代码参考一下。谢谢。

    2.我还有个问题,随机抽取一个表的20题,然后再随机抽取另一个表的20题,然后把这40题放在一个datagridview里的示例代码。谢谢。


    C#初学者!~~~

    2012年12月2日 6:45

答案

  • 那么以后希望你用啥数据库写清楚。

    随机抽取题目,我建议你可以先随机生成一堆随机序列号(假设1~100个题目),你可以这样生成随机号:

    class Program
        {
            static void Main(string[] args)
            {
                List<int> numbers = new List<int>();
                Random r =new Random(Guid.NewGuid().GetHashCode());
     
                for (int i = 1; i < 101; i++)
                {
                    numbers.Insert(r.Next(0, numbers.Count), i);    //随机插入数字编号
                }
     
                //生成SQL语句
                string s = "Select * from xxx where Id in("+string.Join(",",numbers.Take(20))+")";
     
                //检测SQL语句
                Console.WriteLine(s);
            }
        }

    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    • 已标记为答案 呆oO 2012年12月3日 2:35
    2012年12月2日 8:22
    版主

全部回复

  • 其实你完全不必这样麻烦,你完全可以这样:

    Select Top 20 * From xxx ordery by newid()

    这样一来肯定排序就随机了。

    第二问:

    假设你的两个表结构完全一样,你的SQL:

    Select Top 20 * From xxx ordery by newid()

    Union

    Select Top 20 * From yyy ordery by newid()

    调用SqlDataAdapter的Fill方法,填充到DataTable,绑定到GridView即可。


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    2012年12月2日 7:52
    版主
  • 但是我的出现问题:“表达式中 'newid' 函数未定义。”

    以下是代码:
                        string sql = string.Format("SELECT TOP 10 * FROM tmb order by newid()");    
                        DataSet ds = new ConnDb().ds(sql);

            public DataSet ds(string sql)
            {
                DataSet ds = new DataSet();
                OleDbDataAdapter da = new OleDbDataAdapter();
                //com.CommandText = sql;
                //com.CommandType = CommandType.Text;
                OleDbCommand cmd = new OleDbCommand(sql, conn);
                da.SelectCommand = cmd;
                da.Fill(ds);
                connClose();
                return ds;
            }


    C#初学者!~~~

    2012年12月2日 7:59
  • 还想请教一下,如果您说的方法可以实现,我还想了解一下我之前提的两个问题,您能帮我写两段示例吗?谢谢

    还有如何随机抽取不重复,谢谢。


    C#初学者!~~~


    • 已编辑 呆oO 2012年12月2日 8:05
    2012年12月2日 8:03
  • 应该是可以的。你的数据库版本是2005或者2005以上的吗?


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    2012年12月2日 8:13
    版主
  • 是ACCESS2003,

    还想请教一下,如果您说的方法可以实现,我还想了解一下我之前提的两个问题,您能帮我写两段示例吗?谢谢

    还有如何随机抽取不重复,谢谢。


    C#初学者!~~~

    2012年12月2日 8:14
  • 那么以后希望你用啥数据库写清楚。

    随机抽取题目,我建议你可以先随机生成一堆随机序列号(假设1~100个题目),你可以这样生成随机号:

    class Program
        {
            static void Main(string[] args)
            {
                List<int> numbers = new List<int>();
                Random r =new Random(Guid.NewGuid().GetHashCode());
     
                for (int i = 1; i < 101; i++)
                {
                    numbers.Insert(r.Next(0, numbers.Count), i);    //随机插入数字编号
                }
     
                //生成SQL语句
                string s = "Select * from xxx where Id in("+string.Join(",",numbers.Take(20))+")";
     
                //检测SQL语句
                Console.WriteLine(s);
            }
        }

    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    • 已标记为答案 呆oO 2012年12月3日 2:35
    2012年12月2日 8:22
    版主
  • 谢谢董哥,我先试试看。


    C#初学者!~~~

    2012年12月3日 2:36
  • 我按照你的代码执行出现两个错误,我理解不了,麻烦帮我指点一下。谢谢


    C#初学者!~~~

    2012年12月3日 5:18
  • 我的没有错误啊……

    你要不这样改:

     

    string s = "Select * from xxx where Id in(" + string.Join(",", numbers.Take(20)

    .Select(c=>c.ToString()).ToArray()) + ")";


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    2012年12月3日 5:25
    版主
  • 老师,能不能麻烦您解释一下上面的代码,我看不太懂后面的部分。谢谢

    C#初学者!~~~

    2012年12月3日 5:34
  • 老师,能不能麻烦您解释一下上面的代码,我看不太懂后面的部分。谢谢

    C#初学者!~~~


    String.Join希望附带一个string和string数组的参数。前一个是逗号,后一个我使用Select强制把每个int转换成string,然后再使用ToArray转换成string数组。

    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    2012年12月3日 5:53
    版主
  • 老师,我还有个问题,看下我的代码:

                        DataSet ds = new DataSet();
                        DataTable dt1 = new DataTable();
                        DataTable dt2 = new DataTable();
    
                        sql = string.Format("select tmid,tm,cxmc from tmb where cxmc='大型客车' union select tmid,tm,cxmc from tmb where cxmc='小型汽车' order by tmid");
                        OleDbDataReader dr = new ConnDb().dr(sql);
                        //获取当前车型的第个ID
                        if(dr.Read())
                        {
                            begincount = Convert.ToInt32(dr["tmid"].ToString());
                        }
                        //获取当前车型的最后一个ID
                        while (dr.Read())
                        {
                            endcount = Convert.ToInt32(dr["tmid"].ToString());
                        }
    
                        List<int> numbers = new List<int>();
                        Random rdm = new Random(Guid.NewGuid().GetHashCode());
    
                        for (int i = begincount ; i <= endcount ; i++)
                        {
                            numbers.Insert(rdm.Next(0, numbers.Count), i);
                        }
    

    我现在想在两个不同条件筛选出来的记录里随机抽题(看上面的SQL语句),但是ID号中间有断开的,比如:1-100是小型汽车,100-200是大型货车,200-300是大型客车,我现在想筛选出小型汽车和大型客车的题目然后随机抽题,ID号是1-100,200-300,应该如何写代码实现?谢谢

    C#初学者!~~~

    2012年12月3日 7:30
  • 分两次随机选题:第一次是1~100,第二次是200~300,假设你的两个表的结构完全一样,然后使用DataTable的Merge方法合并即可。


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    2012年12月3日 7:38
    版主
  • 我写的代码比较乱,合并DATATAL可能比较麻烦。我想,能不能用两个FOR循环生成随机数,然后合并这些随机数到一个数组中,然后在这个数组中抽题呢。麻烦写个示例,谢谢。

    C#初学者!~~~

    2012年12月3日 7:50
  • 我写的代码比较乱,合并DATATAL可能比较麻烦。我想,能不能用两个FOR循环生成随机数,然后合并这些随机数到一个数组中,然后在这个数组中抽题呢。麻烦写个示例,谢谢。

    C#初学者!~~~


    请自己设法按照我第一个示例代码先动脑子自己写,然后有问题才提出。谢谢!

    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    2012年12月3日 7:52
    版主
  • 您好,上次咨询您的这个问题,现在又出现了新的问题!我现在用MERGE方法合并了两张表,我想让合并后的总数是100,第一张表我随机抽取了30题,第二张表随机抽取70题。下面是SQL:

    第一表:

    sql = "SELECT tmid,tm as 题目,tmlx as 题目类型,daA as 答案A,daB as 答案B,daC as 答案C,daD as 答案D,daE as 答案E,daF as 答案F,daG as 答案G,zqda as 正确答案,ZJB.zjmc as 所属章节,picpath as 图片路径,szym as 所在页码,daanshu as 答案数,daantishi as 答案提示,cxb.cxmc as 车型 FROM TMB,ZJB,CXB where tmb.cxmc=cxb.cxmc and tmb.zjmc=zjb.zjmc and tmb.cxmc='大型客车' and zjb.cxmc='大型客车' and tmid in(" + string.Join(",", numbers.Take(30).Select(c => c.ToString()).ToArray()) + ")";

    第二表:

    sql = "SELECT tmid,tm as 题目,tmlx as 题目类型,daA as 答案A,daB as 答案B,daC as 答案C,daD as 答案D,daE as 答案E,daF as 答案F,daG as 答案G,zqda as 正确答案,ZJB.zjmc as 所属章节,picpath as 图片路径,szym as 所在页码,daanshu as 答案数,daantishi as 答案提示,cxb.cxmc as 车型 FROM TMB,ZJB,CXB where tmb.cxmc=cxb.cxmc and tmb.zjmc=zjb.zjmc and tmb.cxmc='小型汽车' and zjb.cxmc='小型汽车' and tmid in(" + string.Join(",", numbers.Take(76).Select(c => c.ToString()).ToArray()) + ")";

    问题在这里,第一表的numbers.Take(30),每次都固定抽取30题出来。但第二表的SQL语句中的numbers.Take(76),这里填入70的话,不能固定抽取出70题。而是在70左右上下浮动,合并后的总数在95-106之间浮动的随机数,填写76的时候才能偶尔抽取到70题,请您帮我看一下是什么问题?下面附上代码:

                        DataSet ds = new DataSet();
                        DataTable dt1 = new DataTable();
                        DataTable dt2 = new DataTable();
                        DataTable dt3 = new DataTable();
                        //////////////////////////////随机抽取第一组考题开始/////////////////////////
                        sql = string.Format("select tmid,tm,cxmc from tmb where cxmc='大型客车' order by tmid");
                        OleDbDataReader dr = new ConnDb().dr(sql);
                        //获取当前车型的第个ID
                        if(dr.Read())
                        {
                            begincount = Convert.ToInt32(dr["tmid"].ToString());
                            //获取当前车型的最后一个ID
                            while (dr.Read())
                            {
                                endcount = Convert.ToInt32(dr["tmid"].ToString());
                            }
                        }
    
                        //创建随机数
                        List<int> numbers = new List<int>();
                        Random rdm = new Random(Guid.NewGuid().GetHashCode());
    
                        for (int i = begincount ; i <= endcount ; i++)
                        {
                            numbers.Insert(rdm.Next(0, numbers.Count), i);
                        }
    
                        sql = "SELECT tmid,tm as 题目,tmlx as 题目类型,daA as 答案A,daB as 答案B,daC as 答案C,daD as 答案D,daE as 答案E,daF as 答案F,daG as 答案G,zqda as 正确答案,ZJB.zjmc as 所属章节,picpath as 图片路径,szym as 所在页码,daanshu as 答案数,daantishi as 答案提示,cxb.cxmc as 车型 FROM TMB,ZJB,CXB where tmb.cxmc=cxb.cxmc and tmb.zjmc=zjb.zjmc and tmb.cxmc='大型客车' and zjb.cxmc='大型客车' and tmid in(" + string.Join(",", numbers.Take(30).Select(c => c.ToString()).ToArray()) + ")";
                        dt2 = new ConnDb().dt(sql);
                        //////////////////////////////随机抽取第一组考题结束/////////////////////////
    
                        //////////////////////////////随机抽取第二组考题开始/////////////////////////
                        sql = string.Format("select tmid,tm,cxmc from tmb where cxmc='小型汽车' order by tmid");
                        dr = new ConnDb().dr(sql);
                        if (dr.Read())
                        {
                            begincount = Convert.ToInt32(dr["tmid"].ToString());
                            while (dr.Read())
                            {
                                endcount = Convert.ToInt32(dr["tmid"].ToString());
                            }
                        }
                        Random rdm1 = new Random(Guid.NewGuid().GetHashCode());
                        for (int i = begincount; i <= endcount; i++)
                        {
                            numbers.Insert(rdm1.Next(0, numbers.Count), i);
                        }
    
                        sql = "";
                        // sql = "SELECT tmid,tm as 题目,tmlx as 题目类型,daA as 答案A,daB as 答案B,daC as 答案C,daD as 答案D,daE as 答案E,daF as 答案F,daG as 答案G,zqda as 正确答案,ZJB.zjmc as 所属章节,picpath as 图片路径,szym as 所在页码,daanshu as 答案数,daantishi as 答案提示,cxb.cxmc as 车型 FROM TMB,ZJB,CXB where tmb.cxmc=cxb.cxmc and tmb.zjmc=zjb.zjmc and tmb.cxmc='小型汽车' and zjb.cxmc='大型客车' and tmid in(" + string.Join(",", numbers.Take(107).Select(c => c.ToString()).ToArray()) + ")";
                        sql = "SELECT tmid,tm as 题目,tmlx as 题目类型,daA as 答案A,daB as 答案B,daC as 答案C,daD as 答案D,daE as 答案E,daF as 答案F,daG as 答案G,zqda as 正确答案,ZJB.zjmc as 所属章节,picpath as 图片路径,szym as 所在页码,daanshu as 答案数,daantishi as 答案提示,cxb.cxmc as 车型 FROM TMB,ZJB,CXB where tmb.cxmc=cxb.cxmc and tmb.zjmc=zjb.zjmc and tmb.cxmc='小型汽车' and zjb.cxmc='小型汽车' and tmid in(" + string.Join(",", numbers.Take(76).Select(c => c.ToString()).ToArray()) + ")";
    
                        ds = new ConnDb().ds(sql);
                        dt1 = new DataTable();
                        dt3 = new ConnDb().dt(sql);
                        //////////////////////////////随机抽取第二组考题结束/////////////////////////
    
                        dt3.Merge(dt2);//合并两组考题
                        if (dt3.Rows.Count != 100)
                        {
                            MessageBox.Show("题目数量不足,无法生成考试题目!" + dt3.Rows.Count + "");
                            return;
                        }
                        dgv_Exam.DataSource = dt3;


    C#初学者!~~~


    • 已编辑 呆oO 2012年12月16日 4:36
    2012年12月16日 4:26
  • 尝试两张表先分别随机:

    Select * from xxx by newid()

    然后确保每个表记录都要至少>70条。

    然后筛选70条记录。


    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    2012年12月16日 5:22
    版主
  • 首先可以确定记录大于70.其次我用的是ACCESS,newid()不能用。我用的方法也是你上次告诉我的。麻烦您查看一下上面的代码,看看问题出在什么地方。谢谢。

    C#初学者!~~~

    2012年12月16日 9:26