Coffeehouse Thread

37 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

Randomnesessesses

Back to Forum: Coffeehouse
  • User profile image
    W3bbo

    Behold! This 'ere Sea-Sharp be not workingzor properleeeeey:

                // randomly pick buttons that are mines
                for(int i=0; i<Mines; i++) {
                    
                    Random R = new Random( DateTime.Now.Second );
                    double rX = R.NextDouble();
                    double rY = R.NextDouble();
                    
                    // Convert X and Y to integers between 0 and Width|Height
                    int X = Convert.ToInt32(rX * (Width  - 1));
                    int Y = Convert.ToInt32(rY * (Height - 1));
                    
    //                if(Boxes[X, Y].isMine == true) {
    //                    i--;
    //                } else {
                        Boxes[X, Y].isMine = true;
    //                }
                    
                }
    


    (Boxes is a 2-dimesnional array of a class with boolean property "isMine"), Width = 24, Height = 36, Mines = 20

    When I uncomment the commmented bit, it sometimes gets stuck in an infinite loop, when I set "Mines" to something small, like 8, the function takes about 15 seconds to complete (rather than the 15 miliseconds it takes when I leave the comments in).

    any ideas?

  • User profile image
    Maurits

    So you're picking cells at random... and if they're already a mine, you pick another cell at random?

    Hmm...

    Try this method instead.  Number the cells from 1 to 20.

    for (i = 1 to # of mines)
    {
        Pick a random number n from 1 to # of cells
        Count *unmined* cells until you reach n (when you reach the last cell, wrap)
        Put a mine on that cell
    }

    That at least has an upper bound on the time it takes to complete Smiley

  • User profile image
    billh

    I guess I would need to know what you are trying to do in the above example before commenting further.  Are you trying to populate an array with randomly placed mines, or trying to find them? Or something completely different?

  • User profile image
    Maurits

    W3bbo wrote:
                    Random R = new Random( DateTime.Now.Second );



    The root of your problem, though, is this line.  When you create two Random objects with the same seed, they will give you the same random sequence.

    Create the Random object prior to the for loop, and reuse it.

    EDIT: As an experiment, print out the value of X and Y from your code.  You should see something like:

    X = 17, Y = 5
    X = 17, Y = 5
    ...
    ... one second later...
    X = 3, Y = 12
    X = 3, Y = 12
    ...
    ... one second later...
    (etc.)

  • User profile image
    W3bbo

    Maurits wrote:
    W3bbo wrote:
                    Random R = new Random( DateTime.Now.Second );



    The root of your problem, though, is this line.  When you create two Random objects with the same seed, they will give you the same random sequence.

    Create the Random object prior to the for loop, and reuse it.

    EDIT: As an experiment, print out the value of X and Y from your code.  You should see something like:

    X = 17, Y = 5
    X = 17, Y = 5
    ...
    ... one second later...
    X = 3, Y = 12
    X = 3, Y = 12
    ...
    ... one second later...
    (etc.)


    Yep, that was the cause of the problem, having changed it to "DateTime.Now.Milisecond" it works faster.

    But now I've got another problem, I'm adding a grid of System.Windows.Forms.Button to a Panel, but even with SuspendLayout and ResumeLayout, I can still see the redraw, and it takes about 1.5 seconds (and raises CPU% to 100%, although I can't argue the nice "slide-in, slide-out" effect caused by the repainting looks bad.

    Is there any way to add a hundred or so buttons to a panel without it doing it all curtains-y?

    The same happens when I call Panel.Controls.Clear(), it "curtains" it out.

  • User profile image
    W3bbo

    Here's a shot of it so far. I inserted the Suspend and ResumeLayout calls just before and after all control-related calls.

  • User profile image
    Maurits

    W3bbo wrote:

    Yep, that was the cause of the problem, having changed it to "DateTime.Now.Milisecond" it works faster.


    ... eh...

    You really only need one Random object per program.  This is a rare exception to the principle that objects should be created in the smallest possible scope.

    (Also, it doesn't really matter for this project, but things like DateTime.Now.Second and DateTime.Now.Millisecond are lousy random seeds if you care about randomness.  There's only sixty-ish possibilities for .Second, for example.  So if you play the game sixty-one times, you'll see the same starting position twice.)

  • User profile image
    W3bbo

    Maurits wrote:
    You really only need one Random object per program.  This is a rare exception to the principle that objects should be created in the smallest possible scope.


    Manip suggested I do that, blame him.

    Maurits wrote:
    (Also, it doesn't really matter for this project, but things like DateTime.Now.Second and DateTime.Now.Millisecond are lousy random seeds if you care about randomness.  There's only sixty-ish possibilities for .Second, for example.  So if you play the game sixty-one times, you'll see the same starting position twice.)


    I tried using Convert.ToIn32(.Ticks) but I got overflow/too-large exceptions.

  • User profile image
    Minh

    put this line outside of the for loop

    Random R = new Random( DateTime.Now.Second );

    You're re-seeding R with the same value -- even with milisecond, it'll still be the same value if your computer is fast enough.

  • User profile image
    Minh

    W3bbo wrote:


    I tried using Convert.ToIn32(.Ticks) but I got overflow/too-large exceptions.
    Seeding needs to be done only once every time you run the program. In that case, it doesn't matter the second or milisecond value you use (assuming you can't start your app again a second later)

  • User profile image
    Maurits

    W3bbo wrote:

    I tried using Convert.ToIn32(.Ticks) but I got overflow/too-large exceptions.


    The beauty of persisting a single Random object is that you can just call the argumentless constructor and you don't have to worry about the time-dependent issue you ran into.

    That said, MSDN lists a way to force .Ticks into an Int32 in the Random(Int32) manpage...

    Random rdm1 = new Random(unchecked((int)DateTime.Now.Ticks));

  • User profile image
    Maurits

    Oh, and one more thing... Random can return random integers between 0 and a given upper bound directly, which could simplify your code.

    See Random.Next(Int32)

  • User profile image
    W3bbo

    Nevermind, I just found the second override of the Next() method, I'm an eejit Smiley


    But I've still got performance problems with the redrawing.

  • User profile image
    Tom Servo

    Wouldn't it be faster and more efficient to ownerdraw the contents into the panel instead of using a trillion of buttons? I'm sure GDI loathes you for that one.

  • User profile image
    W3bbo

    Tom Servo wrote:
    Wouldn't it be faster and more efficient to ownerdraw the contents into the panel instead of using a trillion of buttons? I'm sure GDI loathes you for that one.


    ...I'm not sure if I understand you.

  • User profile image
    Rossj

    What Tom said Smiley There are *far* too many buttons on that Form. Draw it yourself (on a single control) and maybe you can even have some nice lil animations. It'll be much faster.

  • User profile image
    W3bbo

    Rossj wrote:
    What Tom said Smiley There are *far* too many buttons on that Form. Draw it yourself (on a single control) and maybe you can even have some nice lil animations. It'll be much faster.


    ...but then how would I get the "button press" effect?

    ...actually, how would I "draw" a button anyway? Do I need to type out "DrawLine(co-ords)" over and over again?

  • User profile image
    Rossj

    Ahem.

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.