/////////////////////////////////////////////////////////////////////// // // blaise.java // // Copyright (c) 1997 by Jeremy Baer // jbaer@cs.washington.edu // http://www.cs.washington.edu/homes/jbaer // // The applet contained in this file implements a tool to visualize // numeric patterns in Pascal's triangle. // // There is nothing particularly mystical about this code -- the // applet itself is incredibly simple. It's what the applet does // that's interesting. // // Permission to study and modify this code for educational purposes // only is hereby granted. No commercial use of this code is // permitted without the express permission of the author. // ////////////////////////////////////////////////////////////////////// import java.awt.*; import java.awt.image.*; import java.applet.*; import java.lang.*; import java.util.*; import BigInt; // from the MIT Scheme project public class blaise extends Applet { int TABLE_SIZE = 0; int TRI_SIZE = 128; /* offscreen image for redrawing the board */ Image offscreenImage; Graphics offscreenGraphics; Vector triangle; BigInt divisor = new BigInt(2); TextField divTF; boolean newDivis = true; /** * Initialize the applet. */ public void init() { int row, col, count = 0; // get the rows parameter String tempStr = getParameter("rows"); try { TRI_SIZE = Integer.parseInt(tempStr); } catch(NumberFormatException ex) {;} // compute the size of the table for(count = 1; count <= TRI_SIZE; count++) TABLE_SIZE += count; count = 0; triangle = new Vector(TABLE_SIZE); /* Build the table of numbers representing Pascal's triangle. Note that the triangle is stored in a linear vector, as we can easily compute offsets into that vector given row and column numbers */ for(row = 0; row < TRI_SIZE; row++) { for(col = 0; col <= row; col++) { /* If we're on the edge, the number is a one */ if(col == 0 || col == row) triangle.addElement(new BigInt(1)); /* otherwise, it is the sum of the two numbers above it in the triangle */ else { int prev1, prev2; prev1 = (count - (row + 1)); prev2 = (count - row); triangle.addElement(BigInt.add((BigInt)triangle.elementAt(prev1), (BigInt)triangle.elementAt(prev2))); } count++; } } /* make the text field and "Set Divisor" button */ setLayout(new BorderLayout()); Panel p = new Panel(); add("South", p); divTF = new TextField("2", 4); p.add(divTF); p.add(new Button("Set Divisor")); } /* * Handle updates */ public void update(Graphics g) { /* init our offscreen image if it hasn't already been done */ if(offscreenImage == null) { offscreenImage = createImage(size().width, size().height); offscreenGraphics = offscreenImage.getGraphics(); } /* if we just entered a new divisor, then we actually have to redraw the thing -- otherwise, just copy it from offscreen */ if(newDivis) { offscreenGraphics.setColor(Color.lightGray); offscreenGraphics.fillRect(0,0,size().width, size().height); painter(offscreenGraphics, g); } else g.drawImage(offscreenImage, 0, 0, null); } public void paint(Graphics g) { /* init our offscreen image if it hasn't already been done */ if(offscreenImage == null) { offscreenImage = createImage(size().width, size().height); offscreenGraphics = offscreenImage.getGraphics(); } /* if we just entered a new divisor, then we actually have to redraw the thing -- otherwise, just copy it from offscreen */ if(newDivis) { offscreenGraphics.setColor(Color.lightGray); offscreenGraphics.fillRect(0,0,size().width, size().height); painter(offscreenGraphics, g); } else g.drawImage(offscreenImage, 0, 0, null); } /** * This actually performs the drawing, on both Graphics objects passed to * it (offscreen and onscreen). */ public void painter(Graphics g, Graphics g2) { int row, col, count = 0; Rectangle drawRect = new Rectangle((TRI_SIZE + 20), 10, 2, 2); newDivis = false; g.setColor(Color.black); g2.setColor(Color.black); /* loop through the rows and columns, drawing each cell */ for(row = 0; row < TRI_SIZE; row++) { drawRect.reshape((TRI_SIZE + 20) - row, 10 + (2 * row), 2, 2); for(col = 0; col <= row; col++) { /* see if it's divisible and set the right color */ if((BigInt.remainder((BigInt)triangle.elementAt(count), divisor)).isZero()) { g.setColor(Color.black); g2.setColor(Color.black); } else { g.setColor(Color.red); g2.setColor(Color.red); } /* draw the cell on both Graphics objects */ g.fillRect(drawRect.x, drawRect.y, drawRect.width, drawRect.height); g2.fillRect(drawRect.x, drawRect.y, drawRect.width, drawRect.height); /* move the drawing rect */ drawRect.translate(2, 0); count++; } } } /* * This handles the user's clicks on the "Set Divisor" button */ public boolean action(Event evt, Object obj) { if ("Set Divisor".equals(obj)) { String divStr = divTF.getText(); Long newDiv = new Long(divStr); long newDiv2 = newDiv.longValue(); divisor = null; divisor = new BigInt(newDiv2); newDivis = true; repaint(); return true; } else { return false; } } public String getAppletInfo() { return "blaise (c) 1997 by Jeremy Baer"; } }