SyncMaster
SyncMaster

Reputation: 9916

Issue with Random numbers in Java

I wrote a piece of code to move an object in a Random Direction in Java. There are two functions.

  1. FindRandomDirection - Gets a random direction from 8 possible directions (Directions are represented by the numbers 1,2,3,4,6,7,8,9 in a numpad). Check is done to see if the object is near any of the borders. If so the object will move in a direction away from the border.

  2. MoveObject - Changes the (X, Y) co-ordinates of the object by moving by a constant STEP.

But what ever values I give for X, Y; after repeating the process several times (700 or more), the values of X, Y becomes {X: 20-50} and {Y: 450-465}.

I.e.

Case 1: (x:35,y:65) becomes (x:35, y:465)
Case 2: (x:30, y:455) becomes (x:30, y:460)
Case 3: (x:435, y:65) becomes (x:25, y:460)
Case 4: (x:430, y:465) becomes (x:40, y:460)

I would like to why the after several iterations the x, y points converge towards these values even though I generate the numbers at random.

Below is the code for the same.

import java.io.*;
public class bug
{
    //public static int x = 35;
    //public static int y = 60;

    //public static int x = 35;
    //public static int y = 460;

    //public static int x = 435;
    //public static int y = 60;

    public static int x = 435;
    public static int y = 460;

    public static final int NORTH = 8;
    public static final int EAST = 6;
    public static final int WEST = 4;
    public static final int SOUTH = 2;
    public static final int NORTHEAST = 9;
    public static final int NORTHWEST = 7;
    public static final int SOUTHWEST = 1;
    public static final int SOUTHEAST = 3;
    public static final int STEP = 5;

    //Function to move the object in a specified direction.
    public static void moveObject(int direction)
    {
            double nX = 0, nY=0;
            switch(direction)
            {
            case  NORTH:
                nY = y- STEP; 
                nX = x;
                break;
            case  SOUTH:
                nY = y+ STEP; 
                nX = x;
                break;
            case  EAST:             
                nY = y; 
                nX = x +  STEP;
                break;
            case  WEST:
                nY = y; 
                nX = x- STEP;               
                break;
            case  NORTHEAST:
                nX = x +  STEP;
                nY = y- STEP; 
                break;
            case  NORTHWEST:
                nX = x- STEP;
                nY = y- STEP; 
                break;
            case  SOUTHEAST:
                nX = x +  STEP;
                nY = y+ STEP; 
                break;
            case  SOUTHWEST:
                nX = x- STEP;
                nY = y+ STEP; 
                break;
            }
            x = (int) nX;
            y = (int) nY;
            System.out.println("Direction: "+direction+"; X: "+x+"; Y: "+y);
        }
//Function to move the object in a random direction
//Also if wall(Border) is present the object should move in proper direction
    public static int findRandomDirection(int objObjectX, int objObjectY)
    {
        int[] move = {1,2,3,4,0,6,7,8,9};
        int randDir=0;
        //Generate a random direction to move. Generate new direction if the objected can not be moved in a direction 
        do
        {
            java.util.Random randomGenerator = new java.util.Random();
            randDir = randomGenerator.nextInt(8);

            //If the object lies near East Border, it can not move in that direction
            if(objObjectX <= 25)
            {
                move[0] = 0;
                move[3] = 0;
                move[6] = 0;
            }

            //If the object lies near West Border, it can not move in that direction
            if(objObjectX >= 465)
            {
                move[2] = 0;
                move[5] = 0;
                move[8] = 0;                
            }

            //If the object lies near North Border, it can not move in that direction
            if(objObjectY <= 25)
            {
                move[6] = 0;
                move[7] = 0;
                move[8] = 0;
            }

            //If the object lies near South Border, it can not move in that direction
            if(objObjectY >= 465)
            {
                move[0] = 0;
                move[1] = 0;
                move[2] = 0;                
            }
        } while(move[randDir]==0);
        return move[randDir];       
    }
    public static void main(String[] args)
    {
        for(int i = 0; i<1000;i++)
        {
        int dir=findRandomDirection(x,y);   
        moveObject(dir);
        }
    }
}

So over time, my object moves towards the lower left corner of the board. Kindly help me in finding the bug.

Upvotes: 2

Views: 439

Answers (3)

erickson
erickson

Reputation: 269627

The nextInt(n) method return numbers from zero, inclusive, to n, exclusive. Since you are passing the value 8, the results are from the set of 8 values, 0–7. Thus, the ninth element of the array, which represents the northeast direction, is never selected.

This bias against the northeast results in an eventual migration to the southwest.

Upvotes: 1

akgood
akgood

Reputation: 1117

When you select a direction, you select a value between 0 and 7 inclusive. These values (in your mapping) correspond to:

public static final int SOUTHWEST = 1;
public static final int SOUTH = 2;
public static final int SOUTHEAST = 3;
public static final int WEST = 4;
public static final int EAST = 6;
public static final int NORTHWEST = 7;
public static final int NORTH = 8;

But note that this will never be chosen:

public static final int NORTHEAST = 9;

So, it's not surprising to me that your code seems biased toward the southeast...

Upvotes: 3

VeeArr
VeeArr

Reputation: 6178

Since you are using nextInt(8), the value returned will always be between 0 and 7 (inclusive). Since 8 is never returned, movement is biased towards the opposite direction. You probably want to use nextInt(9), to return a value between 0 and 8 (inclusive).

edit: To clarify, since "8" is never chosen as your random direction, and moves[8]==9, the object never moves in the NORTHEAST direction, which means over time it will tend to travel SOUTHWEST.

Also, as @Joey said above, you shouldn't reinitialize the Random object every time, but that isn't what was causing the drifting behavior.

Upvotes: 6

Related Questions