1

I have been able to use the random method to accomplish most of my tasks in trying to populate labels and RadioButtonList Items randomly to create a 5 question quiz. The code generates a good blend of questions given the large pool it draws from.

However, the inner code for randomly populating the RadioButtonList Items is acting funny.

  1. When I throw in breakpoints at my while loop and run it step by step the answers are populated in different order on every next question.

  2. But when I simply open up the browser and run it from the Sharepoint website I have it deployed to, the answers follow the same order sequence on every next question/all questions. Note: It does however throw unique orders on page refresh; in other words when I start the quiz again.

I cant seem to figure out the hitch for the life of me. Could use a few sets of eyes.

Here is the code thus far: Please advise

  public void LoadQuestions()
    {
        try
        {
            SPWeb thisWeb = SPContext.Current.Web;
            SPList oSPList = thisWeb.Lists["QuestionsAndAnswers"];
            SPListItemCollection oSPListItemCollection = oSPList.Items;

            Random rand = new Random();
            List<int> tempStore = new List<int>();
            List<int> tempStore2 = new List<int>();
            int tempValue = 0;
            //int tempValue2 = 0;
            int icount = 1;
            int iMax = oSPListItemCollection.Count;
            //int icount2 = 0;
            //int iMax2 = oSPListItemCollection.Count;
            SPListItem thisItem;
            Label thisQuestion;
            Label thisCorrectAnswer;
            RadioButtonList thisAnswers;

            while (icount < 6)
            {
                tempValue = rand.Next(1, iMax);
                if (tempStore.Exists(value => value == tempValue))
                    continue;
                else
                {
                    tempStore.Add(tempValue);
                    thisQuestion = (Label)UpdatePanelMaster.FindControl("Question" + icount.ToString());
                    thisItem = oSPListItemCollection[tempValue];
                    thisQuestion.Text = icount + ". " + thisItem["Question"].ToString();

                    thisCorrectAnswer = (Label)UpdatePanelMaster.FindControl("CorrectAnswer" + icount.ToString());
                    thisCorrectAnswer.Text = thisItem["CorrectAnswer"].ToString();

                    thisAnswers = (RadioButtonList)UpdatePanelMaster.FindControl("RadioButtonList" + icount.ToString());

                    //Entering code to handle random answer arrangements 
                    //This code works ok when run in a step by step debug fashion but no when deployed  and run from the website directly. 
                    Missing/Changes required?
                    int tempValue2;
                    int Icounter = 0;
                    string[] AnswerArr = new string[] { thisItem["CorrectAnswer"].ToString(), thisItem["IncorrectAnswer1"].ToString(), thisItem["IncorrectAnswer2"].ToString(), thisItem["IncorrectAnswer3"].ToString() };
                    Random rand2 = new Random();

                    while (Icounter < 4)
                    {
                        tempValue2 = rand2.Next(0, 13);//max number of items in the array 
                        decimal toCeilingVar = tempValue2 / 4; 
                        int fraction = Convert.ToInt32(System.Math.Ceiling(toCeilingVar));
                        string tempArrValue = AnswerArr[fraction];
                        if (thisAnswers.Items.FindByValue(tempArrValue) == null)
                        {
                            //add new value because the current value is not in the list
                            thisAnswers.Items.Add(tempArrValue);
                            Icounter++;
                            tempArrValue = string.Empty;
                        }
                        tempValue2 = 0;
                        toCeilingVar = 0;
                        fraction = 0; 

                        //End Random Answer handling 
                    }
                    tempValue = 0;
                    icount++;
                }
            }
        }
        //End random question handling

        catch (Exception ex)
        {
            throw ex;
        }
    }
user1266515
  • 796
  • 3
  • 15
  • 33
  • Side note: it would be interesting to know why this question was upvoted... It is caused by top answer to 2 most likely tags [C# random](http://stackoverflow.com/questions/tagged/c%23+random?sort=votes&pagesize=50) and contains very long sample... – Alexei Levenkov Jun 27 '13 at 05:09

2 Answers2

1

The problem is (inside the loop):

Random rand2 = new Random();

The Random class is, if no explicit seed is provided, seeded using the time. If you create multiple instances in a tight loop, they will often be close enough (in time) together that they have the same seed. This means they will all generate the same sequence of pseudo-random numbers. Two options:

  • lose the inner Random instance (rand2) completely - just use the single outer instance (rand); using more Random instances does not increase the randomness
  • use the outer instance to seed the inner instance

I'd only use the latter if there was a good reason, for example parallelism

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
1

Probably what is happening here is that when run in production, the line Random rand2 = new Random() is called several times in a very short interval of time, so each instance will have the same initial seed value. The default constructor for Random uses a time-based seed with fairly low resolution in my experience.

To solve this, I would just use the single rand variable to generate all random numbers, or initialize rand2 outside the outermost loop.

Kent Skinner
  • 106
  • 4