This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.

Hi there! I'm new to programming and have following problem. A circle, with radius 30, needs to move around a perimeter of 400 pixels from position (30,30) in a clock-wise direction at first. It moves each time by 5pixels delayed by 20 milliseconds. With each move, it needs to be capable to change its direction with a probability of 0.01. Although I'm able to have the circle moving around the perimeter at the desired speed, I just can't get it to randomly change its direction. I have tried if-statements: (if randomNum > 0.01 then change direction,) switch-statements and boolean values. I however haven't been able to get it to work for me. I know how to change the direction once or twice, but this needs to be done indefinitely, during each move of the circle and everything needs to be enclosed by a while (true) loop, thus making sure the circle moves until program is quit. Clearly, this is repetition, so a loop is required, but where should the random class: Math.random be placed, as a number between 0 and 1 needs to be generated on each move. If num > 0.01 then move clockwise, if num < 0.01 then move anti-clockwise. During the next move it needs to be: if num >0.01 then move anti-clockwise, if num < 0.01 then move clockwise and so on. Please help!!

If you are using the timer class, then this would be in the timer callback routing and would not need a loop. Post some of your code, and we'll be happy to help some more.

Tom Blough

Tom Blough<br /> <blockquote><font size="1" face="Verdana, Arial">quote:</font><hr>Cum catapultae proscriptae erunt tum soli proscripti catapultas habebunt.<hr></blockquote>

Amil Mehmedagic
Greenhorn

Joined: Feb 27, 2004
Posts: 22

posted

0

Thanks for your response! I haven't been taught about the Timer class. I am using the CircleFigure class, which has the following methods: moveRight(x),moveLeft(x),moveUp(x),moveDown(x),moveTo(x,y),setRadius(x), setColour(c),drawHollow(),drawFilled(),getXCentre() and getYCentre(). Ultimately, I cannot use the Timer class for this problem. Here is my code, which makes the circle move around a perimeter of 400 pixels. I know that I have to use the random method from the Math class to generate a number between 0 and 1, which will decide on the direction. Note that this is missing from the code: [code] public class MovingCircle3 {

/*Create a circle of radius 30 pixels at position(30,30). Circle is to move at a rate of 5 pixels every 20 milliseconds to follow the perimeter of the square (400 pixels). Initially the circle is to move in a clockwise direction. However at each move the circle must have a probability of 0.01 to change direction. */ [code] public class MovingCircle1{

public static void main ( String [ ] args){

CircleFigure.create(); CircleFigure.setRadius(30); CircleFigure.moveTo(30,30); int x = CircleFigure.getXCentre(); int y = CircleFigure.getYCentre(); double randomNum; double probDirectionChange = 0.01; while (true) { do { Delay.milliseconds(20); x = x + 5; CircleFigure.moveRight(5); } while ( x != 430);

do { Delay.milliseconds(20); y = y + 5; CircleFigure.moveDown(5); } while ( y != 430);

do { Delay.milliseconds(20); x = x - 5; CircleFigure.moveLeft(5); } while ( x != 30);

do { Delay.milliseconds(20); y = y - 5; CircleFigure.moveUp(5); } while ( y != 30);

} } } I have also written other slight variations of the code above. I also tried placing if-statements within each of the do-loops. The circle however just changes its direction for a second and immediately continues on its clockwise path. The correct way is that when the circle changes its direction with prob. 0.01 and thus starts moving anti-clockwise, then the probability of changing back to clockwise is 0.01 and vice versa. At the start the probability of changing the direction from clockwise to anti-clockwise is 0.01 and this is a constant. However the random number (Math.random()) needs to be generated each time, the circle moves 5 pixels, so there is always a chance of direction change. So far i've just been unable to utilize the Math.class correctly for this purpose, or is there something else I overlooked? A thousand thanks for any assistance!

Tom Blough
Ranch Hand

Joined: Jul 31, 2003
Posts: 263

posted

0

Use the same technique in my first post but instead use it to toggle a boolean variable:

Do your delay first. There is no need to duplicate this call multiple time. Wait first, then figure out if you are moving clockwise or counterclockwise, and finally execute the move in the correct direction. Tom Blough

Amil Mehmedagic
Greenhorn

Joined: Feb 27, 2004
Posts: 22

posted

0

I've followed your advice and written this code. However the circle still only moves around the perimeter. It doesn't change the direction. What have I done wrong? Here is the code: [code] public class MovingCirclenew {

public static void main ( String [ ] args) {

CircleFigure.create(); CircleFigure.setRadius(30); CircleFigure.moveTo(30,30); int x = CircleFigure.getXCentre(); int y = CircleFigure.getYCentre();

boolean isClockwise = true;

while (true) { Delay.milliseconds(20); if (Math.random() < 0.01) isClockwise = !isClockwise; if (isClockwise) { while (x!=430) { Delay.milliseconds(20); CircleFigure.moveRight(5); x = x + 5; } while (y!=430) { Delay.milliseconds(20); CircleFigure.moveDown(5); y = y + 5; } while (x!=30) { Delay.milliseconds(20); CircleFigure.moveLeft(5); x = x - 5;} while (y!=30) { Delay.milliseconds(20); CircleFigure.moveUp(5); y = y - 5;}

}else { while (y!=430) { Delay.milliseconds(20); CircleFigure.moveDown(5); y = y + 5;} while (x!=430) { Delay.milliseconds(20); CircleFigure.moveRight(5); x = x + 5; } while (y!=30){ CircleFigure.moveUp(5); y = y - 5; } while (x!=30) { Delay.milliseconds(20); CircleFigure.moveLeft(5); x = x - 5;} } } } } The problem I believe lies in that the parameters or path that the circle is supposed to move in needs to be declared in a while loop. This is the only way I know to tell the object where to stop travelling along one direction. This means that the one loop is active until the circle moves to x == 430 and then the next loop is activated, which brings the circle down. During all of this time however the randomNum is not generated. It is only generated once the circle has travelled once around the perimeter. How can I then program, so that the circle has a chance of 0.01 to change its direction, each time it moves either right,down,left or up? Because I think the code above only generates the number after the circle has already travelled around, instead doing it every time the object moves.

