Reputation: 107
I have to print a circle (taking as input it's radius, the coordinates of the center of the circle (cx
and cy
), and the character with which it has to be drawn).
I wrote a series of if-blocks for the axes and the circle. They work well if I use them separately, but when I put them in the same method (I have to have only one method) they overlap in an undesirable way.
Note: in case if the character overlaps the axes, the character has priority.
public static void drawCircle(int radius, int cx, int cy, char symbol) {
// this method verifies that there are no negative
// values involved (throws error/exception)
verifyInput(radius, cx, cy);
// set the values for extension of the axes
// (aka how long are they)
int xMax = cx + radius + 1;
int yMax = cy + radius + 1;
for (int j = yMax; j >= 0; j--) {
for (int i = 0; i <= xMax; i++) {
// set of if-block to print the axes
if (i == 0 && j == 0) {
System.out.print('+');
} else if (i == 0) {
if (j == yMax) {
System.out.print('^');
}
if (j != yMax) {
System.out.println('|');
}
} else if (j == 0) {
if (i == xMax) {
System.out.println('>');
}
if (i != xMax) {
System.out.print('-');
}
}
// if block to print the circle
if (onCircle(radius, cx, cy, i, j) == true) {
System.out.print('*');
} else {
System.out.print(' ');
}
}
// I'm not sure if I need to use the print here V
// System.out.println()
}
}
Here is the onCircle
method. It verifies for every i,j
if it is on the outline of the circle to be drawn.
public static boolean onCircle(int radius, int cx, int cy, int x, int y) {
boolean isDrawn = false;
if (Math.pow(radius,2)<=(Math.pow((x-cx),2)+Math.pow((y-cy),2))
&& (Math.pow((x-cx),2)+Math.pow((y-cy),2))<=(Math.pow(radius,2)+1)) {
isDrawn = true;
}
return isDrawn;
}
Here is my output (without the last print statement):
^ |
*** |
* * |
* * |
* * + - - - - -*-*-*- >
Here is my output (with the last print statement):
^
|
***
|
* *
|
* *
|
* *
+ - - - - -*-*-*- >
Here is what I should get:
Upvotes: 3
Views: 1804
Reputation: 3448
jwaddell is right, your code needs only 5 minor updates like this (see comment like // <--
):
public static void drawCircle(int radius, int cx, int cy, char symbol) {
// this method verifies that there are no negative
// values involved (throws error/exception)
verifyInput(radius, cx, cy);
// set the values for extension of the axes
// (aka how long are they)
int xMax = cx + radius + 1;
int yMax = cy + radius + 1;
for (int j = yMax; j >= 0; j--) {
for (int i = 0; i <= xMax; i++) {
// set of if-block to print the axes
if (onCircle(radius, cx, cy, i, j) == true) { // <-- draw circle first
System.out.print(symbol); // <-- use param 'symbol' here
} else if (i == 0 && j == 0) {
System.out.print('+');
} else if (i == 0) {
if (j == yMax) {
System.out.print('^');
}
if (j != yMax) {
System.out.print('|'); // <-- don't print new line here
}
} else if (j == 0) {
if (i == xMax) {
System.out.print('>'); // <-- don't print new line here
}
if (i != xMax) {
System.out.print('-');
}
} else {
System.out.print(' ');
}
}
System.out.println(); // <-- then add new line here
}
}
You can optimize onCircle
like this:
public static boolean onCircle(int radius, int cx, int cy, int x, int y) {
double distance2 = Math.pow((x - cx), 2) + Math.pow((y - cy), 2);
double radius2 = Math.pow(radius, 2);
return radius2 <= distance2 && distance2 <= (radius2 + 1.0d);
}
The result with drawCircle(5, 10, 12, '&');
is as expected:
^
| &&&
| & &
| & &
|
| & &
| & &
| & &
|
| & &
| & &
| &&&
|
|
|
|
|
|
+--------------->
Upvotes: 1
Reputation:
The general Equation of a circle:
In Java it can be implemented like this:
(x-a)*(x-a) + (y-b)*(y-b) == r*r
In the case of an integer coordinate system, it can be rounded like this:
(int) Math.sqrt((x-a)*(x-a) + (y-b)*(y-b)) == r
If the radius r=12
and the center of the circle a=5,b=1
, then the circle and axes look like this:
r=12,a=5,b=1
^y
|
|
| * * * * * * * * *
* * * *
* * | * *
* * | * *
* * | * *
* | *
* | *
* | *
* | *
* | *
* | *
* | *
* | * *
------* ------------+---------------------------------* ---->x
* | *
* | *
* | *
* | *
* | *
* | *
* * | * *
* * | * *
* * | * *
* * * *
| * * * * * * * * *
|
|
|
// radius
int r = 12;
// center of the circle
int a = 5, b = 1;
// whitespace
int s = 3;
// print area
int xMin = a-r-s, xMax = a+r+s;
int yMin = b-r-s, yMax = b+r+s;
// output an ASCII circle and axes
System.out.println("r="+r+",a="+a+",b="+b);
for (int y = yMax; y >= yMin; y--) {
for (int x = xMin; x <= xMax; x++) {
if ((int) Math.sqrt((x-a)*(x-a) + (y-b)*(y-b)) == r) {
// circle
System.out.print("* ");
} else if (x == a && y == b) {
// center of the circle
System.out.print("* ");
} else if (x == 0 && y == 0) {
// origin of coordinates
System.out.print("+-");
} else if (x == 0) {
// ordinate axis - y
System.out.print(y == yMax ? "^y" : "| ");
} else if (y == 0) {
// abscissa axis - x
System.out.print(x == xMax ? ">x" : "--");
} else {
// whitespace
System.out.print(" ");
}
}
// new line
System.out.println();
}
See also:
• Print out an ASCII circle and axes
• Print out an ASCII circle of the specified width
Upvotes: 3
Reputation: 1934
It looks like the formatting issue is that you are sometimes using System.out.println
where you should be using System.out.print
. System.out.println
will end the current line, so it should only be used once per output line. Thus you should just have the single empty System.out.println
statement at the end of the outer (j
) loop, and use System.out.print
throughout the rest of the program.
You will also need to fix the printing of the horizontal axis, as at the moment it will print both the axis and the circle, instead of just the circle.
Upvotes: 2