
import java.awt.*;

public class RandomMosaicWalkApplet extends java.applet.Applet implements Runnable {

         /*
             Applet shows a window full of randomly colored
             squares.  A "disturbance" moves randomly around
             in the window, randomly changing the color of
             each square that it visits.  Depneds on the class
             MosaicCanvas.
         */
                
   int ROWS = 10;    // number of rows of squares; can be reset by applet param named "rows"
   int COLUMNS = 20; // number of colums of squares; can be reset by applet param named "columns"

   int currentRow;       // row currently containing "disturbance"
   int currentColumn;    // column currently containing "disturbance"
   MosaicCanvas mosaic;  // the actual mosaic of colored squares

   Thread runner = null; // thread for running the moving disturbance animation
   boolean suspended;    // set to true when applet is suspended
   boolean finished;     // set to true when applet is destroyed
   
   public void init() {
      setLayout(new BorderLayout());
      String param;
      param = getParameter("rows");
      if (param != null) {
         try {
            ROWS = Integer.parseInt(param);
         }
         catch (NumberFormatException e) {
         }
      }
      param = getParameter("columns");
      if (param != null) {
         try {
            COLUMNS = Integer.parseInt(param);
         }
         catch (NumberFormatException e) {
         }
      }
      mosaic = new MosaicCanvas(ROWS,COLUMNS);
      add("Center",mosaic);
   }
   
   synchronized public void start() {
      suspended = false;
      if (runner == null || !runner.isAlive()) {
         runner = new Thread(this);
         runner.start();
      }
      else
         notify();
   }
   
   synchronized public void stop() {
      suspended = true;
   }
   
  synchronized public void destroy() {
      finished = true;
      runner = null;
   }
   
   
   public void run() {
      currentRow = ROWS / 2;
      currentColumn = COLUMNS / 2;
      fillWithRandomColors();
      while (true) {
         synchronized(this) {
            while (suspended && ! finished)
               try {
                  wait();
               }
               catch (InterruptedException e) {
               }
            if (finished)
               break;
         }
         changeToRandomColor(currentRow,currentColumn);
         randomMove();
         mosaic.delay(20);
      }
   }
   
   void fillWithRandomColors() {
        // fill every square, in each row and column,
        // with a random color
        for (int row=0; row < ROWS; row++) {
           for (int column=0; column < COLUMNS; column++) {
              changeToRandomColor(row, column);  
           }
        }
   }  // end of fillWithRandomColors()
   
   void changeToRandomColor(int rowNum, int colNum) {
        // change the square in row number rowNum and
        // column number colNum to a random color.
        int red = (int)(256*Math.random());    // choose random levels in range
        int green = (int)(256*Math.random());  //     0.0 to 1.0 for red, green, 
        int blue = (int)(256*Math.random());   //     and blue color components
        mosaic.setColor(rowNum,colNum,red,green,blue);  
    }  // end of changeToRandomColor()
    
    void randomMove() {
        // randomly move the disturbance in one of
        // four possible directions: up, down, left, or right;
        // if this moves the disturbance outside the window,
        // then move it to the opposit edge of the window.
        int directionNum = (int)(4*Math.random());
             // direction num is randomly set to 0, 1, 2, or 3
        switch (directionNum) {
           case 0:  // move up 
              currentRow--;
              if (currentRow < 0)
                  currentRow = ROWS - 1;
              break;
           case 1:  // move right
              currentColumn++;
              if (currentColumn >= COLUMNS)
                currentColumn = 0;
              break; 
           case 2:  // move down
              currentRow ++;
              if (currentRow >= ROWS)
                  currentRow = 0;
              break;
           case 3:  
              currentColumn--;
              if (currentColumn < 0)
                  currentColumn = COLUMNS - 1;
              break; 
        }
    }  // end of randomMove()
    
} // end of class
