How can I make this tree's angle and depth to be random by using 'random number'?
In the below code JFrame is been used. The intent behind the question is to get the idea of randomizing the angles and the depth, which is passed in the paint method.
public class DrawTreeFrame extends JFrame {
public DrawTreeFrame() {
setSize(800, 700);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
private void drawTree(Graphics g, int x1, int y1, double angle, int depth) {
if(depth==0)
return;
int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 10.0);
int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 10.0);
g.drawLine(x1, y1, x2, y2);
drawTree(g, x2, y2, angle-20, depth-1);
drawTree(g, x2, y2, angle+20, depth-1);
}
#Override
public void paint(Graphics g) {
g.setColor(Color.BLACK);
drawTree(g, 400, 600, -90, 10);
}
public static void main(String[] args) {
new DrawTreeFrame();
}
}
You can use Math.random(). The following code method will give you random numbers in a range;
public int getRandomNumber(int min, int max) {
return (int) ((Math.random() * (max - min)) + min);
}
Ultimately your code should look like this:-
class DrawTreeFrame extends JFrame {
public DrawTreeFrame() {
setSize(800, 700);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
private void drawTree(Graphics g, int x1, int y1, double angle, int depth) {
if(depth==0)
return;
int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 10.0);
int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 10.0);
g.drawLine(x1, y1, x2, y2);
drawTree(g, x2, y2, angle-20, depth-1);
drawTree(g, x2, y2, angle+20, depth-1);
}
#Override
public void paint(Graphics g) {
g.setColor(Color.BLACK);
int x1 = getRandomNumber(100, 400);
int y1 = getRandomNumber(400, 800);
double angle = getRandomNumber(-10, -100);
int depth = getRandomNumber(5, 20);
drawTree(g, x1, y1, angle, depth);
}
public int getRandomNumber(int min, int max) {
return (int) ((Math.random() * (max - min)) + min);
}
public static void main(String[] args) {
new DrawTreeFrame();
}
}
What I'm trying to do here is generate 5 random ovals and rectangles. If I remove
for(MyOval oval : ovals){
oval.draw(g);
}
from the first class, it will display 5 random rectangles. If I remove
for(MyRectangle rectangle : rectangles){
rectangle.draw(g);
}
it will display 5 random ovals. If I remove nothing, it doesn't work. What I'm doing wrong?
DrawPanel Class
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;
public class DrawPanel extends JPanel{
private Random randomNumbers = new Random();
private MyOval[] ovals;
private MyRectangle[] rectangles;
public DrawPanel(){
setBackground(Color.WHITE);
ovals = new MyOval[ 5 + randomNumbers.nextInt(5)];
rectangles = new MyRectangle [ 5 + randomNumbers.nextInt(5)];
for (int count = 0; count <ovals.length; count++){
int x1 = randomNumbers.nextInt(300);
int y1 = randomNumbers.nextInt(300);
int x2 = randomNumbers.nextInt(300);
int y2 = randomNumbers.nextInt(300);
Color color = new Color (randomNumbers.nextInt(256), randomNumbers.nextInt(256), randomNumbers.nextInt(256));
ovals[count] = new MyOval(x1, y1, x2, y2, color);
rectangles[count] = new MyRectangle(x1, y1, x2, y2, color);
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
for(MyRectangle rectangle : rectangles){
rectangle.draw(g);
}
for(MyOval oval : ovals){
oval.draw(g);
}
}
}
Main Class
import javax.swing.JFrame;
public class TestDraw {
public static void main(String[] args) {
DrawPanel panel = new DrawPanel();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(300,300);
application.setVisible(true);
}
}
MyOval Class
import java.awt.Color;
import java.awt.Graphics;
public class MyOval {
private int x1;
private int y1;
private int x2;
private int y2;
private Color myColor;
public MyOval(int x1, int y1, int x2, int y2, Color color){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
myColor = color;
}
public void draw(Graphics g){
g.setColor(myColor);
g.drawOval(x1, y1, x2, y2);
}
}
MyRectangle Class
import java.awt.Color;
import java.awt.Graphics;
public class MyRectangle {
private int x1;
private int y1;
private int x2;
private int y2;
private Color myColor;
public MyRectangle(int x1, int y1, int x2, int y2, Color color){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
myColor = color;
}
public void draw(Graphics g){
g.setColor(myColor);
g.drawRect(x1, y1, x2, y2);
}
}
The problem is that you are allocating two arrays with random length, but then using the length of the first array to iterate through both arrays.
Quote:
ovals = new MyOval[ 5 + randomNumbers.nextInt(5)];
rectangles = new MyRectangle [ 5 + randomNumbers.nextInt(5)];
for (int count = 0; count <ovals.length; count++){
int x1 = randomNumbers.nextInt(300);
int y1 = randomNumbers.nextInt(300);
int x2 = randomNumbers.nextInt(300);
int y2 = randomNumbers.nextInt(300);
Color color = new Color (randomNumbers.nextInt(256), randomNumbers.nextInt(256), randomNumbers.nextInt(256));
ovals[count] = new MyOval(x1, y1, x2, y2, color);
rectangles[count] = new MyRectangle(x1, y1, x2, y2, color);
}
Solution is to either initialize the elements in each array separately up to their length, or if you intended both arrays to be the same length you could choose one random length before you allocate the arrays. Latter fix would be as shown below:
int len = 5 + randomNumbers.nextInt(5);
ovals = new MyOval[ len ];
rectangles = new MyRectangle [ len ];
By doing what Farrukh said, I'll be getting ovals and rectangles that are using the same variables, meaning that they will be within each other. Thanks for your help, I found another way to solve my problem, now it gerenates independent ovals and rectangles
ovals = new MyOval[ 5 + randomNumbers.nextInt(5)];
rectangles = new MyRectangle [ 5 + randomNumbers.nextInt(5)];
for (int count = 0; count <ovals.length; count++){
int x1 = randomNumbers.nextInt(300);
int y1 = randomNumbers.nextInt(300);
int x2 = randomNumbers.nextInt(300);
int y2 = randomNumbers.nextInt(300);
Color color = new Color (randomNumbers.nextInt(256), randomNumbers.nextInt(256), randomNumbers.nextInt(256));
ovals[count] = new MyOval(x1, y1, x2, y2, color);
}
for (int count = 0; count <rectangles.length; count++){
int x1 = randomNumbers.nextInt(300);
int y1 = randomNumbers.nextInt(300);
int x2 = randomNumbers.nextInt(300);
int y2 = randomNumbers.nextInt(300);
Color color = new Color (randomNumbers.nextInt(256), randomNumbers.nextInt(256), randomNumbers.nextInt(256));
rectangles[count] = new MyRectangle(x1, y1, x2, y2, color);
}
How can I find xpoints[] and ypoints[], if I want to draw a polygon with the mouse, using getX() and getY() ?
My code at the moment is:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Poligonos extends Figura{
public void Poligonos (int[] xPoints, int[] yPoints, int nPoints){
//private int[] xPoints = {(x1/2), x1, (x1+(x1/2))} // {(getX()/2), getX(), (getX()+(getX()/2))};
//private int[] yPoints = {( y1 + y1 ), y1 ,( y1 + y1 )};
}
#Override
public void desenha(Graphics g) {
g.setColor(cor);
g.drawPolygon( xPoints, yPoints, 3);
}
#Override
public void setCoordenadas(int x1, int y1, int x2, int y2) {
p.x = Math.min(x1, x2);
p.y = Math.min(y1, y2);
int xPoints[] = {(p.x /2), p.x , ( p.x +( p.x /2))}; // {(getX()/2), getX(), (getX()+(getX()/2))};
int yPoints[] = {( p.y + p.y ), p.y ,( p.y + p.y )};
}
}
And getX() and getY() part is:
#Override
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
}
#Override
public void mouseDragged(MouseEvent e) {
x2 = e.getX();
y2 = e.getY();
r.setCoordenadas(x1, y1, x2, y2);
pEdicao.repaint();
}
How can I make this work? I just want draw a pentagon and a triangle with mouse.
Thanks for your time.
You could make a setup where you do something like
int numCoordinates = /*(get the number of coordinates by getting number of clicks after a certain action, etc.)*/
int[] xCords = new int[numCoordinates];
int[] yCords = new int[numCoordinates];
xCords[index] = e.getX();
yCords[index] = e.getY();
index++;
if(index > numCoordinates){
index = 0;
pEdicao.repaint();
}
I have written program for drawing pythagoras tree fractal. Can anybody see any way of improving it ? Now it is 89 LOC.
import java.awt.*;
import java.util.Scanner;
import javax.swing.*;
public class Main extends JFrame {;
public Main(int n) {
setSize(900, 900);
setTitle("Pythagoras tree");
add(new Draw(n));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Give amount of steps: ");
new Main(sc.nextInt());
}
}
class Draw extends JComponent {
private int height = 800;
private int width = 800;
private int steps;
public Draw(int n) {
steps = n;
Dimension d = new Dimension(width, height);
setMinimumSize(d);
setPreferredSize(d);
setMaximumSize(d);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
g.setColor(Color.black);
int x1, x2, x3, y1, y2, y3;
int base = width/7;
x1 = (width/2)-(base/2);
x2 = (width/2)+(base/2);
x3 = width/2;
y1 = (height-(height/15))-base;
y2 = height-(height/15);
y3 = (height-(height/15))-(base+(base/2));
g.drawPolygon(new int[]{x1, x1, x2, x2, x1}, new int[]{y1, y2, y2, y1, y1}, 5);
int n1 = steps;
if(--n1 > 0){
g.drawPolygon(new int[] {x1, x3, x2}, new int[] {y1, y3, y1}, 3);
paintMore(n1, g, x1, x3, x2, y1, y3, y1);
paintMore(n1, g, x2, x3, x1, y1, y3, y1);
}
}
public void paintMore(int n1, Graphics g, double x1_1, double x2_1, double x3_1, double y1_1, double y2_1, double y3_1){
int x1, x2, x3, y1, y2, y3;
x1 = (int)(x1_1 + (x2_1-x3_1));
x2 = (int)(x2_1 + (x2_1-x3_1));
x3 = (int)(((x2_1 + (x2_1-x3_1)) + ((x2_1-x3_1)/2)) + ((x1_1-x2_1)/2));
y1 = (int)(y1_1 + (y2_1-y3_1));
y2 = (int)(y2_1 + (y2_1-y3_1));
y3 = (int)(((y1_1 + (y2_1-y3_1)) + ((y2_1-y1_1)/2)) + ((y2_1-y3_1)/2));
g.setColor(Color.green);
g.drawPolygon(new int[] {x1, x2, (int)x2_1, x1}, new int[] {y1, y2, (int)y2_1, y1}, 4);
g.drawLine((int)x1, (int)y1, (int)x1_1, (int)y1_1);
g.drawLine((int)x2_1, (int)y2_1, (int)x2, (int)y2);
g.drawLine((int)x1, (int)y1, (int)x2, (int)y2);
if(--n1 > 0){
g.drawLine((int)x1, (int)y1, (int)x3, (int)y3);
g.drawLine((int)x2, (int)y2, (int)x3, (int)y3);
paintMore(n1, g, x1, x3, x2, y1, y3, y2);
paintMore(n1, g, x2, x3, x1, y2, y3, y1);
}
}
}
Use drawPolygon instead of multiply drawLine
Remove the unused method pow,
Clean up your imports
Remove the unnecessary variables h and w
put --n > 0 into a one line
do some reformatting
and there you go, 90 lines (comments still counted):
import java.awt.*;
import java.util.Scanner;
import javax.swing.*;
public class Main extends JFrame {;
public Main(int n) {
setSize(900, 900);
setTitle("Pythagoras tree");
add(new Draw(n));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Give amount of steps: ");
new Main(sc.nextInt());
}
}
class Draw extends JComponent {
private int height = 800;
private int width = 800;
private int steps;
public Draw(int n) {
steps = n;
Dimension d = new Dimension(width, height);
setMinimumSize(d);
setPreferredSize(d);
setMaximumSize(d);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
g.setColor(Color.black);
int x1, x2, x3, y1, y2, y3;
int base = width/7;
x1 = (width/2)-(base/2);
x2 = (width/2)+(base/2);
x3 = width/2;
y1 = (height-(height/15))-base;
y2 = height-(height/15);
y3 = (height-(height/15))-(base+(base/2));
//paint
g.drawPolygon(new int[]{x1, x1, x2, x2, x1}, new int[]{y1, y2, y2, y1, y1}, 5);
int n1 = steps;
if(--n1 > 0){
g.drawPolygon(new int[] {x1, x3, x2}, new int[] {y1, y3, y1}, 3);
paintMore(n1, g, x1, x3, x2, y1, y3, y1);
paintMore(n1, g, x2, x3, x1, y1, y3, y1);
}
}
public void paintMore(int n1, Graphics g, double x1_1, double x2_1, double x3_1, double y1_1, double y2_1, double y3_1){
double x1, x2, x3, y1, y2, y3;
//counting
x1 = x1_1 + (x2_1-x3_1);
x2 = x2_1 + (x2_1-x3_1);
x3 = ((x2_1 + (x2_1-x3_1)) + ((x2_1-x3_1)/2)) + ((x1_1-x2_1)/2);
y1 = y1_1 + (y2_1-y3_1);
y2 = y2_1 + (y2_1-y3_1);
y3 = ((y1_1 + (y2_1-y3_1)) + ((y2_1-y1_1)/2)) + ((y2_1-y3_1)/2);
//paint
g.setColor(Color.green);
g.drawPolygon(new int[] {(int)x1, (int)x2, (int)x2_1, (int)x1},
new int[] {(int)y1, (int)y2, (int)y2_1, (int)y1}, 4);
g.drawLine((int)x1, (int)y1, (int)x1_1, (int)y1_1);
g.drawLine((int)x2_1, (int)y2_1, (int)x2, (int)y2);
g.drawLine((int)x1, (int)y1, (int)x2, (int)y2);
if(--n1 > 0){
g.drawLine((int)x1, (int)y1, (int)x3, (int)y3);
g.drawLine((int)x2, (int)y2, (int)x3, (int)y3);
paintMore(n1, g, x1, x3, x2, y1, y3, y2);
paintMore(n1, g, x2, x3, x1, y2, y3, y1);
}
}
}
Rewrite it in 25 lines of F#? ;-)
replace:
private int pow(int n){
int pow = 2;
for(int i = 1; i < n; i++){
if(n==0){
pow = 1;
}
pow = pow*2;
}
return pow;
}
with
private int pow2(int n) { //Better name, to avoid confusion
return 1 << n;
}
Although I can't see where you use this function.
There are many ways to shorten the code (and the suggestions from Eric and Mihir are a good start), but I would focus on clarity. Variables like x1 and y1 scream for a Point struct to hold these pairs together. You could then pass these points in an array.