I would like to write some Java code that will make the mouse "click" somewhere within a 25 by 50 pixel region on the screen. Additionally, I would like the majority of this "clicking" to occur nearer the center of that region (and less around the outside edges of the region). This will approximate the way an actual user might click in the same region.

I am trying to use the nextGaussian method to accomplish this, but I have run into a few snags. One of my criteria is that I don't EVER want to click OUTSIDE the borders (or even ON the borders) of this region and since it is a "standard distribution", eventually nextGaussian will generate numbers that are outside my acceptable range.

I feel like I am close to understanding how this works, but lack of experience is making it slow going. Any suggestions would be appreciated.

Here is what I have so far. I have tinkered with it a bit, but this is the base code...

Robot robot = null;
    int xOff = 908;
    int yOff = 652;
    int w = 25;
    int h = 50;
    int xCenter = w / 2;
    int yCenter = h / 2;
    int xTemp;
    int yTemp;
    int sdX;
    int sdY;
    Random r = new Random();
    
    for (int idx = 1; idx <= 100; ++idx){
      sdX = (int)Math.round(r.nextGaussian() * xCenter + xCenter);
      sdY = (int)Math.round(r.nextGaussian() * xCenter + yCenter);
      xTemp = sdX + xOff;
      yTemp = sdY + yOff;

      try {
        robot = new Robot();
        robot.mouseMove( xTemp, yTemp);
        robot.mousePress(InputEvent.BUTTON1_MASK);
        robot.mouseRelease(InputEvent.BUTTON1_MASK);
        robot.delay(1000);
      } catch (Exception e) {
        System.err.println(e.getMessage());
        e.printStackTrace();
      }

Recommended Answers

All 9 Replies

I don't EVER want to click OUTSIDE the borders (or even ON the borders)

Since you are generating the x,y locations, I don't understand why you can't restrict the click points to where-ever you want them.
Please explain what the problem is.
Your code doesn't check the points before clicking them. Do you have a formula to compute the boundary you don't want to cross?

Since you are generating the x,y locations, I don't understand why you can't restrict the click points to where-ever you want them.
Please explain what the problem is.
Your code doesn't check the points before clicking them. Do you have a formula to compute the boundary you don't want to cross?

Think of it this way... The region I want to click inside of is defined by the w (width) and h (height) integer values. They form a rectangle 25 pixels in width and 50 pixels in height. I want to approximate how a user would click within that region. To do this I use the nextGaussian() method which randomly generates values according to a "standard distribution", i.e., a bell curve. This means that the majority of the clicks will be in the center of the region and very few will occur near the borders of the region.

The problem is that EVENTUALLY that nextGaussian() method will generate a number that is outside that region. It might take a long time, but it WILL happen at some point. The solution is to somehow restrict the values returned by the nextGaussian() method so this cannot happen. The trick is that I can't have that "restriction" effect the "standard distribution" very much or it defeats the purpose.

I have tried a couple of schemes to try "clipping" values that are outside the region, but each scheme has had some sort on derogatory effect on the "standard distribution".

The solution is to somehow restrict the values returned by the nextGaussian() method so this cannot happen. The trick is that I can't have that "restriction" effect the "standard distribution" very much or it defeats the purpose.

Sounds like a contrdiction. You want to restrict the output but can't because it will defeat the distribution.
Either wrap the given method and throw away the ones outside of the desired range or write your own method that doesn't generate outside values.

Sounds like a contrdiction. You want to restrict the output but can't because it will defeat the distribution.
Either wrap the given method and throw away the ones outside of the desired range or write your own method that doesn't generate outside values.

Yes, I suppose in the THEORETICAL application of the nextGaussian() method you hear what "sounds like a contradiction" but I assure you that the PRACTICAL application is not, and here is why.

In our problem, we need to generate random numbers that cluster around an average. In real life, values that "cluster" around an average tend to form a normal distribution, also sometimes called a Gaussian distribution. The nextGaussian() method lets us generate random numbers with this distribution.

The "gotcha" in this "practical application" has to do with the absolute minimum and maximum that nextGaussian() can return, or that could occur. Well, theoretically at least, the slightly paradoxical answer is: There is theoretically no absolute minimum and maximum value that can occur in a normal distribution.
Anyway, leaving the theory aside, the practical result is that nextGaussian() could sooner or later produce values outside the expected range.

This means I need to impose some artificial constraints on the range of values we allow. For example, I can deliberately discard negative (or zero) values by using the following code:

int delay;
do {
  double val = r.nextGaussian() * 100 + 500;
  delay = (int) Math.round(val);
} while (delay <= 0);

Now, as much as I enjoy discussing Java programming theory, I am still left without a solution. I think we have thoroughly covered the "defining the problem" part of the discussion, so is there anyone that has some experience with using the nextGaussian() method, who can offer some useful suggestions?

Ok, I'll hope a specialist can find this and make some suggestions.

Good luck.

I've followed this with some bemusement. You say "This means I need to impose some artificial constraints on the range of values we allow.". So what exactly is wrong with this:

do {
  sdX = (int)Math.round(r.nextGaussian() * xCenter + xCenter);
} while (sdX < 0 || sdX >=w);

I've followed this with some bemusement. You say "This means I need to impose some artificial constraints on the range of values we allow.". So what exactly is wrong with this:

do {
  sdX = (int)Math.round(r.nextGaussian() * xCenter + xCenter);
} while (sdX < 0 || sdX >=w);

I have tried a variety of "clipping" restrictions and each time I come up with unexpected results, i.e., all the clicking occurs in only 1 quadrant of the button or all the clicking occurs at the wrong x and y offsets (general screen locations).

I think the problem is that I am trying to include too many "variables" from the get-go. I think I will go back a rewrite this from scratch... Starting with just clicking in a rectangle, then randomly in a rectangle, then randomly in a rectangle somewhere on the screen, etc.

I will post the solution if and when I get it to work.

I think I will go back a rewrite this from scratch... Starting with just clicking in a rectangle, then randomly in a rectangle, then randomly in a rectangle somewhere on the screen, etc.

It's very refreshing to see someone taking a logical step-by-step approach to solving a problem rather than the usual "I've written 500 lines of code and when i try to run them they DON'T WORK - panic panic.

However, you can't be far off - checkout line 16 where you have an x that should be a y.

Since nextGuassian() will give you a double with mean 0 and std dev of 1.0, perhaps you can use a std deviation of 1/3 of half of your range: rand.nextGaussian()*0.33*halfRange to get 99.7% of your values between [-halfRange,halfRange] and add that to your midpoint?

Random rand = new Random();
        int x0 = 10;
        int x1 = 50;
        int xRange = x1 - x0;
        int halfRange = xRange/2;
        int midPoint = x0+halfRange;

        for (int i=0; i<50; i++){
            System.out.println(Math.round(midPoint+(rand.nextGaussian()*0.33*halfRange)));
        }

You cannot absolutely guarantee that you won't get an invalid value, but it should be outside of the 3 std dev range or around 0.3%. You can just discard those values.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.