Amil Mehmedagic
Greenhorn

Joined: Feb 27, 2004
Posts: 22

posted

0

Here is my final shot at it. It however still doesn't do what it's supposed to do. What have I done wrong? public static void main ( String [ ] args) {

CircleFigure.create(); CircleFigure.setRadius(30); CircleFigure.moveTo(30,30); int x = CircleFigure.getXCentre(); int y = CircleFigure.getYCentre();

boolean isClockwise = true;

while (true) { Delay.milliseconds(20); if (Math.random() < 0.01) isClockwise = false; if (isClockwise = true) { while (x!=430) { Delay.milliseconds(20); CircleFigure.moveRight(5); x = x + 5; if (Math.random() < 0.01) isClockwise = false;

} while (y!=430) { Delay.milliseconds(20); CircleFigure.moveDown(5); y = y + 5; if (Math.random() < 0.01) isClockwise = false; } while (x!=30) { Delay.milliseconds(20); CircleFigure.moveLeft(5); x = x - 5; if (Math.random() < 0.01) isClockwise = false; } while (y!=30) { Delay.milliseconds(20); CircleFigure.moveUp(5); y = y - 5; if (Math.random() < 0.01) isClockwise = false; }

}else { while (y!=430) { Delay.milliseconds(20); CircleFigure.moveDown(5); y = y + 5; if (Math.random() < 0.01) isClockwise = true;} while (x!=430) { Delay.milliseconds(20); CircleFigure.moveRight(5); x = x + 5; if (Math.random() < 0.01) isClockwise = true;} while (y!=30){ Delay.milliseconds(20); CircleFigure.moveUp(5); y = y - 5; if (Math.random() < 0.01) isClockwise = true;} while (x!=30) { Delay.milliseconds(20); CircleFigure.moveLeft(5); x = x - 5; if (Math.random() < 0.01) isClockwise = true;} } } } }

Tom Blough
Ranch Hand

Joined: Jul 31, 2003
Posts: 263

posted

0

You should not have all the while loops inside the if( clockwise)/else construction. The outer while( true) loop makes the object move continuosly. Within the loop, you wait the proscribed time, check to see if you need to change direction, and then based on the current direction, you make ONE move only! The while loop then restarts, waits 20 milliseconds, decides if it need to change direction, and then makes ONE more move. The loop then restarts...

Your logic for determining where the circle is within the pattern needs some work as well. Just checking if x != 430 is not enough. Is it at the top of the pattern or the bottom? If it is at the top (i.e. y == 30) an you are moving clockwise, then you need to add 5 to x, but if y == 430, then you are at the bottom of the pattern and therefore you need to move the circle to the left (i.e. subtract 5). So, you will need to do something like this:

Notice how we first check to see which side the circle is currently on (i.e x == 30), then we check to see if it can move further on that side (i.e y > 30)? It's not enough just to find out what side we are on. What if x = 30 and y = 30? If we know we are moving clockwise, then we know we are in the upper left corner and we need to move right. So the test (x == 30 && y > 30) would be false (we don't want to move up any more), but the test (y = 30 && x < 430) would be true so we would move to the right. There are some more elegant ways to do this, but get this working first, and then we'll discuss some improvements you can make.

You do realize that the 0.01 means it will only change direction 1% of the time right? This means you would have to run the program a long time to see it change direction. What *I* would do is make that 0.01 into a variable and, for testing, change it to 0.50 which means 50% of the time it will change direction. Use that for testing since you will see it change direction much more frequently. Once you verify that it does indeed randomly change direction, change it back to 0.01. Also, you may want to System.out.println out the random() value so you can see if it should be changing or not. Maybe do both - use 0.50 AND print out the value. Hope this helps, brian

I got it to work exactly as I wanted it to! Thank you very much Tom for your help and support with this task. I wasted countless hours trying to make the program work using faulty logic. I probably wouldn't have finished this task so quickly without your help. Of course I thank Brian for his contribution as well. This is now only the third small program I wrote. In your earlier message, you said that there is a more elegant way to do it. What exactly did u have in mind? I'm thinking of trying to write the same program using switch-statements.

Tom Blough
Ranch Hand

Joined: Jul 31, 2003
Posts: 263

posted

0

Amil, Glad to hear you got it working. I alluded to the more elegant method in an earlier post. Instead of using a flag to denote direction, you can make the direction change either a postive or negative amount. Then, instead of moveRight, moveLeft, moveUp, moveDown methods you would just have moveVertical, and moveHorizontal methods. These methods would take a positive or negative displacement value. Tom