5

所以我完成了一个递归画线的程序,它接受一个参数“n”来定义递归的深度。我有 2 个函数,一个绘制相对左侧的线,另一个绘制相对右侧的线。我对其进行了测试,它似乎适用于前 4 个级别,但是要么线条变得太小而无法准确表示,要么我的代码有问题,因为线条之间的中断似乎变得任意。希望有人可以测试我的代码,看看他们是否能找到问题所在。

下图的深度为 10。

编辑:修复了一部分代码,但仍然需要帮助

public class Art
{

//draws the relatively left line
public static void drawLeftLine(double x0, double y0, double x1, double y1)
{
    //define new x coordinate for line
    //double x2 = (1/3.0)*(x1 - x0);

    //color of line
    StdDraw.setPenColor(StdDraw.BLUE);


    //draw line by adding new x coord to original
    StdDraw.line(x0, y0, x1, y1);

}
//draw relatively right line
public static void drawRightLine(double x0, double y0, double x1, double y1)
{
    //define new x coord for line
    //double x2 = (2/3.0)*(x1 - x0);

    //color of line
    StdDraw.setPenColor(StdDraw.BLUE);


    //draw line by adding new x coord to original
    StdDraw.line(x0, y0, x1, y1);

}

public static void cantor(int n, double x0, double y0, double x1, double y1)
{
    if (n == 0)
        return;

    drawLeftLine(x0, y0, x1, y1);
    drawRightLine(x0, y0, x1, y1);

    y0 = y0 - 0.1;
    y1 = y1 - 0.1;



    cantor(n-1, x0, y0, x0 + ((x1 - x0))/3.0, y1); //left
    cantor(n-1, (2.0/ 3) * (x1 - x0) + x0, y0, x1, y1); //right

}

public static void main(String[] args)
{ 
    //change n into integer (depth)
    int n = Integer.parseInt(args[0]);

    //specify inital values for line
    double x0 = 0;
    double y0 = 0.9;
    double x1 = 0.9;
    double y1 = 0.9;



    //recursive function cantor
    cantor(n, x0, y0, x1, y1);

}
}
4

1 回答 1

4

我认为绘图看起来不正确,因为所有漂亮的双精度值都用离散像素近似,导致线段之间出现不必要的重叠(参见底部的编辑)。但是,关于您的代码的一些评论:

1)您不需要drawLeftLineanddrawRightLine方法,因为目前它们正在绘制完全相同的东西。由于在每个步骤中您调用cantor了两次(对于已删除的内部三分之一的每一侧调用一次),cantor因此对于必须绘制的每个线段都有一个调用。因此,我会将所有绘图直接放入该cantor方法中。

2)由于y0y1总是相同的,我会将它们简化为一个y变量。

3)我会将计算新值x0x1值的数学简化为

double third = (x1 - x0) / 3;
cantor(n - 1, x0, x0 + third, y); // left
cantor(n - 1, x1 - third, x1, y); // right

4)而不是每次递减y值,你应该有一个全局变量来决定应该递减的量(否则如果你尝试事情会破坏)。这个值可以设置为。0.1n > 101.0 / n

5)你不需要在每次绘画时都设置笔的颜色。您可以在 main 方法中设置一次。

6)StdDraw已经在您正在绘制的图片周围设置了一个边框,因此无需从您的坐标开始0.9- 您可以使用它1

按照这些建议,代码将如下所示:

private static double yIncrement;

public static void cantor(int n, double x0, double x1, double y) {
  if (n == 0)
    return;

  StdDraw.line(x0, y, x1, y);

  y = y - yIncrement;

  double third = (x1 - x0) / 3;
  cantor(n - 1, x0, x0 + third, y); // left
  cantor(n - 1, x1 - third, x1, y); // right

}

public static void main(String[] args) {
  //change n into integer (depth)
  int n = Integer.parseInt(args[0]);

  // specify inital values for line
  double x0 = 0;
  double x1 = 1;
  double y = 1;

  yIncrement = 1.0 / n;
  StdDraw.setPenColor(Color.BLUE);

  // recursive function cantor
  cantor(n, x0, x1, y);
}

编辑:使用StdDraw画布大小、画布缩放设置和线段端点舍入模式,您可以获得更好的图片(下面的代码生成的图片看起来大部分正确到第 8 级)

private static double yIncrement;

public static void cantor(int n, double x0, double x1, double y) {
  if (n == 0)
    return;

  x0 = Math.ceil(x0);
  x1 = Math.floor(x1);

  StdDraw.line(x0, y, x1, y);

  y = y - yIncrement;

  double third = (x1 - x0) / 3;
  cantor(n - 1, x0, x0 + third, y); // left
  cantor(n - 1, x1 - third, x1, y); // right

}

public static void main(String[] args) {
  // change n into integer (depth)
  int n = Integer.parseInt(args[0]);

  int width = 1920;
  int height = 1080;

  StdDraw.setCanvasSize(width, height);

  // specify inital values for line
  double x0 = 0;
  double x1 = width;
  double y = 1;

  yIncrement = 1.0 / n;
  StdDraw.setPenColor(Color.BLUE);
  StdDraw.setXscale(0, width);

  // recursive function cantor
  cantor(n, x0, x1, y);
}

要以绝对正确的方式将所有内容显示到第 10 级,您需要 3^9 像素(19K 像素)的宽度。对于第 9 级,即 3^8 = 6K。对于 8 级,即 3^7 = 2k,这就是为什么它在 1.9K 像素宽度和整数舍入下看起来几乎正确的原因。

于 2013-10-04T15:18:19.070 回答