2013-10-04 7 views
5

Così ho finito un programma che disegna in modo ricorsivo le linee che prendono un argomento "n" per definire la profondità della ricorsione. Ho 2 funzioni, una che disegna la linea relativamente a sinistra e un'altra che disegna quella relativamente giusta. L'ho provato e sembra funzionare per i primi 4 livelli, ma poi le linee diventano troppo piccole per rappresentare con precisione o c'è qualcosa di sbagliato nel mio codice perché le interruzioni tra le righe sembrano diventare arbitrarie. Speravo che qualcuno potesse testare il mio codice e vedere se riuscivano a trovare quale fosse il problema.Controllare il debug del programma

L'immagine seguente è di profondità 10.

EDIT: Risolto un parte del codice, ancora bisogno di aiuto se

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

} 
} 

risposta

4

Penso che il disegno non sembra corretto perché il di il fatto che tutti i buoni valori double vengono approssimati con pixel discreti che causano sovrapposizioni indesiderate tra i segmenti della linea (vedi EDIT in basso). Alcuni commenti sul tuo codice tuttavia:

1) Non sono necessari i metodi drawLeftLine e drawRightLine poiché attualmente stanno disegnando esattamente la stessa cosa. Poiché in ogni fase si chiama due volte cantor (una per ciascun lato del terzo interno eliminato), si ha una chiamata a cantor per ogni segmento di linea che deve essere disegnato. Pertanto, inserisco tutto il disegno direttamente nel metodo cantor.

2) Poiché y0 e y1 sono entrambi sempre uguali, li ridurrei a una singola variabile .

3) vorrei semplificare la matematica per calcolare i nuovi x0 e x1 valori verso il basso per

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

4) Invece di decrementare il valore y da 0.1 ogni volta, si dovrebbe avere una variabile globale che decide il importo con il quale questo dovrebbe essere decrementato (altrimenti se provi a n > 10 le cose si romperanno). Questo valore può essere impostato su 1.0/n.

5) Non è necessario impostare il colore della penna ogni volta che si dipinge. Puoi impostarlo solo una volta nel metodo principale.

6) StdDraw già imposta un bordo attorno all'immagine che si sta disegnando, quindi non è necessario avviare le coordinate da 0.9 - è possibile utilizzare invece 1.

Seguendo questi suggerimenti il ​​codice sarebbe simile a questa:

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

EDIT: Giocando intorno con la dimensione StdDraw tela, le impostazioni di scala tela, e segmento di linea endpoint arrotondamento modalità è possibile avere un quadro leggermente migliore (la codice di seguito produce un quadro che sembra per lo più corretto fino al livello 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); 
} 

per mostrare tutto fino al decimo livello assoluto correttezza si avrebbe bisogno di una larghezza di 3^9 pixel (19k pixel). Per il livello 9 questo è 3^8 = 6K. Per il livello 8 è 3^7 = 2k, che è il motivo per cui sembra quasi corretto con larghezza di 1,9K pixel e arrotondamento intero.

+0

In realtà non sono autorizzato a fare confusione con la dimensione della tela per questo progetto, ma cercherò di implementarlo in pochi minuti. Sembra fantastico, ed è anche bello sapere che probabilmente è un errore grafico. Tu sei l'uomo! Grazie! – user2782981