如何使用递归函数使 Bug 对象移动五次?

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

我正在从 Allen B. Downey "Think Java" 写的书中学习 Java。在第 5 章中,介绍了 GridWorld 的概念,您基本上有一个 10x10 的网格,其中 "actors" 例如 Bug、Rocks 和 Grid 本身,它代表对象。安装代码后,GridWorld GUI 将显示一个包含两个角色的网格,一个 "bug" 和一个 "rock"。

点击演员,会出现一个带有方法的下拉菜单,可以调用该演员。

其中一项作业是通过使用名为 randomBugMath.random(); 编写一个方法,该方法将 Bug 作为参数并将 Bug 的方向设置为 0、90、180 或 270 之一,即北、东、南、西,以相等的概率,然后如果可以的话移动虫子。

下一个作业是修改randomBug取一个整数n并重复n次。

这是我的代码:

/* 
 * 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);

    }


}

我正在尝试使用递归函数重复这个过程五次,所以 Bug 应该移动五次,除非它到达 Grid 的边缘。有时会出现的问题是 Bug 移动超过 5 次,它移动 6 或 10 步,即使我使用条件 n <= 0 限制了它。

我应该在代码中更改或添加什么才能完成作业?

问题是你总是在最后调用 randomBug(x, Math.random(), n-1);。你永远 return 从方法。这是一个无限循环。

要解决这个问题,我会从所有分支中删除 n >= 0 测试,然后将此测试添加到函数的顶部。

if (n < 0) return; // Or n <= 0?

这个 if 测试称为递归函数的基本情况。

首先,你应该让你的代码尽可能简单,尽量把重复的元素分开(你的代码至少有2个)。

其次,当您的 n 达到 0 时,它无法通过所有检查并转到 else 条件。然后它继续朝那个方向前进,直到它不能再前进。我很惊讶你还没有得到 Whosebug。

最后你的代码应该看起来像这样:

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);
}

最后,你不断检查你的随机数是否在两个值之间,在这种特殊情况下不需要这样做:

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

如果第二个 if 语句也大于 .25,则无需检查第二个 if 语句,因为您的第一个检查已经确认它是。

这样好一点吗?我试过了,好像还行...

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

        if (n <= 0) return;

        if (y <= 0.2){
            x.setDirection(0);
        } else if (y <= 0.5){
            x.setDirection(90);
        } else if (y <= 0.8){
            x.setDirection(180);
        } else {
            x.setDirection(270);
        }

        if (x.canMove()) x.move();

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

    }