This site requires JavaScript, please enable it in your browser!
Greenfoot back
Tommy99
Tommy99 wrote ...

2015/2/6

Problem with Robot going back and forth forever?

Tommy99 Tommy99

2015/2/6

#
Hello. I am almost completed my project and just have one mistake left to correct. I am making a maze game which includes a robot that moves by itself and sticks to a path of always having a wall on its left side. For some reason, when it moves to a space where it does not have a wall on its left side, it does not properly turn left and move forward like it should. Instead, it moves back and forth infinitely. Any help would be appreciated. Robot code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

public class Robot extends MazeWalker
{
    public Robot()
    {
        super();
    }

    public void act() 
    {
        if(wallOnLeft()==true || edgeOnLeft()==true){
            if(canMove()==true){
                moveForward();
            }
            if(canMove()==false){
                turn(90);
            }

        }
        if(wallOnLeft()==false && edgeOnLeft()==false){
            turn(-90);
            moveForward();
        }

        isTouchingTarget();
    }    

    public boolean wallOnLeft()
    {
        int xOffset=0, yOffset=0;

        switch(getRotation()){
            case EAST: yOffset=-1; break;
            case SOUTH: xOffset=1; break;
            case WEST: yOffset=1; break;
            case NORTH: xOffset=-1; break;
        }
        return getOneObjectAtOffset(xOffset, yOffset, Wall.class)!=null;

    }

    public boolean edgeOnLeft()
    {
        switch(getRotation()){
            case EAST: return getY()==0; 
            case SOUTH: return getX()==getWorld().getWidth()-1;
            case WEST: return getX()==getWorld().getHeight()-1;
            case NORTH: return getX()==0;
        }
        return false;
    }

    public boolean robotCanMove()
    {
        return wallOnLeft() || edgeOnLeft();

    }

    public void moveForward()
    {
        counter++;
        if(counter==5){
            move(1);
            counter=0;
        }
    }

}
MazeWalker code (MazeWalker is the Robot's superclass):
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

public class MazeWalker extends Actor
{
    protected final int NORTH = 270;
    protected final int EAST = 0;
    protected final int SOUTH = 90;
    protected final int WEST = 180;
    protected int counter = 0;



    

    public MazeWalker()
    {
        getImage().scale(20,20);
    }

    public void act() 
    {
        isFacingWall();
        isFacingEdge();
        canMove();
        
    }    

    public boolean isFacingWall()
    {
        int xOffset=0, yOffset=0;
        
        
        switch(getRotation()){
            case EAST: xOffset=1; break;
            case SOUTH: yOffset=1; break;
            case WEST: xOffset=-1; break;
            case NORTH: yOffset=-1; break;
        }
        return getOneObjectAtOffset(xOffset, yOffset, Wall.class)!=null;
        

        
    }
    
    public boolean isFacingEdge()
    {
        switch(getRotation()){
            case EAST: return getX()==getWorld().getWidth()-1; 
            case SOUTH: return getY()==getWorld().getHeight()-1;
            case WEST: return getX()==0;
            case NORTH: return getY()==0;
        }
        return false;
    }
    
    public boolean canMove()
    {
        return !(isFacingWall() || isFacingEdge());
    }
    
    public void isTouchingTarget()
    {
        Actor target = getOneIntersectingObject(Target.class);
        if(target!=null){
            getWorld().addObject(new GameOver(), 14, 14);
            Greenfoot.stop(); 
            
        } 
    }
}
danpost danpost

2015/2/6

#
I think the problem is mainly due to how your 'counter' field is restricting the moving of the robot. If there is no wall to the left, the robot will turn; but the 'moveForward' method says "wait a minute, the counter is not yet 5". So, the robot has not moved, but just turned left. To the left of the robot at this point is the location the robot was previously at (where it moved from on its earlier move), which is obviously not a wall. So, again, the robot turns and the 'moveForward' again says the same thing. After several turns (5, to be exact), the robot will finally move. Five turns to the left should be equivalent to one turn to the left. This leads me to believe that the value of the 'counter' field is not zero when the wall breaks left (when the robot says "oops, that wall to my left is no longer there and I need to turn left and reacquire it". I cannot say without testing what would be the best solution, here. Maybe the 'counter' should restrict all action except for when it is zero (using it to control execution of the entire act method code instead of just the 'moveForward' code). Maybe just forcing a move at the time of a left turn instead of calling the 'moveForward' method that may not cause movement. I, myself, may even go as far as having a String hold characters that represent what action to take when the counter value reaches 5. If the String is empty, determine the next action (two actions characters can be placed in it at the same time for a turn/move combination). I would use "l", "r", "u", "d" and "f" for left, right, up, down, and forward. The first character would determine the action to take and, when taken, it would be removed from the string. Doing it this way, each turn and move would be done individually in different time frames (where in the possible solutions previously given, a turn/move combination would be executed in a single time frame).
Tommy99 Tommy99

2015/2/6

#
Is there a simpler way, without using a String? I'm still stumped on this. Thank you for the reply though, I understand the problem more now.
danpost danpost

2015/2/6

#
You could try one of the possible solutions given in the middle paragraph in my last post.
Tommy99 Tommy99

2015/2/7

#
Oh okay, thanks.
You need to login to post a reply.