// galton.java - jpq - 09/01/03 import java.awt.event.* ; import java.awt.* ; import java.applet.* ; import java.util.* ; public class galton extends java.applet.Applet { controles C ; dessin D ; private int getparmi (String s, int n) { int nn = n ; s = getParameter (s) ; if (s != null) { try { nn = Integer.parseInt (s) ; } catch (NumberFormatException nfe) { } if (nn <= 0) nn = n ; } return nn ; } public void init () { setLayout (new BorderLayout ()) ; int nclous = getparmi ("nclous", 1) ; int nb = getparmi ("nbilles", 1) ; int dt = getparmi ("dt", 0) ; D = new dessin (nclous, dt, nb) ; C = new controles (D) ; D.C = C ; add (C, BorderLayout.NORTH) ; add (D, BorderLayout.CENTER) ; } public void destroy () { remove (D) ; remove (C) ; } public String getAppletInfo () { return "galton par j.-p. Quelen" ; } //////////////////////////////////////////////////////////////////////////////// protected class dessin extends Canvas { int nclous, n, dt, boucle ; int L, H, Ls2, Hs4, Hb, Hb1 ; Random rnd ; int [] classes ; controles C ; gtab gt ; Image img ; Graphics g ; public dessin (int nclous, int dt, int n) { this.nclous = nclous ; this.dt = dt ; this.n = n ; classes = new int [nclous + 1] ; gt = new gtab () ; gt.maj (classes.length, classes) ; rnd = new Random () ; } // dessin de l'entonnoir private void ent (Graphics g) { g.setColor (Color.white) ; g.fillRect (1, 1, L, Hs4 - 10) ; g.setColor (Color.black) ; g.drawLine (Ls2 - Hs4, 1, Ls2 - 10, Hs4 - 10) ; g.drawLine (Ls2 + 10, Hs4 - 10, Ls2 + Hs4, 1) ; g.setColor (Color.blue) ; for (int i = 0 ; i < n ; i ++) { int x = (int)(rnd.nextDouble () * (Math.max (0, Hs4 - 15))) ; int y = (int)(rnd.nextDouble () * (Math.max (0, Hs4 - x - 15))) ; x *= (int)(rnd.nextDouble () * 2) * 2 - 1 ; g.fillOval (Ls2 + x, y, 7, 7) ; } g.setColor (Color.black) ; g.drawLine (0, 0, L, 0) ; } public void update (Graphics g) { paint (g) ; } public void paint (Graphics g) { // if (img == null) { L = getSize().width ; H = getSize().height ; // img = createImage (L, H) ; // g = img.getGraphics () ; L -= 2 ; H -= 2 ; Ls2 = L / 2 ; Hs4 = H / 4 ; Hb = H - 50 ; } g.setColor (Color.black) ; g.drawRect (0, 0, L + 1, H + 1) ; g.setColor (Color.white) ; g.fillRect (1, 1, L, H) ; // dessin de l'entonnoir ent (g) ; // dessin des clous g.setColor (Color.green) ; int pas = (Hb - Hs4) / nclous ; int dec = 0 ; int x = Ls2 - 2 ; int x1 = x ; int y = Hs4 - 2 ; for (int i = 0 ; i < nclous ; i ++) { while (x1 - 3 - dec > 0) { g.fillOval (x, y, 5, 5) ; g.fillOval (x1, y, 5, 5) ; x += pas ; x1 -= pas ; } y += pas ; if (dec == 0) dec = pas / 2 ; else dec = 0 ; x = Ls2 - 2 + dec ; x1 = x ; } // dessin des bacs Hb1 = y ; g.setColor (Color.black) ; g.drawLine (1, H, L, H) ; int dec1 = 0 ; if (dec == 0) dec1 = pas / 2 ; x = Ls2 + dec1 ; x1 = x ; int ind = nclous / 2 ; int ind1 = ind ; while (x1 + pas > 0) { g.setColor (Color.black) ; g.drawLine (x, H, x, Hb1) ; g.drawLine (x1, H, x1, Hb1) ; g.setColor (Color.blue) ; if ((ind >= 0) && (ind < classes.length)) { int ci = classes [ind] ; if (ci > 0) g.fillRect (x - pas, H - ci, pas, ci) ; } if ((ind1 >= 0) && (ind1 < classes.length)) { int ci = classes [ind1] ; if (ci > 0) g.fillRect (x1 - pas, H - ci, pas, ci) ; } x += pas ; x1 -= pas ; ind ++ ; ind1 -- ; } // g1.drawImage (img, 0, 0, this) ; // dessin de la bille qui tombe while (boucle > 0) { boucle -- ; n -- ; ent (g) ; C.tn.setText (Integer.toString (n)) ; dec = 0 ; int xp = 10000 ; int yp = 10000 ; x = Ls2 - 3 ; y = Hs4 - pas / 2 - 3 ; ind = 0 ; for (int i = 0 ; i < nclous ; i ++) { boolean brnd = (rnd.nextDouble () >= 0.5) ; if (brnd) x += pas / 2 ; else x -= pas / 2 ; if (brnd) ind ++ ; for (int k = 0 ; k < pas ; k ++) { g.setColor (Color.white) ; g.fillOval (xp, yp, 7, 7) ; g.setColor (Color.blue) ; g.fillOval (x, y, 7, 7) ; // g1.drawImage (img, 0, 0, this) ; xp = x ; yp = y ++ ; if (dt > 0) { try { Thread.sleep (dt); } catch (InterruptedException e) {} } } if (i == 0) { g.setColor (Color.black) ; g.drawLine (Ls2 - Hs4, 1, Ls2 - 10, Hs4 - 10) ; g.drawLine (Ls2 + 10, Hs4 - 10, Ls2 + Hs4, 1) ; // g1.drawImage (img, 0, 0, this) ; } } g.setColor (Color.white) ; g.fillOval (xp, yp, 7, 7) ; if ((ind >= 0) && (ind < classes.length)) classes [ind] ++ ; x = Ls2 + dec1 ; x1 = x ; ind = nclous / 2 ; ind1 = ind ; while (x1 + pas > 0) { g.setColor (Color.black) ; g.drawLine (x, H, x, Hb1) ; g.drawLine (x1, H, x1, Hb1) ; g.setColor (Color.blue) ; if ((ind >= 0) && (ind < classes.length)) { int ci = classes [ind] ; if (ci > 0) g.fillRect (x - pas, H - ci, pas, ci) ; } if ((ind1 >= 0) && (ind1 < classes.length)) { int ci = classes [ind1] ; if (ci > 0) g.fillRect (x1 - pas, H - ci, pas, ci) ; } x += pas ; x1 -= pas ; ind ++ ; ind1 -- ; } // g1.drawImage (img, 0, 0, this) ; // gt.maj (nclous + 1, classes) ; } } } //////////////////////////////////////////////////////////////////////////////// protected class controles extends Panel implements ActionListener { dessin D ; TextField tn, tdt, tnclous ; Button ok, plus, etoile ; Font f ; private Label ajoutlbl (String s) { Label l = new Label (s) ; l.setBackground (Color.lightGray) ; l.setFont (f) ; return l ; } private TextField ajouttf (int i, int j) { TextField T = new TextField (Integer.toString (i), j) ; T.setFont (f) ; return T ; } private Button ajoutb (String s) { Button b = new Button (s) ; b.addActionListener (this) ; b.setFont (f) ; return b ; } public controles (dessin D) { this.D = D ; f = new Font ("Arial", Font.PLAIN, 10) ; setBackground (Color.lightGray) ; setLayout (new GridLayout(2, 1)) ; Panel p = new Panel () ; add (p) ; p.add (ajoutlbl ("clous :")) ; p.add (tnclous = ajouttf (D.nclous, 2)) ; p.add (ok = ajoutb ("RAZ")) ; p = new Panel () ; add (p) ; p.add (ajoutlbl ("dt :")) ; p.add (tdt = ajouttf (D.dt, 2)) ; p.add (ajoutlbl ("billes :")) ; p.add (tn = ajouttf (D.n, 3)) ; p.add (plus = ajoutb ("+")) ; p.add (etoile = ajoutb ("*")) ; } private int maj (TextField T, int n) { try { n = Integer.parseInt (T.getText ()) ; } catch (NumberFormatException nfe) { } if (n <= 0) n = 1 ; return n ; } public void actionPerformed (ActionEvent e) { Object obj = e.getSource () ; if (( obj == ok) || (obj == plus) || (obj == etoile)) { int n = maj (tn, D.n) ; if (n >= 0) D.n = n ; tn.setText (Integer.toString (D.n)) ; try { D.dt = Integer.parseInt (tdt.getText ()) ; } catch (NumberFormatException nfe) { } tdt.setText (Integer.toString (D.dt)) ; if (obj == ok) { int nclous = maj (tnclous, D.nclous) ; if (nclous > 0) D.nclous = nclous ; if (D.classes.length < nclous + 1) D.classes = new int [nclous + 1] ; else for (int i = 0 ; i < D.classes.length ; i ++) D.classes [i] = 0 ; D.gt.maj (D.nclous + 1, D.classes) ; } else if (obj == plus) D.boucle = 1 ; else D.boucle = D.n ; tnclous.setText (Integer.toString (D.nclous)) ; tdt.setText (Integer.toString (D.dt)) ; D.repaint () ; } } } } //////////////////////////////////////////////////////////////////////////////// class gtab { static boolean change ; static int dim ; static int [] tableau ; static public void maj (int d, int [] tab) { dim = d ; tableau = tab ; change = true ; } }