// A revision of the GaltonBoard applet // Written by Julian Devlin, 8/97, for the text book // "Introduction to Probability," by Charles M. Grinstead & J. Laurie Snell // A few necessary packages import java.awt.*; import java.applet.Applet; import java.util.Random; // The GaltonBoard applet class public class GaltonBoard extends Applet { Board myboard; // Pins, slots, etc. // UI elements Panel contpanel; Scrollbar pausebar, probbar, rowsbar; Label pauselabel, problabel, rowslabel; //Checkbox soundon; // State variables int screenwidth = 400; int screenheight = 500; // Initialization public void init() { //resize(screenwidth, screenheight); // Make applet correct size setBackground(new Color(255, 255, 255)); // Set color myboard= new Board(this); // Instantiate Board class // Set up UI controls contpanel = new Panel(); contpanel.setLayout(new GridLayout(6, 1, 5, 5)); contpanel.setBackground(new Color(255, 255, 255)); pausebar = new Scrollbar(Scrollbar.HORIZONTAL, 100, 20, 1, 2000); probbar = new Scrollbar(Scrollbar.HORIZONTAL, 50, 20, 0, 100); rowsbar = new Scrollbar(Scrollbar.HORIZONTAL, 10, 20, 1, 30); pauselabel = new Label("Delay - " + String.valueOf(pausebar.getValue()) + " microseconds"); problabel = new Label("Chance of falling right - " + String.valueOf(probbar.getValue()) + "/100"); rowslabel = new Label("Rows of pins - " + String.valueOf(rowsbar.getValue())); //soundon = new Checkbox("Sound", null, false); setLayout( new BorderLayout(5,5)); add("South", contpanel); add("Center", myboard); contpanel.add(pausebar); contpanel.add(pauselabel); contpanel.add(probbar); contpanel.add(problabel); contpanel.add(rowsbar); contpanel.add(rowslabel); //contpanel.add(soundon); myboard.pinrows = rowsbar.getValue(); validate(); //myboard.init(); myboard.start(); // Run board.... } // If it is run as an application, make a window with an applet in it public static void main(String arg[]) { Frame f = new Frame("My Window"); GaltonBoard myGalt = new GaltonBoard(); myGalt.init(); //myGalt.start(); f.setLayout(new GridLayout(1, 1)); // f.resize(myGalt.screenwidth, myGalt.screenheight); f.add(myGalt); f.show(); } public boolean handleEvent(Event evt) { // If user is changing options if(evt.target instanceof Scrollbar) { if (evt.target==pausebar) { myboard.pauselength = ((Scrollbar)evt.target).getValue(); pauselabel.setText("Delay - " + String.valueOf(pausebar.getValue()) + " microseconds"); } if (evt.target==probbar) { myboard.leftprob = (float) ((Scrollbar)evt.target).getValue()/100; problabel.setText("Chance of falling right - " + String.valueOf(probbar.getValue()) + "/100"); } if (evt.target==rowsbar) { myboard.pinrows = ((Scrollbar)evt.target).getValue(); rowslabel.setText("Rows of pins - " + String.valueOf(rowsbar.getValue())); } return true; } // Otherwise, handle as usual return super.handleEvent(evt); } } // Board class - does all the work class Board extends Canvas implements Runnable { // Constants final int NUMBALLS = 100; final int PINSIZE = 4; final int BALLSIZE = 8; final int SIDE = 20; final int HEIGHT = (int) Math.round((Math.sqrt(3)/2)*SIDE); final int DROPCOORD = 20; final int CUTCOORD = 20; // Variables int pinrows; int maxy; int barwidth; int firstcol; int curball = 0; int xpos; int ypos; int oldx, oldy; int slotno; int pauselength = 100; float leftprob = (float) .5; int flatball; //jd- 30 is actuall max pin num int slotballs[] = new int[31]; int oldclipx, oldclipy; Rectangle cliparea; int screenwidth = size().width; // DUPLICATE int screenheight = size().height; Thread runner; Random randGen = new Random(); //AudioClip myclip; boolean isrunning; boolean painted; GaltonBoard mydad; public Board(GaltonBoard parent) { mydad = parent; } public void doinit() { //for (int k=0; k leftprob) xpos -= (SIDE/2); else { xpos += (SIDE/2); slotno++; } ypos += HEIGHT; if (painted==true) { //System.out.println("smallset"); cliparea.x=Math.min(xpos, oldx); cliparea.y=oldy; cliparea.width=Math.max(xpos, oldx) - cliparea.x + BALLSIZE + 1; cliparea.height=ypos - oldy + BALLSIZE + 1; } else { //System.out.println("bigset"); oldclipx = cliparea.x; oldclipy = cliparea.y; cliparea.x = Math.min(Math.min(xpos, oldx), oldclipx); cliparea.y = Math.min(Math.min(oldy, oldclipy), ypos); cliparea.width = (Math.max(Math.max(xpos, oldx), (oldclipx+cliparea.width-(BALLSIZE+1)))-cliparea.x)+BALLSIZE+1; cliparea.height = (Math.max(Math.max(ypos, (oldclipy+cliparea.height-(BALLSIZE+1))), oldy)-cliparea.y)+BALLSIZE+1; } //myclip.play(); painted = false; repaint(); } // Drop the ball into its final slot public void dropSlot() { pause(pauselength); oldy=ypos; ypos = (screenheight - CUTCOORD) - ((slotballs[slotno]+1) * flatball); slotballs[slotno] = slotballs[slotno]+1; if (ypos <= maxy) { flatball=flatball/2; cliparea=new Rectangle(0, 0, screenwidth, screenheight); repaint(); } else { if (painted == true) { //System.out.println("smallset"); cliparea.x = xpos; cliparea.y = oldy; cliparea.width = BALLSIZE+1; cliparea.height = ypos-oldy+BALLSIZE+1; } else { //System.out.println("bigset"); oldclipy = cliparea.y; cliparea.y = Math.min(Math.min(oldy, oldclipy), ypos); cliparea.height = (Math.max(Math.max(ypos, (oldclipy+cliparea.height-(BALLSIZE+1))), oldy)-cliparea.y)+BALLSIZE+1; } } //xpos = screenwidth/2-(BALLSIZE/2); //ypos = (DROPCOORD-(PINSIZE/2)-BALLSIZE+1); painted=false; repaint(); } // Return basic info public String getAppletInfo() { return "This applet was written by Julian Devlin. It simulates a Galton board."; } // Wait a certain amount of time void pause(int time) { try { Thread.sleep(time); } catch (InterruptedException e) { } } }