/*********************************************************** * * The authors Bent Kristiansen, Roy Mitchley, Per E. Heyerdahl * * Centre of Science and Technology * Faculty of Engineering, Oslo College * * spring 1997 * * Permission to use, copy, modify, and distribute this * software and its documentation for NON-COMMERCIAL purposes * and without fee is hereby granted provided that this * copyright notice appears in all copies. * * THE AUTHORS MAKE NO REPRESENTATIONS OR * WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHORS * AND PUBLISHER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED * BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * *************************************************************/ import java.applet.*; import java.awt.*; import java.net.*; /************************************************************ * * class RadixSort * * class RadixSort visualise the radixsort algorithm. * It is an applet that sort 20 random numbers in the * range 0-99. The queues used in the algorithm is * visualised with painted "containers" on a canvas. * How the numbers move is visualised with small boxes * that move on the canvas. * ************************************************************/ public class RadixSort extends Applet { /* init() - initialize the applet */ public void init() { setLayout(new BorderLayout()); resize(578,420); counter = 0; sc = new SortCanvas(); start = new NumberBox[20]; sortFirst = new NumberBox[20]; collecting = new NumberBox[20]; sortSecond = new NumberBox[20]; finish = new NumberBox[20]; q = new Queue[10]; sc.setBackground(new Color(0, 0, 128)); add("Center",sc); gr = new CheckboxGroup(); netscape = new Checkbox(" Netscape", gr, true); explorer = new Checkbox(" Explorer", gr, false); cards = new Panel(); layout = new CardLayout(); cards.setLayout(layout); manual = new CardPanelGrid(11, 1); Label l1 = new Label(" SPEED"); l1.setFont(new Font("TimesRoman", Font.BOLD, 15)); Label l2 = new Label("MOVMENT"); l2.setFont(new Font("TimesRoman", Font.BOLD, 15)); Label l3 = new Label("UTILITIES"); l3.setFont(new Font("TimesRoman", Font.BOLD, 15)); manual.add(l1); manual.add(netscape); manual.add(explorer); manual.add(new Label("")); manual.add(l2); manual.add(new Button("Move")); manual.add(new Button("Auto")); manual.add(new Label("")); manual.add(l3); manual.add(new Button("Help")); manual.add(new Button("Restart")); cards.add("M", manual); automatic = new CardPanelGrid(11,1); automatic.setFont(new Font("Courier", Font.BOLD, 22)); automatic.add(new Label(" A")); automatic.add(new Label(" U")); automatic.add(new Label(" T")); automatic.add(new Label(" O")); automatic.add(new Label(" M")); automatic.add(new Label(" A")); automatic.add(new Label(" T")); automatic.add(new Label(" I")); automatic.add(new Label(" C")); automatic.add(new Label("Please")); automatic.add(new Label("Wait!!")); cards.add("A", automatic); atend = new CardPanelGrid(11,1); atend.add(new Label("")); atend.add(new Label("RadixSort")); atend.add(new Label("Created by")); atend.add(new Label("Kristiansen")); atend.add(new Label("Mitchley")); atend.add(new Label("Heyerdahl")); atend.add(new Label("")); atend.add(new Label("Oslo College")); atend.add(new Label("of Engineering")); atend.add(new Label(" spring 1997")); atend.add(new Label("")); cards.add("E", atend); p = new Panel(); p.setLayout(new BorderLayout()); p.add("Center", cards); add("East", p); makeNumbers(); firstSort(); collect(); secondSort(); collectSorted(); } public boolean handleEvent(Event e) { switch(e.id) { case Event.MOUSE_MOVE: if( e.x > 481 && e.y > 43 && e.y < 83) showStatus("Click here if you are using Netscape Navigator"); else if(e.x > 481 && e.y > 83 && e.y < 125) showStatus("Click here if you are using Microsoft Internet Explorer"); else if(e.x > 481 && e.y > 185 && e.y < 221) showStatus("This button moves the boxes one by one"); else if(e.x > 481 && e.y > 221 && e.y < 257) showStatus("Makes the boxes move automatically - you have to wait to it's done"); else if(e.x > 481 && e.y > 333 && e.y < 369) showStatus("Click here to get help"); else if(e.x > 481 && e.y > 369 && e.y < 406) showStatus("This button restarts the applet"); else showStatus("Click \"Move\" to start, or \"Help\" for more information"); return true; case Event.MOUSE_EXIT: showStatus("Click \"Move\" to start, or \"Help\" for more information"); return true; case Event.KEY_PRESS: switch(e.key) { case 'n': case 'N': Object a = "Netscape"; action(e, a); netscape.setState(true); explorer.setState(false); return true; case 'e': case 'E': Object b = "Explorer"; action(e, b); netscape.setState(false); explorer.setState(true); return true; case 'm': case 'M': action(e, "Move"); return true; case 'a': case 'A': action(e, "Auto"); return true; case 'h': case 'H': action(e, "Help"); return true; case 'r': case 'R': action(e, "Restart"); return true; } } return super.handleEvent(e); } public boolean action(Event evt, Object arg) { if(arg.equals("M")) layout.show(cards, (String)arg); else if(arg.equals("A")) layout.show(cards, (String)arg); else if(arg.equals("E")) layout.show(cards, (String)arg); else if(evt.target.equals(netscape)) { for(int i=0; i<20; i++) { start[i].setSpeed(4); sortFirst[i].setSpeed(4); collecting[i].setSpeed(4); sortSecond[i].setSpeed(4); finish[i].setSpeed(4); shortWait = 900; longWait = 1500; } } else if(evt.target.equals(explorer)) { for(int i=0; i<20; i++) { start[i].setSpeed(6); sortFirst[i].setSpeed(6); collecting[i].setSpeed(6); sortSecond[i].setSpeed(6); finish[i].setSpeed(6); shortWait = 750; longWait = 1500; } } else if(arg.equals("Move")) { if(counter < 20 && counter >= 0) { start[counter].whereToGo(1); start[counter].start(); } if(counter < 40 && counter >= 20) { sortFirst[counter-20].whereToGo(2); sortFirst[counter-20].start(); } else if(sortFirst[19].isAlive()) // can't start collecting before counter--; // before sortFirst is finished if(counter < 60 && counter >= 40) { eraseSortFirstBox(collecting[counter-40].getNumber()); collecting[counter-40].whereToGo(1); collecting[counter-40].start(); } if(counter < 80 && counter >= 60) { sortSecond[counter-60].whereToGo(3); sortSecond[counter-60].start(); } else if(sortSecond[19].isAlive()) // can't start finish before counter--; // before sortSecond is finished if(counter < 100 && counter >= 80) { eraseSortSecondBox(finish[counter-80].getNumber()); finish[counter-80].whereToGo(1); finish[counter-80].start(); } counter++; } else if(arg.equals("Auto")) { Object a = "A"; action(evt, a); while(counter < 100) { if(counter < 20 && counter >= 0) { start[counter].whereToGo(1); start[counter].start(); try{ Thread.sleep(shortWait); } catch(InterruptedException e) {} } if(counter < 40 && counter >= 20) { sortFirst[counter-20].whereToGo(2); sortFirst[counter-20].start(); try{ Thread.sleep(longWait); } catch(InterruptedException e) {} } else if(sortFirst[19].isAlive()) // see above in arg.equals("Move") counter--; if(counter < 60 && counter >= 40) { eraseSortFirstBox(collecting[counter-40].getNumber()); collecting[counter-40].whereToGo(1); collecting[counter-40].start(); try{ Thread.sleep(shortWait); } catch(InterruptedException e) {} } if(counter < 80 && counter >= 60) { sortSecond[counter-60].whereToGo(3); sortSecond[counter-60].start(); try{ Thread.sleep(longWait); } catch(InterruptedException e) {} } else if(sortSecond[19].isAlive()) // see above in arg.equals("Move") counter--; if(counter < 100 && counter >= 80) { eraseSortSecondBox(finish[counter-80].getNumber()); finish[counter-80].whereToGo(1); finish[counter-80].start(); try{ Thread.sleep(shortWait); } catch(InterruptedException e) {} } counter++; } a = "E"; action(evt, a); try{ Thread.sleep(3000); } catch(InterruptedException e) {} a = "M"; action(evt, a); } else if(arg.equals("Help")) { try { AppletContext c = getAppletContext(); URL u = new URL(getDocumentBase(), "help.html"); // help file c.showDocument(u, "main"); }catch(MalformedURLException e); } else if(arg.equals("Restart")) { try { AppletContext c = getAppletContext(); URL u = new URL(getDocumentBase(), "restart.html"); // starts the applet c.showDocument(u, "main"); }catch(MalformedURLException e); } else return false; return true; } /* makeNumbers() - generate numbers and set target co-ordinates */ public void makeNumbers() { RandomIntGenerator random = new RandomIntGenerator(0,99); for(int i=0; i<20; i++) { start[i] = new NumberBox(random.draw(),sc); for(int j=0; j xPoint) startX = startX - 2; if(startX < xPoint) startX = startX + 2; if(startX == xPoint) startY = startY + 1; g.setColor(Color.yellow); g.drawRect(startX+1, startY+1, 22, 14); drawNumber(g); g.dispose(); } /* drawNumber(Graphics) - draw number in a digital style. We use this because it makes the applet faster (instead of drawString())*/ public void drawNumber(Graphics g) { int x = startX+1; int y = startY+1; int num = number; int hold = -1; if(number >= 10) { num = number/10; hold = number%10; } if(number >= 10) // num must be in the leftmost position { if(num==0 || num==4 || num==5 || num==6 || num==8 || num==9) g.drawLine(x+4, y+3, x+4, y+6); if(num==0 || num==2 || num==6 || num==8) g.drawLine(x+4, y+8, x+4, y+11); if(num==0 || num==2 || num==3 || num==5 || num==6 || num==7 || num==8 || num==9) g.drawLine(x+5, y+2, x+8, y+2); if(num==2 || num==3 || num==4 || num==5 || num==6 || num==8 || num==9) g.drawLine(x+5, y+7, x+8, y+7); if(num==0 || num==2 || num==3 || num==5 || num==6 || num==8 || num==9) g.drawLine(x+5, y+12, x+8, y+12); if(num==0 || num==1 || num==2 || num==3 || num==4 || num==7 || num==8 || num==9) g.drawLine(x+9, y+3, x+9, y+6); if(num==0 || num==1 || num==3 || num==4 || num==5 || num==6 || num==7 || num==8 || num==9) g.drawLine(x+9, y+8, x+9, y+11); } if(hold != -1) // hold must be in the rightmost position { if(hold==0 || hold==4 || hold==5 || hold==6 || hold==8 || hold==9) g.drawLine(x+13, y+3, x+13, y+6); if(hold==0 || hold==2 || hold==6 || hold==8) g.drawLine(x+13, y+8, x+13, y+11); if(hold==0 || hold==2 || hold==3 || hold==5 || hold==6 || hold==7 || hold==8 || hold==9) g.drawLine(x+14, y+2, x+17, y+2); if(hold==2 || hold==3 || hold==4 || hold==5 || hold==6 || hold==8 || hold==9) g.drawLine(x+14, y+7, x+17, y+7); if(hold==0 || hold==2 || hold==3 || hold==5 || hold==6 || hold==8 || hold==9) g.drawLine(x+14, y+12, x+17, y+12); if(hold==0 || hold==1 || hold==2 || hold==3 || hold==4 || hold==7 || hold==8 || hold==9) g.drawLine(x+18, y+3, x+18, y+6); if(hold==0 || hold==1 || hold==3 || hold==4 || hold==5 || hold==6 || hold==7 || hold==8 || hold==9) g.drawLine(x+18, y+8, x+18, y+11); } if(number < 10) // if number are smaller than 10 it must be in center { if(num==0 || num==4 || num==5 || num==6 || num==8 || num==9) g.drawLine(x+9, y+3, x+9, y+6); if(num==0 || num==2 || num==6 || num==8) g.drawLine(x+9, y+8, x+9, y+11); if(num==0 || num==2 || num==3 || num==5 || num==6 || num==7 || num==8 || num==9) g.drawLine(x+10, y+2, x+13, y+2); if(num==2 || num==3 || num==4 || num==5 || num==6 || num==8 || num==9) g.drawLine(x+10, y+7, x+13, y+7); if(num==0 || num==2 || num==3 || num==5 || num==6 || num==8 || num==9) g.drawLine(x+10, y+12, x+13, y+12); if(num==0 || num==1 || num==2 || num==3 || num==4 || num==7 || num==8 || num==9) g.drawLine(x+14, y+3, x+14, y+6); if(num==0 || num==1 || num==3 || num==4 || num==5 || num==6 || num==7 || num==8 || num==9) g.drawLine(x+14, y+8, x+14, y+11); } } /* run() - control the movement to the box. Give the box the right speed and stops it on the given co-ordinates*/ public void run() { if(where == 1) { while(startX > xPoint) { moveToLine(); try{ sleep(sleepTime); } catch(InterruptedException e) {} } } if(where == 2) { while(startY != 16) { moveToSort(1); try{ sleep(sleepTime); } catch(InterruptedException e) {} } while(startX != xPoint || startY != yPoint) { moveToBox(); try{ sleep(sleepTime); } catch(InterruptedException e) {} } } if(where == 3) { while(startY != 216) { moveToSort(2); try{ sleep(sleepTime); } catch(InterruptedException e) {} } while(startX != xPoint || startY != yPoint) { moveToBox(); try{ sleep(sleepTime); } catch(InterruptedException e) {} } } } /* Instance variables */ private int where; private int sleepTime = 4; private int number; private int xPoint = 0; private int yPoint = 0; private int startX = 456; private int startY = 0; private SortCanvas background; } /************************************************************ * * class CardPanelGrid * * class CardPanelGrid implements a panel with GridLayout * ************************************************************/ class CardPanelGrid extends Panel { /* CardPanelGrid(int,int) - constructor that sets GridLayout */ CardPanelGrid(int hight, int width) { setLayout(new GridLayout(hight, width)); } } /************************************************************ * * class Queue * * class Queue implements a queue structure for integers. * The size is fixed to 10. * *************************************************************/ class Queue { /* Queue() - constructor that make an integer array of size 10 */ public Queue() { length = 10; queue = new int[length]; last = 0; } /* set(int) - add an new element to the array */ public void set(int y) { queue[last] = y; last++; } /* get() - removes an element in queue fashion, and returns it */ public int get() { int hold = queue[0]; for(int i=1;i high) r = high; return r; } /** * test stub for the class */ public static void main(String[] args) { RandomIntGenerator r1 = new RandomIntGenerator(1, 10); RandomIntGenerator r2 = new RandomIntGenerator(0, 1); int i; for (i = 1; i <= 100; i++) System.out.println(r1.draw() + " " + r2.draw()); } private static double nextRandom() { int pos = (int)(java.lang.Math.random() * BUFFER_SIZE); if (pos == BUFFER_SIZE) pos = BUFFER_SIZE - 1; double r = buffer[pos]; buffer[pos] = java.lang.Math.random(); return r; } private static final int BUFFER_SIZE = 101; private static double[] buffer = new double[BUFFER_SIZE]; static { int i; for (i = 0; i < BUFFER_SIZE; i++) buffer[i] = java.lang.Math.random(); } private int low; private int high; }