2

For some coursework I need to generate a normal magic square through brute force, this is part of the code. fyi; I'm not allowed to use any classes other than the commonly used. (I'm probably pushing my luck with Math.Pow)

I have the following method to generate a 2 dimensional of size NxN:

    static int[,] GenerateSquare(int n)
    {
        int[,] sqarray = new int[n,n];
        int[] rndarray = new int[n];

        //puts completely random integers from 1 to n^2 in all elements of the square array (sqarray)
        for (int i = 0; i < n; i++)
        {
            rndarray = FullRndArray(n);

            for (int j = 0; j < n; j++)
            {
                sqarray[i, j] = rndarray[j];
            }
        }

        return sqarray;
    }

The FullRndArray() method is below:

static int[] FullRndArray(int n)
    {
        //creates an array of size n and fills with random intigers between 1 and n^2
        int[] rndarray = new int[n];
        Random rnd = new Random();

        int ntothe2 = Convert.ToInt32(Math.Pow(n, 2));

        for (int i = 0; i < n; i++)
            rndarray[i] = rnd.Next(1, ntothe2 + 1);

        return rndarray;
    }

The problem is that when i run this code, the contents of each line is random, but each line of the square is the same as the last (ie 1-1, 1-2, 1-3 are the same as 2-1, 2-2, 2-3 and the same as 3-1, 3-2, 3-3 respectively). Yet when i go through debugger line by line, i end up with a perfectly random set of numbers in every space. Can anyone explain this error to me please?

IamPancakeMan
  • 199
  • 1
  • 10
  • You can eliminate the `Math.Pow` just by using `n * n`. And generally speaking, you can use `(int)` instead of `Convert.Int32` unless you want rounding. – Gabe Jan 21 '14 at 19:32

2 Answers2

5

This is the culprit:

Random rnd = new Random();

Random numbers are generated starting from a seed: same seed means same not-so-random sequence of numbers. Random uses the current time as seed, so when you run your code it runs so fast that you are creating two Randoms with the same seed, which then produce two identical rows. On the other hand, when you are debugging you let enough time pass and everything goes as expected.
The solution is to create an instance of Random, static or at the beginning of GenerateSquare, and use that one for the whole process.

BlackBear
  • 22,411
  • 10
  • 48
  • 86
1

I got exactly the same behavior that you describe.

This seems to work :

static int[,] GenerateSquare(int n)
{
    int[,] sqarray = new int[n, n];
    int[] rndarray = new int[n];

    Random rnd = new Random();
    //puts completely random integers from 1 to n^2 in all elements of the square array (sqarray)
    for (int i = 0; i < n; i++)
    {
        rndarray = FullRndArray(n, rnd);
        for (int j = 0; j < n; j++)
        {
            sqarray[i, j] = rndarray[j];
        }
    }

    return sqarray;
}
static int[] FullRndArray(int n, Random rnd)
{
    //creates an array of size n and fills with random intigers between 1 and n^2
    int[] rndarray = new int[n];

    int ntothe2 = Convert.ToInt32(Math.Pow(n, 2));

    for (int i = 0; i < n; i++)
        rndarray[i] = rnd.Next(1, ntothe2 + 1);

    return rndarray;
}

I understand we must use the Random.Next() method on the same instance in order to be "really" random (as described in the BlackBear answer).

It probably worked during debug because you induced time laps between steps.

cubitouch
  • 1,929
  • 15
  • 28