javarecursiongridworld

How to make Bug object move five times using recursive function?


I am learning Java from the book written by Allen B. Downey, "Think Java". In chapter 5, it is being introduced the notion of GridWorld where you basically have a grid 10x10 with "actors" such as a Bug, a Rocks and Grid itself, which represents objects. When the code is installed, the GridWorld GUI will show a grid containing two actors, a "bug" and a "rock".

enter image description here

By clicking on the actor, there is a drop-down menu with methods, which can be called upon that actor.

enter image description here

One of the assignments is to write a method, by using Math.random(); named randomBug that takes a Bug as a parameter and sets the Bug's direction to one of 0, 90, 180 or 270, that is North, East, South, West, with equal probability, and then moves the bug if it can.

Next assignment is to modify randomBug to take an integer n and repeat n times.

This is my code:

/* 
 * AP(r) Computer Science GridWorld Case Study:
 * Copyright(c) 2005-2006 Cay S. Horstmann (http://horstmann.com)
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * @author Cay Horstmann
 */

import info.gridworld.actor.ActorWorld;
import info.gridworld.actor.Bug;
import info.gridworld.actor.Rock;

/**
 * This class runs a world that contains a bug and a rock, added at random
 * locations. Click on empty locations to add additional actors. Click on
 * populated locations to invoke methods on their occupants. <br />
 * To build your own worlds, define your own actors and a runner class. See the
 * BoxBugRunner (in the boxBug folder) for an example. <br />
 * This class is not tested on the AP CS A and AB exams.
 */

public class BugRunner
{
    public static void main(String[] args)
    {
        ActorWorld world = new ActorWorld();
        Bug redbug = new Bug();
        world.add(redbug);
        System.out.println(redbug.getLocation());
        world.show();

        randomBug(redbug, Math.random(), 5);
    }

    public static void randomBug(Bug x, double y, int n){

        if (y <= 0.2 && n >= 0){
            x.setDirection(0);
            if (x.canMove()) x.move();
        } else if (y >= 0.3 && y <= 0.5 && n >= 0){
            x.setDirection(90);
            if (x.canMove()) x.move();
        } else if (y >= 0.6 && y <= 0.8 && n >= 0){
            x.setDirection(180);
            if (x.canMove()) x.move();
        } else {
            x.setDirection(270);
            if (x.canMove()) x.move();
        }

        randomBug(x, Math.random(), n-1);

    }


}

I am trying to use recursive function to repeat the process five times, so the Bug should move five times, unless it reaches the edge of the Grid. The problem that sometimes occurs is that the Bug moves more then 5 times, it makes 6 or 10 steps, even though I limited it by using condition n <= 0.

What should I change or add in my code so that I can accomplish assignment ?


Solution

  • First of all, you should keep your code as simple as possible, try to separate repeating elements as much as possible (your code has at least 2).

    Second, when your n reaches 0 it fails all checks and moves on to the else condition. Then it keeps going in that direction until it can't anymore. I'm surprised you haven't gotten a stackoverflow yet.

    in the end your code should look a bit like this:

    void randomBug(Bug x, double y, int n)
    {
        if( n <= 0 ) //separated repeated use of requirement
            return;
    
        if( [...] )
            x.setDirection( ... );
        else if ( [...] )
            x.setDirection( ... );
        [ more else ifs as needed ]
    
        if( x.canMove() ) //separated repeated use of action
            x.move();
    
        randomBug(x, Math.random(), n-1);
    }
    

    Lastly, you keep checking if your random is between two values, that is not needed in this particular case:

    if( y <= .25 )
        // do if smaller than .25
    else if( y <= .5 ) //no need to check inbetween
        // do if smaller than .5
    

    there is no need to check in the second if statement if it is also larger than .25 since your first check already confirmed that it is.