use*_*981 5 java graphics recursion
所以我完成了一个递归绘制线的程序,它接受一个参数"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);
}
}
Run Code Online (Sandbox Code Playgroud)
我认为绘图看起来不正确,因为所有漂亮的双精度值都用离散像素近似,导致线段之间出现不必要的重叠(请参阅底部的编辑)。然而,关于您的代码的一些评论:
1)您不需要drawLeftLine和drawRightLine方法,因为目前它们正在绘制完全相同的东西。由于在每个步骤中您都会调用cantor两次(删除的内部三分之一的每一侧各一次),因此cantor对于必须绘制的每个线段您都会调用一次。因此,我会将所有绘图直接放入该cantor方法中。
2)由于y0和y1总是相同的,我会将它们减少为一个y变量。
x03)我会将计算新值和x1值的数学简化为
double third = (x1 - x0) / 3;
cantor(n - 1, x0, x0 + third, y); // left
cantor(n - 1, x1 - third, x1, y); // right
Run Code Online (Sandbox Code Playgroud)
4)您应该有一个全局变量来决定应该减少的量,而不是y每次0.1都减少该值(否则,如果您尝试,n > 10事情就会崩溃)。该值只需设置为 即可1.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);
}
Run Code Online (Sandbox Code Playgroud)
编辑:使用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);
}
Run Code Online (Sandbox Code Playgroud)
要绝对正确地显示第十级的所有内容,您需要 3^9 像素(19K 像素)的宽度。对于 9 级,即 3^8 = 6K。对于 8 级,即 3^7 = 2k,这就是为什么它在 1.9K 像素宽度和整数舍入的情况下看起来几乎正确。